Camera stream stalls after ~15-30 min (corrupted FLV timestamps) #90

Open
opened 2026-07-13 15:20:34 +02:00 by fmontagna · 1 comment

Description

The /api/camera/h264 and /api/camera/stream endpoints degrade and stall after a variable time (~15-30 min). The FLV source emits valid H264 but with non-monotonic container timestamps (large PTS jumps). When ffmpeg's live transcoding hits one of these jumps, its realtime timestamping breaks and output collapses, stalling the stream.

The video data itself is fine; only the container timestamps are broken. Verified by capturing the source directly (not through the bridge): curl saves the raw FLV to a file, and decoding that file afterwards with ffmpeg -f null - completes with zero errors.

Steps to Reproduce

  1. Open /api/camera/h264 or /api/camera/stream and leave it running.
  2. After ~15-30 min the stream degrades and stalls.

Expected Behavior

Stream stays stable for hours regardless of the source's corrupted timestamps.

Actual Behavior

MJPEG becomes choppy and stalls; H264 stops producing frames with the connection still open. H264 frames produced in 1h of wall-clock: 9572 without fix vs 28694 with the fix below. invalid dropping / non-monotonic DTS messages appear only without the fix.

Out-of-phase timestamps in the raw source capture (ffprobe on the curl dump, PTS in seconds):

line 9847:  1230.628000    -> 2784369.560000   (delta +2783138.9)   # ~+32 days
line 27027: 2786516.936000 -> 1270393.604000   (delta -1516123.3)   # ~-17 days

Proposed Fix

Add -use_wallclock_as_timestamps 1 to the non-RTSP input args. In CameraCache._input_args:

else:
    args += ["-use_wallclock_as_timestamps", "1",
             "-probesize", "500000", "-analyzeduration", "500000"]

handle_camera_stream builds its ffmpeg input args locally instead of using _input_args, so the same flag needs to be added there as well for the MJPEG endpoint.

Environment

  • KX-Bridge Version: v0.9.28-nightly24
  • Operating System: Debian 13
  • Installation: Docker
  • Printer Firmware Version: 1.2.0.6

During testing I repeatedly hit HTTP 429 from the printer. handle_camera_stream spawns a dedicated FLV ffmpeg per request, so each MJPEG client opens its own FLV connection to the printer. Would it be possible to route /api/camera/stream through the CameraCache fanout (as /api/camera/h264 already does), so all MJPEG clients share the single FLV connection?

## Description The `/api/camera/h264` and `/api/camera/stream` endpoints degrade and stall after a variable time (~15-30 min). The FLV source emits valid H264 but with non-monotonic container timestamps (large PTS jumps). When ffmpeg's live transcoding hits one of these jumps, its realtime timestamping breaks and output collapses, stalling the stream. The video data itself is fine; only the container timestamps are broken. Verified by capturing the source directly (not through the bridge): `curl` saves the raw FLV to a file, and decoding that file afterwards with `ffmpeg -f null -` completes with zero errors. ## Steps to Reproduce 1. Open `/api/camera/h264` or `/api/camera/stream` and leave it running. 2. After ~15-30 min the stream degrades and stalls. ## Expected Behavior Stream stays stable for hours regardless of the source's corrupted timestamps. ## Actual Behavior MJPEG becomes choppy and stalls; H264 stops producing frames with the connection still open. H264 frames produced in 1h of wall-clock: 9572 without fix vs 28694 with the fix below. `invalid dropping` / non-monotonic DTS messages appear only without the fix. Out-of-phase timestamps in the raw source capture (`ffprobe` on the `curl` dump, PTS in seconds): ``` line 9847: 1230.628000 -> 2784369.560000 (delta +2783138.9) # ~+32 days line 27027: 2786516.936000 -> 1270393.604000 (delta -1516123.3) # ~-17 days ``` ## Proposed Fix Add `-use_wallclock_as_timestamps 1` to the non-RTSP input args. In `CameraCache._input_args`: ```python else: args += ["-use_wallclock_as_timestamps", "1", "-probesize", "500000", "-analyzeduration", "500000"] ``` `handle_camera_stream` builds its ffmpeg input args locally instead of using `_input_args`, so the same flag needs to be added there as well for the MJPEG endpoint. ## Environment - KX-Bridge Version: v0.9.28-nightly24 - Operating System: Debian 13 - Installation: Docker - Printer Firmware Version: 1.2.0.6 ## Related question: 429 on `/api/camera/stream` During testing I repeatedly hit HTTP 429 from the printer. `handle_camera_stream` spawns a dedicated FLV ffmpeg per request, so each MJPEG client opens its own FLV connection to the printer. Would it be possible to route `/api/camera/stream` through the `CameraCache` fanout (as `/api/camera/h264` already does), so all MJPEG clients share the single FLV connection?
fmontagna added the
bug
label 2026-07-13 15:20:34 +02:00
Owner

Thanks for the excellent write-up and root-cause analysis. Applied your proposed fix (-use_wallclock_as_timestamps 1 on both the CameraCache FLV input and the MJPEG endpoint in handle_camera_stream) — will be included in the next nightly build.

The fanout suggestion for /api/camera/stream (routing MJPEG through the shared CameraCache connection instead of a per-client FLV connection) makes sense too and would address the 429s you saw. Tracking that separately as it is a bigger architectural change than the timestamp fix.

Thanks for the excellent write-up and root-cause analysis. Applied your proposed fix (`-use_wallclock_as_timestamps 1` on both the `CameraCache` FLV input and the MJPEG endpoint in `handle_camera_stream`) — will be included in the next nightly build. The fanout suggestion for `/api/camera/stream` (routing MJPEG through the shared `CameraCache` connection instead of a per-client FLV connection) makes sense too and would address the 429s you saw. Tracking that separately as it is a bigger architectural change than the timestamp fix.
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: viewit/KX-Bridge-Release#90
No description provided.