Scripts that run inside WildTrax. The Python runtime ships with the app; nothing to install. To control WildTrax from another machine, use wildtrax_client instead.
from wildtrax import RecordingEngine, transport, metadata
print(RecordingEngine.isRecording)
metadata.scene("SC07")
transport.record()
| Folder | ~/Library/Application Support/WildTrax 2027/scripts/ |
| Files | Every .py file in the folder appears in WildTrax's script list |
| Output | print() goes to the Script Log panel |
| Thread | Scripts run on the UI thread. Use QTimer for anything long-running. |
| Errors | Exceptions are logged; they don't crash WildTrax |
| Access | Scripts can do anything a normal program on your Mac can. Only run ones you trust. |
Properties are read-only and always current. wildtrax.describe() prints everything available.
| Property | Signal |
|---|---|
isRecording |
isRecordingChanged |
timeCode |
doneReadingBuffer |
recordingTimeCode |
doneReadingBuffer |
freeRunning |
doneReadingBuffer |
isPostRolling |
isPostRollingChanged |
isFinalizing |
isFinalizingChanged |
finalizingTake |
isFinalizingChanged |
recordingDropped |
recordingDroppedChanged |
statusBarMessage |
statusBarMessageChanged |
postRollEnabled |
postRollEnabledChanged |
postRollSeconds |
postRollSecondsChanged |
autoAdvanceTake |
autoAdvanceTakeChanged |
| Property | Signal |
|---|---|
currentProjectPath |
currentProjectPathChanged |
takeNamePattern |
takeNamePatternChanged |
syncPointType |
syncPointTypeChanged |
ltcOffsetMs |
ltcOffsetChanged |
falseStartFolder |
falseStartFolderChanged |
falseStartSuffix |
falseStartSuffixChanged |
Methods: getRecentFiles() getLtcOffsetTimecode() msToTimecode(ms)
| Property | Signal |
|---|---|
trackCount |
tracksChanged |
globalMonitor |
globalMonitorChanged |
currentLTCChannel |
currentLTCChannelChanged |
Methods: rowCount() getLTCInputChannelNames()
| Property | Signal |
|---|---|
currentTimeSource |
currentTimeSourceChanged |
Methods: currentTimeSourceName() currentFrameRate() fps() isDropFrame() frameRates() timeSources()
RecordingEngine.isRecordingChanged.connect(lambda: print(RecordingEngine.isRecording))
.disconnect(fn) to stop. RecordingEngine.signal_for("timeCode") returns a property's signal name.
Same command path as OSC and HTTP. Indices are 1-based. Raises CommandError if WildTrax refuses the command.
| Module | Calls |
|---|---|
transport |
record() stop() false_start() false_start_confirmed() |
tracks |
arm(i, value=True) mute(i, value=True) monitor(i, value=True) pan(i, pan) name(i, name) add() remove(i) set_count(n) |
metadata |
project(v) scene(v) slate(v) take(v) roll(v) note(v) add_marker() reset_next_to_default() |
soundboard |
play(pad) stop(pad) set_title(pad, title) |
playlist |
play() stop() set_loop(value=True) set_current_index(i) |
raw |
send(action, **args) — any other action, args named as in the HTTP API bodies, e.g. raw.send("soundboardSetPadColor", padIndex=1, color="#ff0000") |
pan: 0 left · 1 right · 2 center.
menu.py in the scripts folder runs at launch.
from wildtrax import menu
menu.add_command("Timecode Window", open_timecode_window)
menu.add_command("Tools/RMS vs Peak", open_rms_tool) # "/" makes a submenu
Restart WildTrax to pick up changes. WILDTRAX_PATH (colon-separated) adds more folders to search for menu.py.
PySide6 is included, and scripts share WildTrax's Qt application.
from PySide6.QtWidgets import QDialog, QVBoxLayout, QLabel
from wildtrax import RecordingEngine
class Timecode(QDialog):
def __init__(self):
super().__init__()
self.label = QLabel(RecordingEngine.timeCode)
QVBoxLayout(self).addWidget(self.label)
RecordingEngine.doneReadingBuffer.connect(
lambda: self.label.setText(RecordingEngine.timeCode))
win = Timecode()
win.show() # keep a reference; .exec() blocks WildTrax
A script can be a WildTrax panel instead of a window: it docks, tears out and saves with a project like any panel. Add PANEL = True, build a QWidget, and register it with wildtrax.panel. Header buttons are wildtrax.ToolbarButton.
PANEL = True # lists the script in the Toolkit as a panel
ICON = "radio-tower" # a bundled icon name, an emoji, or an image file
from PySide6.QtWidgets import QWidget, QVBoxLayout, QPlainTextEdit
import wildtrax
class Notes(QWidget):
def __init__(self):
super().__init__()
self.text = QPlainTextEdit()
QVBoxLayout(self).addWidget(self.text)
# Buttons in the panel's header, drawn like every other panel's.
self.toolbar = [
wildtrax.ToolbarButton("eraser", "Clear", on_click=self.text.clear),
]
wildtrax.panel(Notes) # a class, not an instance
| Showing it | Running the script opens its panel beside the frame you're in, or rebuilds it where it's already open |
| One per showing | Each place the panel shows gets its own widget from the class |
ToolbarButton |
ToolbarButton(icon, tooltip="", on_click=None, checkable=False, checked=False, enabled=True). Set enabled, checked, icon or tooltip any time and the header follows |
WildTrax comes with a few Python tools in the Toolkit. Here is one of them in full: a big live timecode display that turns red while recording. Save it to your scripts folder as timecode_slate.py, and it appears in the Toolkit.
"""A big live timecode display that turns red while recording.
Doc's Mini Timecode Slate. Open it as a panel, tear it out onto a second
screen, or point a camera at it.
What this example shows:
- reading live engine state (RecordingEngine.timeCode, .isRecording)
- reacting to engine signals instead of polling
- a script panel: a plain PySide widget that WildTrax shows as a panel
"""
# This line makes the script a panel; WildTrax reads it without running it.
PANEL = True
# The Toolkit tile icon: a bundled icon name, an emoji or an image file.
ICON = "clapperboard"
from PySide6.QtCore import Qt
from PySide6.QtGui import QFont
from PySide6.QtWidgets import QLabel, QVBoxLayout, QWidget
from wildtrax import RecordingEngine, TimeConfig
import wildtrax
REC_COLOR = "#e5484d"
class TimecodeSlate(QWidget):
def __init__(self):
super().__init__()
self.timecode = QLabel(alignment=Qt.AlignCenter)
font = QFont("Menlo")
font.setStyleHint(QFont.Monospace)
font.setBold(True)
self.timecode.setFont(font)
self.status = QLabel(alignment=Qt.AlignCenter)
layout = QVBoxLayout(self)
layout.addWidget(self.timecode, 1)
layout.addWidget(self.status)
# Connect while visible, disconnect when hidden: a closed slate costs
# nothing. Methods on a QObject (rather than lambdas) are always called on
# the GUI thread, even when the engine emits from its audio thread.
def showEvent(self, event):
# timeCode has no signal of its own; it updates on doneReadingBuffer.
RecordingEngine.doneReadingBuffer.connect(self.refresh_timecode)
RecordingEngine.isRecordingChanged.connect(self.refresh_status)
self.refresh_timecode()
self.refresh_status()
super().showEvent(event)
def hideEvent(self, event):
RecordingEngine.doneReadingBuffer.disconnect(self.refresh_timecode)
RecordingEngine.isRecordingChanged.disconnect(self.refresh_status)
super().hideEvent(event)
def refresh_timecode(self):
text = RecordingEngine.timeCode
if text != self.timecode.text(): # the buffer signal fires far more often than frames change
self.timecode.setText(text)
def refresh_status(self):
source = TimeConfig.currentTimeSourceName()
if RecordingEngine.isRecording:
self.status.setText(f"● REC {source}")
self.timecode.setStyleSheet(f"color: {REC_COLOR};")
self.status.setStyleSheet(f"color: {REC_COLOR};")
else:
self.status.setText(source)
self.timecode.setStyleSheet("")
self.status.setStyleSheet("")
# Keep the digits as large as the panel allows.
def resizeEvent(self, event):
font = self.timecode.font()
font.setPixelSize(max(16, min(self.width() // 7, int(self.height() * 0.55))))
self.timecode.setFont(font)
super().resizeEvent(event)
# One widget per showing of the panel (the Toolkit workspace, a docked
# panel); WildTrax builds them from this class.
wildtrax.panel(TimecodeSlate)