fix: add ffmpeg socket I/O timeout to prevent hung recordings
A stalled RTSP stream (TCP connection alive but no data) made the recorder's ffmpeg processes block forever on read(). The -t 300 flag only bounds by input timestamps, not wall-clock, so it never fired and the recorder loop never started the next segment. Add -rw_timeout (10s socket I/O timeout) so ffmpeg exits on a stalled stream and the existing retry loop reconnects automatically.
This commit is contained in:
parent
9760bdec33
commit
fcc760363f
1 changed files with 7 additions and 4 deletions
11
recorder.go
11
recorder.go
|
|
@ -79,8 +79,9 @@ func (rm *RecorderManager) StopAll() {
|
||||||
// d. On failure: .part file stays (picked up by cleaner), wait 5s, retry
|
// d. On failure: .part file stays (picked up by cleaner), wait 5s, retry
|
||||||
//
|
//
|
||||||
// Each segment is exactly 5 minutes. Gaps between segments are ~1-2s
|
// Each segment is exactly 5 minutes. Gaps between segments are ~1-2s
|
||||||
// (FFmpeg restart overhead). The -t 300 flag provides a hard timeout
|
// (FFmpeg restart overhead). The -t 300 flag bounds the segment by input
|
||||||
// preventing hung FFmpeg processes.
|
// duration, while -rw_timeout makes ffmpeg exit (rather than hang) when the
|
||||||
|
// RTSP stream stalls, so the retry loop below can reconnect.
|
||||||
func (rm *RecorderManager) startRecorder(cam CameraConfig) {
|
func (rm *RecorderManager) startRecorder(cam CameraConfig) {
|
||||||
rtspURL := cam.RTSPMain
|
rtspURL := cam.RTSPMain
|
||||||
if rtspURL == "" {
|
if rtspURL == "" {
|
||||||
|
|
@ -125,14 +126,16 @@ func (rm *RecorderManager) startRecorder(cam CameraConfig) {
|
||||||
partFile := filepath.Join(outDir, "rec_"+timeStr+".part.mp4")
|
partFile := filepath.Join(outDir, "rec_"+timeStr+".part.mp4")
|
||||||
finalFile := filepath.Join(outDir, "rec_"+timeStr+".mp4")
|
finalFile := filepath.Join(outDir, "rec_"+timeStr+".mp4")
|
||||||
|
|
||||||
// Build FFmpeg command with hard 5-minute timeout.
|
// Build FFmpeg command: 5-minute segment, with a socket I/O timeout so a
|
||||||
|
// stalled stream exits ffmpeg instead of hanging the recorder loop.
|
||||||
cmd := exec.Command("ffmpeg",
|
cmd := exec.Command("ffmpeg",
|
||||||
"-hide_banner", "-loglevel", "error",
|
"-hide_banner", "-loglevel", "error",
|
||||||
"-rtsp_transport", "tcp",
|
"-rtsp_transport", "tcp",
|
||||||
|
"-rw_timeout", "10000000", // 10s socket I/O timeout — exit on stalled stream
|
||||||
"-i", rtspURL,
|
"-i", rtspURL,
|
||||||
"-an", // drop audio (pcm_mulaw not supported in MP4)
|
"-an", // drop audio (pcm_mulaw not supported in MP4)
|
||||||
"-c:v", "copy", // stream-copy video: zero transcoding, near-zero CPU
|
"-c:v", "copy", // stream-copy video: zero transcoding, near-zero CPU
|
||||||
"-t", "300", // hard stop after 300 seconds (5 minutes)
|
"-t", "300", // stop after 300 seconds (5 minutes) of input
|
||||||
"-y", // overwrite output without asking
|
"-y", // overwrite output without asking
|
||||||
partFile,
|
partFile,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue