Quick start · Configuration · HTML cookbook
Use an NVIDIA host and a Python module built against the same patched FFmpeg as avplumber, with CUDA/NVCC and DRM/GL for browser sources.
python3 -m pyplumber.mixer.cli --config mixer.jsonThe config must declare outputs, or supply --output <path> / --janus-output.
For a simple file-only show:
python3 -m pyplumber.mixer.cli \
--input <input-1> --input <input-2> --loop-inputs \
--output program.mp4 --fps 30 --remote-control-port 7777Only this --input mode uses fixed 1080×1920 fullscreen and 2/4/8/16-box
layouts. --config supplies its own canvas and scenes. Use --output-format
for an ambiguous target; --codec and --bitrate select the NVENC output.
Run --help for current defaults and the full option list.
File inputs retain their native cadence; --fps selects the canvas/output rate.
For encoded files, fractional rates come from their timestamps. The compositor
selects, repeats or drops source frames as needed, while realtime still paces
input delivery. Browser pacing follows its configured paint rate. See
configuration.
The Compose stack starts the web UI. With a standalone backend:
python3 -m pyplumber.mixer.gui --host 127.0.0.1 --port 7777 --http-port 7681For the recorded two-viewer layout, select Viewers 2, then Program preview in one viewer and Program dirty in the other. The first contains PVW, PGM and eight scene slots; the second shows the program with its enabled keys. Viewer selection is local to the browser. Scene takes, key buttons, AUX paging and AUX layout controls operate the running mixer.
The take bar follows a vision switcher's transition area. A scene tile or 1–9
selects Preview; with Direct cut / D a pick cuts straight to Program. Cut / C
cuts Preview to Program and completes a running transition; Auto / Space runs
the selected transition, Fade / F at its rate or a wipe clip
(W). Pressed again during its own mix it does what the menu beside it says:
Halt holds the mix and once more runs it on, Complete finishes it at once. The lever mixes
by hand from the end it rests at: the far end completes the mix and is where the
next one starts, back at its start the mix is cancelled. After an AUTO or CUT ended
a mix the lever left half way, it acts again once moved to an end. The bar under
the lever shows the transition's progress. Rates read as on a switcher panel:
frames below a second (15f), seconds:frames from one second (1:15). Type
either form, or frames alone (45 shows as 1:15); the small arrows beside it, the
arrow keys and the mouse wheel over it step a frame.
Next in the Preview box chooses what the next take changes, as on a GV panel: BKGD the scene, 1–4 the keys, numbered as in the Keys card, lit while armed. A red dot marks a key on air, which an armed take removes. With BKGD the armed keys go with the background transition on its clock: they mix at its rate, hold when it holds, follow the lever, cut with a cut and switch at a wipe clip's cut point; a cancelled transition leaves them as they were, and they stay armed for the following takes. Without BKGD, Cut cuts the armed keys and Auto fades them at the Fade rate; the lever, which mixes the background only, is off. BKGD is the page's own; the armed keys are the mixer's, the same for every controller.
Each key in the Keys card goes on or off air at its own rate, shown on its tag
(12f, CUT) and kept by the mixer for every controller, with the Fade curve;
Shift+click cuts it whatever the rate. Clicking the tag edits the rate in place
(frames, seconds:frames, or 0 / c to cut; Enter or leaving it sets it, Escape
keeps the old one). Its red border is the tally of the last frame the keyer
emitted, never a pending command; its number turns amber while it is armed. K
changes every key, each at its own rate: all off if any is on, otherwise all on.
FTB in the Program box fades the keyed program to black at the Fade rate and
pressed again back; it flashes while
Program is black, and the clean feed is never faded. The slots card edits the
scene slots of the multiview last clicked (marked "· slots" when two are on screen):
click a slot, then a scene, or Shift+1–8.
Each viewer must support its output codec. The recorded L4 show uses HEVC for Program preview and H.264 for dirty Program; an H.264-capable browser alone cannot display both. Setup can change output codecs, but applying Setup restarts the mixer. The downloadable demonstration MP4 is H.264.
For the optional terminal UI:
python3 -m venv .venv-tui
.venv-tui/bin/pip install -r pyplumber/mixer/gui/requirements.txt
.venv-tui/bin/python -m pyplumber.mixer.gui.tui --host 127.0.0.1 --port 7777TUI keys: 1–9 select scenes, c cuts, f fades, w wipes, t toggles
Direct, r reconnects. Wipe paths are on the backend host. Clips must retain
alpha and cover the scene at their midpoint. --wipe-cache-mb controls the
GPU cache; zero decodes each take. Startup fails on an incomplete cached clip.
--janus-output sends video RTP to 127.0.0.1:5004, RTCP to port 5005 by
default. Set --janus-host / --janus-video-port for another destination.
Each rendition needs its own port pair and a matching Streaming mountpoint.
Setup manages mountpoints through --janus-api; the standalone backend does not.
PLI/FIR feedback requests keyframes, limited by --keyframe-min-interval-ms.
Compose builds the mixer and imports browser/Wayland/Janus service definitions from the shared DMA-BUF stack.
| Dockerfile | Stack | Host |
|---|---|---|
Dockerfile.fedora44 (default) |
Fedora 44 / CUDA 13.4 / FFmpeg 8.1 | R615+ driver |
Dockerfile |
Ubuntu 22.04 / CUDA 11.7 | Older compatible NVIDIA driver |
Select the second with MIXER_DOCKERFILE=Dockerfile. The L4 preset
pins its own FFmpeg build. Keep media/.nv-cache to reuse driver-compiled kernels.
TensorRT is optional (WITH_TENSORRT=1 and the tensorrt_url build secret in the
Fedora image); the manual mixer needs no neural models.
Serve controls at / and the preview server at /preview/, stripping that
prefix. Set MIXER_PREVIEW_BASE=/preview/ (or pass --preview-base /preview/
to python3 -m pyplumber.mixer.gui).
Forward WebSocket upgrades for the preview's Janus path as well as normal HTTP.
The L4 proxy template is a complete example.
WebRTC also needs the configured UDP range reachable from the viewer.
python3 -m pytest -q tests/mixerNVIDIA-dependent cases require the configured GPU host. Against a running backend:
python3 tests/mixer/smoke_test.py --port 7777 --wipe-file <alpha-clip>
python3 tests/mixer/cut_spam.py --url http://127.0.0.1:7681These change Program. See latency for the cut probe and browser measurement, and capacity for the limits of recorded results.