VQF Engine — WebSocket API
The VQF Engine is a compiled Adobe Premiere Pro ControlSurface plugin by Video Quick Fix®. It runs a WebSocket server that accepts plain-text commands and returns plain-text replies. Current engine version: 1.2.2 — download the installer. Available for Mac (macOS 13+) and Windows (10 / 11) — see the VQF Engine page for both installers.
Connection
- URL:
ws://localhost:7890 - Protocol: text frames only (no JSON envelope, no binary)
- The engine is only available while Premiere Pro is running with the plugin loaded. Reconnect with retry/backoff if the connection drops.
Message conventions
- Commands and replies are colon-delimited strings.
- Replies are identified by prefix (e.g.
angle:,clipsize:). Match replies by prefix — do not assume the next frame received is the reply to your last command. - Some commands send no reply at all (noted below). Use a timeout on any command you await.
ticksvalues are Premiere Pro time ticks (as returned by the UXP API'sgetStartTime().ticks/getEndTime().ticks), passed as strings.- Track indexes are 1-based (UXP
getTrackIndex()returns 0-based — add 1).
Commands
get.version1.2.1+
Returns the engine's version string. Use this at connect time to detect an outdated engine and prompt the user to rerun the installer pkg (a new engine only takes effect after Premiere Pro restarts).
Reply: version:<semver>
Engines older than 1.2.1 don't recognize the command and send no reply — treat a timeout as "pre-1.2.1".
→ get.version ← version:1.2.1
get.angle:<startTicks>:<track>
Returns the currently selected camera angle of the multicam clip at the given position in the active sequence.
startTicks— clip start time in tickstrack— 1-based video track index
Reply: angle:<n> where <n> is the active camera number.
→ get.angle:12303360000:1 ← angle:3
get.clipsize:<startTicks>:<endTicks>:<track>
Returns the frame dimensions of the clip at the given position in the active sequence.
startTicks— clip start time in ticksendTicks— clip end time in ticks (optional; if omitted, the engine matches on start time and track only, which may be ambiguous if multiple open timelines have a clip at the same position)track— 1-based video track index
Short form: get.clipsize:<startTicks>:<track>
Reply: clipsize:<width>:<height>
→ get.clipsize:12303360000:15240960000:1 ← clipsize:3840:2160
get.clipsize.marker:<token>:<track> · get.angle.marker:<token>:<track>1.1.0+
Marker-rendezvous variants of get.clipsize / get.angle. Instead of matching a clip by raw ticks (ambiguous across open timelines), the client first creates a temporary sequence marker whose name is a unique token at the clip's start, then queries by that token. The engine locates the marker by name via the Premiere Pro Marker Suite, which pins both the correct timeline and the exact time — no timeline-ID guessing. The client removes the marker after the reply.
token— unique marker name (e.g.VQF-abc123-1); must not contain:track— 1-based video track index
Reply: same as the positional commands — clipsize:<width>:<height> or angle:<n>. If the marker is not found (or the Marker Suite is unavailable), the engine replies with zeros (clipsize:0:0 / angle:0); treat this as failure and fall back to the positional query. Engines built before marker support don't recognize the command and send no reply — use a timeout.
→ get.clipsize.marker:VQF-mdq31x-1:1 ← clipsize:3840:2160
Side effect: a marker-validated timeline seeds the engine's timeline cache, so subsequent positional commands also get faster and more reliable.
cmd.multicam.choosenocut.camera<N>
Switches the currently selected multicam clip to camera <N> without creating a cut. The clip must already be selected in the sequence before sending.
Reply: none. To confirm the switch landed, poll get.angle afterward.
→ cmd.multicam.choosenocut.camera2
multicam.angle:<n>
Sets the camera angle on the currently selected clip. Intended for nested-sequence multicam clips.
Reply:
| Reply | Meaning |
|---|---|
multicam.angle.ok: | angle applied |
multicam.angle.error:parse | <n> was not a valid number |
multicam.angle.error:range | <n> is outside the clip's available angles |
→ multicam.angle:2 ← multicam.angle.ok:
vitals.subscribe1.1.0+ payload
Opts this connection into push telemetry. Costs nothing when unused: all polling work is skipped while no client is subscribed.
Reply: none directly; the engine then pushes two kinds of frames to subscribers:
1. vitals:<json> — once per second:
vitals:{"v":"1.2.1","playing":true,"idleSec":0,
"paused":false,"recording":false,"rewind":false,"ffwd":false,
"speed":1.98,"timecode":"00:01:23:12","displayMode":1,
"cuts":142,"cutsChanged":false,"edited":true,"seqChanged":false,
"markers":7,"tracks":9,"audioPeakDb":-6.2,"soloActive":false}
| Field | Meaning |
|---|---|
v | engine version string (added 1.2.1 — absent on older engines; treat missing as "pre-1.2.1") |
playing / paused / recording / rewind / ffwd | live transport state as Premiere Pro reports it |
speed | actual playback rate derived from timecode deltas: ~1.0 normal, ~2.0 double-tapped L, negative for J-key reverse, ~0 stopped |
timecode | current playhead display string; displayMode is the host's display-mode enum |
idleSec | seconds since last keyboard/mouse input system-wide (AFK detection) |
cuts | segment count of the active timeline (−1 if no timeline known yet); cutsChanged true the tick it changes |
edited | true the tick the timeline's content hash changes — fires for trims, moves, and effect changes even when the cut count is unchanged |
seqChanged | true the tick the user switches to a different sequence |
markers | sequence marker count (−1 unavailable) |
tracks | mixer channel-strip count (audio tracks; −1 unavailable) |
audioPeakDb | loudest master-channel meter value; only sampled during playback, −999 otherwise |
soloActive | The Premiere Pro "rude solo" flag — some channel is soloed |
Fields are additive over the v1 payload (playing, idleSec), so older clients keep working. Parse leniently: treat missing fields as unavailable.
2. event:transport:<json> — pushed immediately (not on the 1 Hz tick):
event:transport:{"type":"play","on":true}
type is one of play, pause, stop, record, rewind, ffwd. Use these for reactions that shouldn't lag up to a second; the next vitals: frame will agree with them.
dump.angle:<startTicks>[:<track>]
Diagnostic dump of the Premiere Pro video segment node tree at the given time — the raw data that get.angle / get.clipsize answers are derived from. Use it when a query returns zeros and you need to see what the engine actually sees. Documented as official as of engine 1.2.1 (present in earlier builds).
startTicks— position in tickstrack— optional 1-based video track index (informational; the dump walks every node regardless)
Reply: a stream of text frames, each prefixed [dump] , opened by [dump] === VIDEO SEGMENT NODE DUMP START === and terminated by [dump] === VIDEO SEGMENT NODE DUMP END ===. In between: one block per node (id, type, flags), selected segment properties (clip track ID, multicam selected track, stream frame width/height, nested-sequence hash), then its inputs and operators, indented by depth. The engine probes the cached last-good timeline, all known-good timelines, and ±5 IDs around the last good one, so the same tree can appear once per matching timeline (--- timeline <id> --- separators). If the VideoSegment suite is unavailable, a single [dump] ERROR: could not acquire VideoSegmentSuite line precedes END.
Output can run to hundreds of frames on complex sequences. The framing (START/END markers, [dump] prefix) is stable API; the exact property lines may grow over time — parse leniently.
→ dump.angle:12303360000:1 ← [dump] === VIDEO SEGMENT NODE DUMP START === ← [dump] time=12303360000 track=1 ← [dump] --- timeline 42 --- ← [dump] NODE id=101 type=Clip flags=0 currentTrack=-1 ... ← [dump] === VIDEO SEGMENT NODE DUMP END ===
uif.window.<name>
Focuses the named Premiere Pro window/panel.
<name>— the panel's display name, e.g.uif.window.Program Monitors
Reply: none.
→ uif.window.Program Monitors
exec:<contextID>:<commandID>1.2.0+
Executes a host command in an explicit UI context. The bare fall-through path (sending a raw command ID) always runs in the global context, which silently ignores context-scoped commands (e.g. anything registered under timeline, project, program.monitor). Use exec: for those.
contextID— the command's context (first field in theget.commandsdump). Empty (exec::cmd.foo) = global context.commandID— the command ID, passed verbatim.
Reply: exec.ok:<contextID>:<commandID> once dispatched (fire-and-forget — confirms the send, not the effect), or exec.error:parse / exec.error:nosuite / exec.error:alloc.
→ exec:timeline:cmd.timeline.setttransitionduration ← exec.ok:timeline:cmd.timeline.setttransitionduration
get.transitions:<startTicks>:<endTicks>:<track>1.2.0+
Reports the head and tail transitions of the clip at the given position, read from the video segment tree. Handles all three transition alignments (start at cut / centered / end at cut) by probing just inside and just outside each clip edge.
startTicks/endTicks— clip start/end in tickstrack— 1-based video track index
Reply: transitions:<headName>:<headDurTicks>:<tailName>:<tailDurTicks>
headName/tailName— the transition's match name (e.g.ADBE Cross Dissolve New), or-if that side has no transition- durations are in ticks (254016000000 ticks = 1 s);
0when absent transitions.error:noclip— no clip found at that position/track;transitions.error:parse— bad arguments
→ get.transitions:12303360000:15240960000:1 ← transitions:ADBE Cross Dissolve New:25401600000:-:0
Read-only: the segment suite exposes no write path, so transition duration cannot be set through the engine — only via the UI command (exec:timeline:cmd.timeline.setttransitionduration, which opens a modal dialog in Premiere Pro).
get.commands1.2.1+
Dumps the full Premiere Pro control-surface command registry — the discovery tool for exec: targets. One frame per command:
command:<contextID>:<commandID>:<contextName>:<commandName>
terminated by commands.done:<count>. On failure: commands.error:<reason> (e.g. commands.error:nosuite). Any : inside free-text name fields is replaced with ; so the wire format stays parseable.
→ get.commands ← command:timeline:cmd.timeline.setttransitionduration:Timeline:Set Transition Duration ← ... ← commands.done:412
Caveats: the framing (one command: frame per entry, the commands.done terminator) is stable API. The registry contents belong to Adobe, vary by Premiere Pro version, and carry no compatibility promise — treat the dump as discovery, verify the commands you build on, and remember that anything you run via exec: executes at your own risk (some commands open modal dialogs).
get.version (or the v vitals field) to know what you're talking to. Questions or something missing? Email support@videoquickfix.com.