From 84d028d20ce3123c969760e9bdbc98ddaf3e7979 Mon Sep 17 00:00:00 2001 From: Josh Allmann Date: Fri, 17 Oct 2025 23:13:46 +0000 Subject: [PATCH] ai/live: Add a desync query parameter to WHEP. This gives audio and video tracks a separate `mid` which stops the browser from trying to keep playback in sync. This may lead to desynced audio and video but improves latency. --- media/whep_server.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/media/whep_server.go b/media/whep_server.go index 61b3662564..fe73fe6610 100644 --- a/media/whep_server.go +++ b/media/whep_server.go @@ -34,6 +34,10 @@ func (s *WHEPServer) CreateWHEP(ctx context.Context, w http.ResponseWriter, r *h return } + // Read any query params + queryParams := r.URL.Query() + desync := queryParams.Get("desync") != "" + // Read the SDP offer offerBytes, err := io.ReadAll(r.Body) if err != nil { @@ -108,11 +112,18 @@ func (s *WHEPServer) CreateWHEP(ctx context.Context, w http.ResponseWriter, r *h hasVideo = true case *mpegts.CodecOpus: + // if tracks share the same mid the browser will sync them for playback + // this may lead to buffering / latency so use a separate mid if requested + audioMid := "livepeer" + if desync { + clog.Info(ctx, "Using a separate mid for audio") + audioMid = audioMid + "-audio" + } webrtcTrack, err := NewLocalTrack( // NB: Don't signal sample rate or channel count here. Leave empty to use defaults. // Opus RTP RFC 7587 requires opus/48000/2 regardless of the actual content webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus}, - "audio", "livepeer", // NB: can be another MediaID to desync a/v for latency + "audio", audioMid, // NB: can be another MediaID to desync a/v for latency ) if err != nil { clog.InfofErr(ctx, "Error creating track for opus", err)