From 980dccea780a7c45b45fb4806ddd498843b83b0f Mon Sep 17 00:00:00 2001 From: Tanmay Deep Sharma Date: Tue, 21 Apr 2026 16:17:47 +0700 Subject: [PATCH] fix(media-server): use single sendrecv transceiver for Meta peer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The offer the media-server sent to Meta had two m=audio sections — one sendonly (from AddTrack creating an implicit transceiver) plus one recvonly (from an explicit AddTransceiverFromKind for outgoing calls). Meta rejected every outbound call with error 100 \"Invalid parameter\" at the terminate webhook, so the contact's phone never rang. Bind the local audio track to a single sendrecv transceiver via AddTransceiverFromTrack and drop the redundant recvonly transceiver. The offer is now a single m=audio sendrecv line with BUNDLE 0, which is what Meta expects. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../media-server/internal/peer/meta_peer.go | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/enterprise/media-server/internal/peer/meta_peer.go b/enterprise/media-server/internal/peer/meta_peer.go index 878a1410b..9d5f46866 100644 --- a/enterprise/media-server/internal/peer/meta_peer.go +++ b/enterprise/media-server/internal/peer/meta_peer.go @@ -88,11 +88,17 @@ func NewMetaPeer(cfg *config.Config, sdpOffer string, iceServers []webrtc.ICESer return nil, "", fmt.Errorf("create local track: %w", err) } - sender, err := pc.AddTrack(localTrack) + // Bind the local track to a single sendrecv transceiver. Using AddTrack + + // a separate recvonly transceiver yields two m=audio sections, which Meta + // rejects with error 100 "Invalid parameter". + 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() { @@ -167,15 +173,8 @@ func NewMetaPeer(cfg *config.Config, sdpOffer string, iceServers []webrtc.ICESer sdpResult = pc.LocalDescription().SDP } else { - // Outgoing call: we generate an offer to send to Meta. - // Add a recvonly transceiver so Meta knows we expect audio. - if _, err := pc.AddTransceiverFromKind(webrtc.RTPCodecTypeAudio, webrtc.RTPTransceiverInit{ - Direction: webrtc.RTPTransceiverDirectionRecvonly, - }); err != nil { - pc.Close() - return nil, "", fmt.Errorf("add audio transceiver: %w", err) - } - + // Outgoing call: we generate an offer to send to Meta. The sendrecv + // transceiver registered above already advertises both directions. offer, err := pc.CreateOffer(nil) if err != nil { pc.Close()