A fresh P2S support bundle showed ffmpeg's reason for the stall:
`frame=1 time=00:00:00.06 dup=0 drop=526 speed=0.0037x`. ffmpeg
connects and frames arrive (drop counter climbs ~15/s), but it emits
one output frame and the output clock freezes.
The streaming command ends with `-r 15`, putting ffmpeg in CFR mode:
it drops/dupes input frames to hit 15 fps based on the source's
timestamps. P2S firmware 01.02.00.00 sends an RTSP stream whose RTP
timestamps don't advance, so CFR treats every frame after the first
as a same-timestamp duplicate and drops it. Snapshot capture works on
the same printer because that path has no `-r` (no CFR conversion);
X1/H2 are unaffected because their firmware timestamps are correct.
The earlier probesize fix was masking this second bug.
Add `-use_wallclock_as_timestamps 1` to the P2S camera profile via
the existing extra_ffmpeg_input_args hook. ffmpeg rebuilds each
packet's PTS from arrival wall-clock time, the output clock advances,
and CFR conversion works. No dataclass change, no other model touched.
Tests: 2 new in test_camera_profiles.py (P2S splices the flag+value
pair; default profile keeps extra_ffmpeg_input_args empty so the
override never leaks to X1/H2).
Reporter on a P2S running firmware 01.02.00.00 saw the camera connect
for a few seconds then time out, repeating. P1S on the same install
worked fine — different protocol (chamber-image port 6000 vs RTSP via
ffmpeg).
The P2S RTSP path was running ffmpeg with `-probesize 32
-analyzeduration 0`, tuned for X1/H2 fast startup. The P2S's slower
keyframe pacing means ffmpeg can't lock onto the stream within 32
bytes — its own stderr says "consider increasing probesize" before
giving up after ~2s. Bambuddy reconnects, cycle repeats.
Instead of bumping the globals (which would regress every other RTSP
model's startup latency), this lifts the per-model tuning into a new
`camera_profiles` registry. CameraProfile dataclass holds the
previously-global knobs (probesize, analyzeduration, rtsp_reconnect_max,
rtsp_reconnect_delay, plus an extra_ffmpeg_input_args hook for future
per-model flags). get_camera_profile(model) returns the model's profile
or DEFAULT_PROFILE.
Default profile preserves the historical X1/H2 fast-startup values
verbatim — X1, X1C, X1E, X2D, H2C, H2D, H2D Pro, H2S all see no
behaviour change. P2S is the only override:
P2S: probesize=1_000_000, analyzeduration=500_000
SSDP internal codes (N7→P2S) resolve via an alias map so the camera
path works during the early-connect window before the display name
is settled.
This is the first step of the camera-architecture overhaul agreed
after #1395. Adding the next quirky model is a config entry, not
another module-level constant.