Historical recipe — not current setup guidance. Measurements and implementation links below belong to their original workload and revision. Deployment labels and defaults may be obsolete. Use the reviewed performance recipes; browse historical evidence.
AVPlumber · Mixer optimization cookbook
Multiviewer: 192 sources, 12 at a time
Implementation links are pinned to develop at c20464a5 (2026-10-09); read against develop at 8fa15c92 on 2026-10-13 and still current. Measurements retain their original workload and scope. Watch the current 192-input L4 demo.
Current scope. Off-page subscriptions avoid additional AUX draw work and retained AUX frame references. Upstream sources remain active and continue decoding/uploading. Default playout latency is two canvas ticks up to 30 fps and three at 40 fps or above.
The Multiviewer aux shows every source in pages of 12 equal tiles, and only the 12 on screen send it frames. The current 192-input L4 show has 16 pages, including its four browser keys. The historical 100-source diagrams below illustrate the same subscription mechanism.
Status: ImplementedAt a glance
- WhatAn aux bus with layout
source_pages. It shows every source in equal 16:9 tiles, 12 per page: 2×6 on the portrait 1080×1920 canvas (tiles of about 536×300), 4×3 on landscape. The operator turns the pages withmixer.aux_page {bus, page|step}. - Why100 sources on one canvas give tiles of about 150×84, too small to judge. Paging keeps tiles readable. In this historical 100-source example, the other 88 sources add no AUX draw or retained AUX frames. Their upstream decode, upload or browser rendering continues.
- LatencyProgram: 0 frames. The bus reads sources the M/E already decodes and never delays the program. The aux draws with the main mixer's deadline (
latency_ms, two ticks up to 30 fps, three at 40 fps or above). A page turn keeps the old page on screen until the 12 new sources are ready at the next tick; if they are not ready within 250 ms (or twice the aux latency, whichever is longer), the old page stays. - Side effects
- A page turn closes 12 subscriptions and opens 12; a closed one's queue is cleared.
- Source names exist only in the web UI. The stream itself carries no labels.
- CostOne compositor pass of 12 tiles per aux frame. One H.264 or HEVC encoder, selected per output. The older H.264 measurement was +8 % ENC and 48 MB; the recorded L4 Multiviewer uses HEVC, so that figure does not describe its current encoder cost. No PGM pad unless the bus asks for the program (
"layouts": [{"preset": "pgm_pvw_grid"}], or a layout with apgmcell); with one, its subscription is closed while the pages show. One edge per source (capacity 1), but only the 12 shown carry frames. An off-page source costs a lock attempt and an atomic check per frame: no retained AUX frame and no AUX draw; upstream decoding remains active. One Python thread for all aux buses wakes once a second to resend the layout to a follower that restarted. - RiskOnly the 12 sources of the page shown are watched. A fault on an off-page source shows only when the operator turns to its page. Keep its page up, or put it in a scene multiview, to watch it continuously.
- Switch it offRemove the bus from
aux_buses.
In the web UI
The viewer header carries the page control ‹ n/N ›: previous, page number, next. [ and ] do the same. The source names are HTML over the video, placed from the tile geometry the mixer reports, so the encoder never draws text.
Where in the code
pyplumber/mixer/aux_layout.py:parse_layout, thesource_pagespreset with itspage(default 0)pyplumber/mixer/aux_layout.py:page_grid, the 2×6 / 4×3 tile geometry; sourcelayout_cells, a page's source cellspyplumber/mixer/aux_layout.py:base_composition, the cells' layers and theiractive_inputsmaskpyplumber/mixer/aux.py: the aux takes the main mixer's latency; source build one compositor and the configured H.264 or HEVC encoderpyplumber/mixer/aux.py:AuxBus.turn(page, step); sourcetick, the resend to a restarted follower, called by the one thread of AuxBusespyplumber/mixer/aux.py: themixer.aux_pagecontrol commandsrc/nodes/mixer_compositor.cpp: the compositor opens the shown sources' subscriptions and closes the rest; source and source warm the next page before it goes on screensrc/mixer/primitives/frame_subscription.hpp:publish, the lock attempt and atomic check where an off-page frame stopssrc/nodes/one_to_many.cpp: the source fan-out callspublishonce per frame and subscriberpyplumber/mixer/gui/assets/index.html: the pager in the viewer header; source: source names over the video- Tests:
tests/mixer/test_aux.py(even, separate tiles that fill the canvas),source (one page of source cells), source (page, step) and source (one scheduler for every bus)
Docs: config.md → aux_buses (layouts, mixer.aux_page).
+8 % ENC and 48 MB are historical H.264 measurements. The diagrams use the historical 100-source example; the recorded L4 show has 192 sources, 16 pages and HEVC monitors. Implementation links are pinned to the reviewed source tree.