From 9f0ebd07cef8e0134fc4958dda85d76a5db262de Mon Sep 17 00:00:00 2001 From: Milos Pesic Date: Thu, 24 Sep 2026 16:27:35 +0200 Subject: [PATCH] egressobs: report audio_only for v2 egress and replay requests (#1816) GetAudioOnly had no case for EgressInfo_Egress or EgressInfo_Replay, so every v2 StartEgress and replay export reported audio_only=false and the rollup billed audio-only Template/Web sessions at the video rate. Co-authored-by: Claude Opus 5.5 (1M context) --- .changeset/egressobs-v2-audio-only.md | 5 ++ observability/egressobs/egress.go | 8 ++++ observability/egressobs/egress_test.go | 65 ++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 .changeset/egressobs-v2-audio-only.md diff --git a/.changeset/egressobs-v2-audio-only.md b/.changeset/egressobs-v2-audio-only.md new file mode 100644 index 000000000..70948704d --- /dev/null +++ b/.changeset/egressobs-v2-audio-only.md @@ -0,0 +1,5 @@ +--- +"github.com/livekit/protocol": patch +--- + +`egressobs.GetAudioOnly` reports v2 `StartEgress` and replay export requests as audio-only when their Template or Web source sets `audio_only`. diff --git a/observability/egressobs/egress.go b/observability/egressobs/egress.go index b804a6099..059f12370 100644 --- a/observability/egressobs/egress.go +++ b/observability/egressobs/egress.go @@ -191,7 +191,15 @@ func GetAudioOnly(info *livekit.EgressInfo) bool { return req.RoomComposite.AudioOnly case *livekit.EgressInfo_Web: return req.Web.AudioOnly + case *livekit.EgressInfo_Egress: + return getAudioOnlyV2(req.Egress) + case *livekit.EgressInfo_Replay: + return getAudioOnlyV2(req.Replay) default: return false } } + +func getAudioOnlyV2(r egress.EgressRequest) bool { + return r.GetTemplate().GetAudioOnly() || r.GetWeb().GetAudioOnly() +} diff --git a/observability/egressobs/egress_test.go b/observability/egressobs/egress_test.go index 4d205cbbf..0a65f1eb3 100644 --- a/observability/egressobs/egress_test.go +++ b/observability/egressobs/egress_test.go @@ -202,6 +202,71 @@ func TestGetAudioOnly(t *testing.T) { }, audioOnly: true, }, + { + name: "v2 Template audio only", + info: &livekit.EgressInfo{ + Request: &livekit.EgressInfo_Egress{ + Egress: &livekit.StartEgressRequest{ + Source: &livekit.StartEgressRequest_Template{ + Template: &livekit.TemplateSource{AudioOnly: true}, + }, + }, + }, + }, + audioOnly: true, + }, + { + name: "v2 Template not audio only", + info: &livekit.EgressInfo{ + Request: &livekit.EgressInfo_Egress{ + Egress: &livekit.StartEgressRequest{ + Source: &livekit.StartEgressRequest_Template{ + Template: &livekit.TemplateSource{Layout: "grid"}, + }, + }, + }, + }, + audioOnly: false, + }, + { + name: "v2 Web audio only", + info: &livekit.EgressInfo{ + Request: &livekit.EgressInfo_Egress{ + Egress: &livekit.StartEgressRequest{ + Source: &livekit.StartEgressRequest_Web{ + Web: &livekit.WebSource{AudioOnly: true}, + }, + }, + }, + }, + audioOnly: true, + }, + { + name: "v2 Media returns false", + info: &livekit.EgressInfo{ + Request: &livekit.EgressInfo_Egress{ + Egress: &livekit.StartEgressRequest{ + Source: &livekit.StartEgressRequest_Media{ + Media: &livekit.MediaSource{}, + }, + }, + }, + }, + audioOnly: false, + }, + { + name: "Replay Template audio only", + info: &livekit.EgressInfo{ + Request: &livekit.EgressInfo_Replay{ + Replay: &livekit.ExportReplayRequest{ + Source: &livekit.ExportReplayRequest_Template{ + Template: &livekit.TemplateSource{AudioOnly: true}, + }, + }, + }, + }, + audioOnly: true, + }, { name: "Track request returns false", info: &livekit.EgressInfo{