From 31962181cb2418ebf1fc5ea30750977d9462bf09 Mon Sep 17 00:00:00 2001 From: Felipe Santos Date: Tue, 25 Nov 2025 16:37:08 -0300 Subject: [PATCH] Add `#timeout` param for ffmpeg source --- README.md | 7 +++++-- internal/ffmpeg/ffmpeg.go | 20 ++++++++++++++++---- internal/ffmpeg/ffmpeg_test.go | 5 +++++ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f27afeb0..1861433d 100644 --- a/README.md +++ b/README.md @@ -371,9 +371,11 @@ But you can override them via YAML config. You can also add your own formats to ```yaml ffmpeg: bin: ffmpeg # path to ffmpeg binary + global: "-hide_banner" + timeout: 5 # default timeout in seconds for rtsp inputs h264: "-codec:v libx264 -g:v 30 -preset:v superfast -tune:v zerolatency -profile:v main -level:v 4.1" mycodec: "-any args that supported by ffmpeg..." - myinput: "-fflags nobuffer -flags low_delay -timeout 5000000 -i {input}" + myinput: "-fflags nobuffer -flags low_delay -timeout {timeout} -i {input}" myraw: "-ss 00:00:20" ``` @@ -383,9 +385,10 @@ ffmpeg: - You can use `width` and/or `height` params, important with transcoding (ex. `#video=h264#width=1280`) - You can use `drawtext` to add a timestamp (ex. `drawtext=x=2:y=2:fontsize=12:fontcolor=white:box=1:boxcolor=black`) - This will greatly increase the CPU of the server, even with hardware acceleration +- You can use `timeout` param to set RTSP input timeout in seconds (ex. `#timeout=10`) - You can use `raw` param for any additional FFmpeg arguments (ex. `#raw=-vf transpose=1`) - You can use `input` param to override default input template (ex. `#input=rtsp/udp` will change RTSP transport from TCP to UDP+TCP) - - You can use raw input value (ex. `#input=-timeout 5000000 -i {input}`) + - You can use raw input value (ex. `#input=-timeout {timeout} -i {input}`) - You can add your own input templates Read more about [hardware acceleration](https://github.com/AlexxIT/go2rtc/wiki/Hardware-acceleration). diff --git a/internal/ffmpeg/ffmpeg.go b/internal/ffmpeg/ffmpeg.go index 242c151d..d945c0ff 100644 --- a/internal/ffmpeg/ffmpeg.go +++ b/internal/ffmpeg/ffmpeg.go @@ -2,6 +2,7 @@ package ffmpeg import ( "net/url" + "strconv" "strings" "github.com/AlexxIT/go2rtc/internal/api" @@ -60,13 +61,14 @@ func Init() { var defaults = map[string]string{ "bin": "ffmpeg", "global": "-hide_banner", + "timeout": "5", // inputs - "file": "-re -i {input}", - "http": "-fflags nobuffer -flags low_delay -i {input}", - "rtsp": "-fflags nobuffer -flags low_delay -timeout 5000000 -user_agent go2rtc/ffmpeg -rtsp_flags prefer_tcp -i {input}", + "file": "-re -i {input}", + "http": "-fflags nobuffer -flags low_delay -i {input}", + "rtsp": "-fflags nobuffer -flags low_delay -timeout {timeout} -user_agent go2rtc/ffmpeg -rtsp_flags prefer_tcp -i {input}", - "rtsp/udp": "-fflags nobuffer -flags low_delay -timeout 5000000 -user_agent go2rtc/ffmpeg -i {input}", + "rtsp/udp": "-fflags nobuffer -flags low_delay -timeout {timeout} -user_agent go2rtc/ffmpeg -i {input}", // output "output": "-user_agent ffmpeg/go2rtc -rtsp_transport tcp -f rtsp {output}", @@ -169,6 +171,16 @@ func inputTemplate(name, s string, query url.Values) string { } else { template = defaults[name] } + if strings.Contains(template, "{timeout}") { + timeout := query.Get("timeout") + if timeout == "" { + timeout = defaults["timeout"] + } + if i, _ := strconv.Atoi(timeout); i > 0 { + timeout = strconv.Itoa(i * 1000000) + } + template = strings.Replace(template, "{timeout}", timeout, 1) + } return strings.Replace(template, "{input}", s, 1) } diff --git a/internal/ffmpeg/ffmpeg_test.go b/internal/ffmpeg/ffmpeg_test.go index 30052d78..b9d02183 100644 --- a/internal/ffmpeg/ffmpeg_test.go +++ b/internal/ffmpeg/ffmpeg_test.go @@ -123,6 +123,11 @@ func TestParseArgsIpCam(t *testing.T) { source: "rtmp://example.com#input=rtsp/udp", expect: `ffmpeg -hide_banner -fflags nobuffer -flags low_delay -timeout 5000000 -user_agent go2rtc/ffmpeg -i rtmp://example.com -c copy -user_agent ffmpeg/go2rtc -rtsp_transport tcp -f rtsp {output}`, }, + { + name: "[RTSP] custom timeout", + source: "rtsp://example.com#timeout=10", + expect: `ffmpeg -hide_banner -allowed_media_types video+audio -fflags nobuffer -flags low_delay -timeout 10000000 -user_agent go2rtc/ffmpeg -rtsp_flags prefer_tcp -i rtsp://example.com -c copy -user_agent ffmpeg/go2rtc -rtsp_transport tcp -f rtsp {output}`, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) {