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

Native input cadence without force_fps

Implementation links are pinned to develop at c20464a5 (2026-10-09). The mixer has changed since; this page was checked against develop at 8fa15c92 on 2026-10-13. Measurements retain their original workload and scope. Watch the current 192-input L4 demo.

File inputs keep their source cadence. The clocked compositor chooses frames for the canvas rate; input realtime remains in place. Output and AUX rate normalization remain.

Current graph and scope

decode / raw read and upload → realtime → colour filter where it converts → fan-out (stamps colour tags) → clocked compositor

The mixer calls the shared input builders with native_rate=True. Their default remains the normalized realtime → force_fps chain for playlist and other users. Browser sources still use smooth_timestamps and repeat_last_frame.

The mixer passes time_base: "1/120000" to realtime: the unit the node counts and stamps in, with wallclock pacing as before. tick_period still exists; a node takes one or the other. Frame periods for 24000/1001, 30000/1001 and 60000/1001 are exact in that time base. The mixer explicitly passes 0.25 seconds negative-time tolerance and a 1-second discontinuity threshold so the finer time base does not change these durations. realtime treats a release time inside the clock's current millisecond as due, so a time base finer than the millisecond clock does not make it spin (Event-loop sharding has the measurement). The shared helper's default chain is unchanged.

Saving in the 188-source configuration

The captured show had 120 encoded sources, 32 raw sources, 36 browser sources and four additional browser keys. Removing the 152 file-input FPS nodes saves 152 nodes and 152 queues. They shared event loops, so this does not remove 152 threads. See sharding and colour tags at the fan-out for the remaining reductions.

GPU correctness test, 2026-10-06

Eight independent 320×180 barcoded CUarray inputs ran at 25, 30, 30000/1001, 469/20 (23.45), 50, 24000/1001, 60000/1001 and 120 fps, looping every 12 seconds. Program and full-rate AUX encoded 1280×360 at 60 fps.

The test used native code at 9f940e44 and Python pacing at d577a12d, before subsequent source-routing and colour-tag changes. This small fixture establishes cadence correctness, not 188-source capacity. Captured report and revision scope.

Why this replaces the old phase recipe

This URL previously documented force_fps.center_phase. It remains useful in normalized chains: one constant aligns the first timestamp to an output tick, avoiding rounding-induced repeat/drop pairs. A historical 110-input 30 fps T4 run recorded 3,214 duplicates and 3,205 drops over 9,621 frames on one raw input before that fix. Those counters are not a measurement of the current native-rate chain.

A first removal prototype retained millisecond timestamps and introduced extra repeat/drop pairs at 60000/1001. The finer realtime time base resolved that regression. Do not remove the precision settings when removing FPS nodes.

Code and reproduction

pyplumber/mixer/inputs.py · tests/cuda/smoke_mixed_fps.py · src/nodes/realtime.cpp. The first and last link are pinned to develop at 8fa15c92, where time_base is. Run the smoke on a compatible NVIDIA host; retain raw reports, revision and build identity.