From 0172ea5150095762050278033d6bfc977317878f Mon Sep 17 00:00:00 2001 From: legop3 Date: Sat, 27 Jun 2026 02:39:31 -0400 Subject: [PATCH] audio stufs --- pi/install_roverd.sh | 6 ++-- pi/roverd/config.go | 36 ++++++++++++++++++- pi/roverd/roverd.sample.yaml | 4 +-- .../services/audioForwardService/policy.js | 28 +++++++++++---- to-do.md | 6 ++-- 5 files changed, 64 insertions(+), 16 deletions(-) diff --git a/pi/install_roverd.sh b/pi/install_roverd.sh index dd6b0db9..4e464f54 100755 --- a/pi/install_roverd.sh +++ b/pi/install_roverd.sh @@ -314,9 +314,9 @@ log "Installed audio-forward listener helper + systemd unit" install -d -o roverd -g roverd /var/lib/roverd cat > /var/lib/roverd/video.env <<'ENV' # Managed by roverd; placeholder values will be overwritten at runtime. -PUBLISH_URL=srt://192.168.0.86:9000?streamid=#!::r=CHANGE_ME,m=publish&latency=10&mode=caller&transtype=live&pkt_size=1316 -AUDIO_PUBLISH_URL=srt://192.168.0.86:9000?streamid=#!::r=CHANGE_ME-audio,m=publish&latency=10&mode=caller&transtype=live&pkt_size=1316 -AUDIO_FORWARD_URL=srt://192.168.0.86:9000?streamid=#!::r=CHANGE_ME-fwd,m=request&latency=10&mode=caller&transtype=live&pkt_size=1316 +PUBLISH_URL=srt://192.168.0.86:9000?streamid=%23%21::r=CHANGE_ME,m=publish&latency=20000&mode=caller&transtype=live&pkt_size=1316 +AUDIO_PUBLISH_URL=srt://192.168.0.86:9000?streamid=%23%21::r=CHANGE_ME-audio,m=publish&latency=20000&mode=caller&transtype=live&pkt_size=1316 +AUDIO_FORWARD_URL=srt://192.168.0.86:9000?streamid=%23%21::r=CHANGE_ME-fwd,m=request&latency=20000&mode=caller&transtype=live&pkt_size=1316 VIDEO_BITRATE=2000000 AUDIO_ENABLE=0 AUDIO_DEVICE=hw:0,0 diff --git a/pi/roverd/config.go b/pi/roverd/config.go index 77860b9b..452bb359 100644 --- a/pi/roverd/config.go +++ b/pi/roverd/config.go @@ -296,6 +296,9 @@ func LoadConfig(path string) (*Config, error) { } cfg.Media.AudioForwardURL = derived } + cfg.Media.PublishURL = normalizeSRTURLForLowLatency(cfg.Media.PublishURL) + cfg.Media.AudioPublishURL = normalizeSRTURLForLowLatency(cfg.Media.AudioPublishURL) + cfg.Media.AudioForwardURL = normalizeSRTURLForLowLatency(cfg.Media.AudioForwardURL) if err := validateServoConfig(&cfg.CameraServo); err != nil { return nil, fmt.Errorf("cameraServo: %w", err) } @@ -440,9 +443,40 @@ func deriveSRTURL(serverURL, streamName string, port int, mode string) (string, port = 9000 } escaped := url.PathEscape(streamName) - return fmt.Sprintf("srt://%s:%d?streamid=#!::r=%s,m=%s&latency=10&mode=caller&transtype=live&pkt_size=1316", host, port, escaped, mode), nil + return fmt.Sprintf("srt://%s:%d?streamid=%%23%%21::r=%s,m=%s&latency=20000&mode=caller&transtype=live&pkt_size=1316", host, port, escaped, mode), nil } +func normalizeSRTURLForLowLatency(raw string) string { + trimmed := strings.TrimSpace(raw) + if trimmed == "" || !strings.HasPrefix(trimmed, "srt://") { + return raw + } + + // SRT stream IDs commonly start with "#!::". In a URL, a literal "#" + // begins the fragment section, so ffmpeg/libsrt can ignore query options + // placed after it. MediaMTX then falls back to the SRT default latency, + // which showed up in diagnostics as a 120 ms receive delay even though the + // URL text contained latency=10. Percent-encoding only the "#!" prefix keeps + // MediaMTX's stream ID parser behavior while allowing latency/mode/transtype + // to remain real SRT query parameters. + normalized := strings.ReplaceAll(trimmed, "streamid=#!::", "streamid=%23%21::") + + // ffmpeg's SRT latency URL option is expressed in microseconds. Use 20 ms as + // the default interactive rover target: much lower than the 120 ms fallback, + // but not so aggressive that tiny LAN jitter immediately causes drops. + if srtLegacyLatencyRe.MatchString(normalized) { + normalized = srtLegacyLatencyRe.ReplaceAllString(normalized, "${1}20000${2}") + } else if !strings.Contains(normalized, "latency=") { + separator := "&" + if !strings.Contains(normalized, "?") { + separator = "?" + } + normalized += separator + "latency=20000" + } + return normalized +} + +var srtLegacyLatencyRe = regexp.MustCompile(`([?&]latency=)10($|&)`) var hexColorRe = regexp.MustCompile(`^#[0-9A-Fa-f]{6}$`) func normalizeHexColor(raw string) (string, error) { diff --git a/pi/roverd/roverd.sample.yaml b/pi/roverd/roverd.sample.yaml index cd2b8d66..6883292c 100644 --- a/pi/roverd/roverd.sample.yaml +++ b/pi/roverd/roverd.sample.yaml @@ -17,8 +17,8 @@ battery: urgent: 1650 maxWheelSpeed: 350 media: - publishUrl: srt://192.168.0.86:9000?streamid=#!::r=roomba-alpha,m=publish&latency=10&mode=caller&transtype=live&pkt_size=1316 - audioForwardUrl: srt://192.168.0.86:9000?streamid=#!::r=roomba-alpha-fwd,m=request&latency=10&mode=caller&transtype=live&pkt_size=1316 + publishUrl: srt://192.168.0.86:9000?streamid=%23%21::r=roomba-alpha,m=publish&latency=20000&mode=caller&transtype=live&pkt_size=1316 + audioForwardUrl: srt://192.168.0.86:9000?streamid=%23%21::r=roomba-alpha-fwd,m=request&latency=20000&mode=caller&transtype=live&pkt_size=1316 publishPort: 9000 # Default assumes camera is mounted upside down; set false for upright mounts. cameraInverted: true diff --git a/server/src/services/audioForwardService/policy.js b/server/src/services/audioForwardService/policy.js index bb72a80d..2ac86a42 100644 --- a/server/src/services/audioForwardService/policy.js +++ b/server/src/services/audioForwardService/policy.js @@ -29,19 +29,35 @@ function createAudioForwardPolicy(deps) { function forcePublishStreamMode(rawUrl) { const value = String(rawUrl || '').trim(); if (!value) return ''; - if (!/[?&]streamid=#!::/.test(value)) return value; - if (/,m=publish\b/.test(value)) return value; - if (/,m=[a-zA-Z]+\b/.test(value)) return value.replace(/,m=[a-zA-Z]+\b/, ',m=publish'); - return value.replace(/([?&]streamid=#!::[^&]*)/, '$1,m=publish'); + const normalized = value + /* + A literal "#" inside the SRT stream ID turns the rest of the URL into a + fragment for normal URL parsers. Encoding the "#!" prefix keeps MediaMTX + receiving the same stream ID while allowing latency/mode/transtype to be + parsed as real SRT options instead of being accidentally hidden inside + the stream ID text. + */ + .replace(/([?&]streamid=)#!::/, '$1%23%21::') + /* + SRT latency is expressed in microseconds by ffmpeg/libsrt. The previous + latency=10 value was both too small to be a sane target and, because of + the unescaped stream ID, was not being applied in practice. Use the same + 20 ms target as rover publishing. + */ + .replace(/([?&]latency=)10\b/, (_, prefix) => `${prefix}20000`); + if (!/[?&]streamid=(?:#!::|%23%21::)/.test(normalized)) return normalized; + if (/,m=publish\b/.test(normalized)) return normalized; + if (/,m=[a-zA-Z]+\b/.test(normalized)) return normalized.replace(/,m=[a-zA-Z]+\b/, ',m=publish'); + return normalized.replace(/([?&]streamid=(?:#!::|%23%21::)[^&]*)/, '$1,m=publish'); } function resolveForwardUrl(roverId) { const record = roverManager.rovers.get(roverId); const configured = record?.meta?.media?.audioForwardUrl; if (configured) return forcePublishStreamMode(configured); - return `srt://127.0.0.1:9000?streamid=#!::r=${encodeURIComponent( + return `srt://127.0.0.1:9000?streamid=%23%21::r=${encodeURIComponent( roverId + streamSuffix, - )},m=publish&latency=10&mode=caller&transtype=live&pkt_size=1316`; + )},m=publish&latency=20000&mode=caller&transtype=live&pkt_size=1316`; } function resolveForwardPathId(roverId) { diff --git a/to-do.md b/to-do.md index a0c0f4ce..7295cd3b 100644 --- a/to-do.md +++ b/to-do.md @@ -1,7 +1,5 @@ -1. add camera filter indicator for when youre changing it -2. make alert feed better with fadeout and stuff and it stays when you hover over one -3. fix rover request spam queue cheat -4. fix this: +1. fix rover request spam queue cheat +2. fix this: `Jun 18 15:14:18 roombaserver.local node[216731]: /home/daniel/MultiRoombaRover/server/src/services/roverManager/socketHandlers.js:92 Jun 18 15:14:18 roombaserver.local node[216731]: cb({ error: err.message }); Jun 18 15:14:18 roombaserver.local node[216731]: ^