Every IP camera "works" when you open it in a player. The stream connects, a picture shows up, everyone moves on. Then the recorder has gaps, the analytics box misses frames, or the "live" view turns out to be a frozen picture from an hour ago — and nothing in your tooling can tell you which property of the stream is broken, because "it connects" was the only test.
I added an rtsp command to RK Edge Doctor (zero-dependency, Python stdlib only) that treats a camera stream like an acceptance test instead of a preview:
- reachability and SDP negotiation (codec, payload, clock) — Basic and Digest auth supported
- time to first frame after PLAY
- measured frame rate, with
--expect-fps / --expect-width / --expect-heightassertions for acceptance runs - RTP packet loss from sequence numbers, inter-arrival jitter, bitrate
- RTP timestamp health — regressions and gaps, the silent killers of recordings and analytics
- an optional decode spot-check for H.264 (when OpenCV is present): reassembles the bitstream from RTP and flags black or frozen pictures
Verdict: HEALTHY / DEGRADED / BROKEN, as JSON + HTML reports you can archive as acceptance evidence.
$ rkdoctor rtsp rtsp://user:pass@cam/stream --duration 15 --expect-fps 25 + reachability: 8 ms + negotiation: H264 (payload 96, clock 90000) + first_frame: 15 ms + loss: 0.000 % + jitter: 0.8 ms + fps: 25.00 fps (measured vs expected 25.00 fps) + timestamps: 0 regressions, 0 gaps + decode: 90 frames decoded (frames decode and the picture changes over time) HEALTHY Two implementation notes. First, there is no ffmpeg/ffprobe involved: the RTSP client is hand-rolled on stdlib sockets (Digest auth included), so the tool runs on a bare board image. Second, the password in the URL is redacted everywhere — terminal output, JSON, HTML. An acceptance tool that leaks camera credentials into its own reports would fail its own acceptance.
Verified end-to-end on an RK3588 board against a synthetic local stream (640×480 H.264 hardware-encoded on the same board, served over UDP, TCP-interleaved, and Digest auth): all three sessions HEALTHY, 0% loss, exactly 25.0 fps. That validates the client; what I really want is reports from real cameras — the weird vendors, the firmware that sends timestamps from 1970, the "25 fps" cameras that send 12. If you run it against a camera you own, the JSON report (credentials already redacted) is very welcome in an issue.
Also new this week: a model health table for the model command — five public YOLO variants measured on RK3588, all NPU_ONLY so far. Custom conversions that come out MIXED or CPU_HEAVY are the rows I actually want to add.
