The printer rotates its FLV/RTSP stream token on reboot. CameraCache.set_url()
was a bare assignment, so the three running ffmpeg loops never noticed - they
only re-read self._url at the top of their outer loop, which they never reach
while permanently blocked in a stdout read on the now-silent, stale-token
connection (TCP stays ESTABLISHED with no data and no FIN, so a passive
reader can't tell "peer is quiet" from "peer is gone").
Three-part fix, all per the excellent root-cause analysis and reproduction
in the issue (thanks @fmontagna):
1. set_url() now detects a URL change and calls reset() to tear down the
stale ffmpeg loops, so the next ensure_running() respawns them against
the new URL.
2. ffmpeg's -timeout option (10s, applies to both RTSP and HTTP-FLW since
both share _input_args) as a second line of defense for a source that
goes silent while the URL stays the same (network loss, camera hang).
3. handle_camera_stream now waits up to 5s for the first frame BEFORE
calling resp.prepare() and returns 503 on timeout. Previously it had no
first-frame timeout at all, and prepare() commits the response status
to 200 - so a stalled source could never surface as an error to the
client, only as an infinite hang.