From 83f32cddac572ae944c6dffa2cf6c9e9ed863a80 Mon Sep 17 00:00:00 2001 From: Tanmay Deep Sharma Date: Tue, 21 Apr 2026 16:51:04 +0700 Subject: [PATCH] fix(media-server): make agent peer bidirectional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The agent peer built its offer via AddTrack, which pion materializes as a sendonly transceiver. The browser could therefore receive customer audio but had no m-line to send its microphone — one-shot answer cannot add a new m-line. Result: audio one-way at best, and in practice neither direction worked because the bridge never saw an agent remote track. Switch to AddTransceiverFromTrack with direction sendrecv, matching the Meta-peer fix. The browser can now respond sendrecv and the bridge's agent-to-Meta forwarding actually has a source. Co-Authored-By: Claude Opus 4.7 (1M context) --- enterprise/media-server/internal/peer/agent_peer.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/enterprise/media-server/internal/peer/agent_peer.go b/enterprise/media-server/internal/peer/agent_peer.go index becc21702..7aef1825d 100644 --- a/enterprise/media-server/internal/peer/agent_peer.go +++ b/enterprise/media-server/internal/peer/agent_peer.go @@ -99,11 +99,18 @@ func NewAgentPeer(cfg *config.Config, id string, role PeerRole, iceServers []web return nil, "", fmt.Errorf("create local track: %w", err) } - sender, err := pc.AddTrack(localTrack) + // Bind the local track to a sendrecv transceiver so the offer advertises + // both directions: we send customer audio to the browser, and we expect + // the browser's microphone audio back. AddTrack alone yields a sendonly + // m=audio, leaving the browser with nowhere to send mic audio. + transceiver, err := pc.AddTransceiverFromTrack(localTrack, webrtc.RTPTransceiverInit{ + Direction: webrtc.RTPTransceiverDirectionSendrecv, + }) if err != nil { pc.Close() - return nil, "", fmt.Errorf("add local track: %w", err) + return nil, "", fmt.Errorf("add audio transceiver: %w", err) } + sender := transceiver.Sender() // Consume RTCP packets from the sender to avoid blocking. go func() {