From ef5750578e2f37aba5f82dc9afe20a0df82c4f74 Mon Sep 17 00:00:00 2001 From: aler9 <46489434+aler9@users.noreply.github.com> Date: Mon, 27 May 2024 23:50:54 +0200 Subject: [PATCH] webrtc: support reading and proxying stereo PCMU/PCMA tracks --- go.mod | 10 +-- go.sum | 19 ++--- internal/protocols/webrtc/incoming_track.go | 82 ++++++++++++++++++--- internal/protocols/webrtc/outgoing_track.go | 38 +++++++++- internal/servers/webrtc/read_index.html | 16 +++- internal/servers/webrtc/server_test.go | 2 +- internal/servers/webrtc/session.go | 12 --- 7 files changed, 134 insertions(+), 45 deletions(-) diff --git a/go.mod b/go.mod index 211b046f0d9..abb7e09b3ca 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/gorilla/websocket v1.5.1 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/matthewhartstonge/argon2 v1.0.0 - github.com/pion/ice/v2 v2.3.11 + github.com/pion/ice/v2 v2.3.24 github.com/pion/interceptor v0.1.29 github.com/pion/logging v0.2.2 github.com/pion/rtcp v1.2.14 @@ -58,12 +58,12 @@ require ( github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pion/datachannel v1.5.5 // indirect github.com/pion/dtls/v2 v2.2.7 // indirect - github.com/pion/mdns v0.0.9 // indirect + github.com/pion/mdns v0.0.12 // indirect github.com/pion/randutil v0.1.0 // indirect - github.com/pion/sctp v1.8.8 // indirect + github.com/pion/sctp v1.8.16 // indirect github.com/pion/srtp/v2 v2.0.18 // indirect github.com/pion/stun v0.6.1 // indirect - github.com/pion/transport/v2 v2.2.3 // indirect + github.com/pion/transport/v2 v2.2.4 // indirect github.com/pion/turn/v2 v2.1.3 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect @@ -81,4 +81,4 @@ replace code.cloudfoundry.org/bytefmt => github.com/cloudfoundry/bytefmt v0.0.0- replace github.com/pion/ice/v2 => github.com/aler9/ice/v2 v2.0.0-20231112223552-32d34dfcf3a1 -replace github.com/pion/webrtc/v3 => github.com/aler9/webrtc/v3 v3.0.0-20231112223655-e402ed2689c6 +replace github.com/pion/webrtc/v3 => github.com/aler9/webrtc/v3 v3.0.0-20240527213244-d3ff0bd9230f diff --git a/go.sum b/go.sum index 8ef3b0a0fe6..4f5183ca67d 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/aler9/ice/v2 v2.0.0-20231112223552-32d34dfcf3a1 h1:fD6eZt+3/t8bzFn6ZZA2eP63xBP06v3EPfPJu8DO8ys= github.com/aler9/ice/v2 v2.0.0-20231112223552-32d34dfcf3a1/go.mod h1:lT3kv5uUIlHfXHU/ZRD7uKD/ufM202+eTa3C/umgGf4= -github.com/aler9/webrtc/v3 v3.0.0-20231112223655-e402ed2689c6 h1:wMd3D1mLghoYYh31STig8Kwm2qi8QyQKUy09qUUZrVw= -github.com/aler9/webrtc/v3 v3.0.0-20231112223655-e402ed2689c6/go.mod h1:1CaT2fcZzZ6VZA+O1i9yK2DU4EOcXVvSbWG9pr5jefs= +github.com/aler9/webrtc/v3 v3.0.0-20240527213244-d3ff0bd9230f h1:IcGmhy+mh/cDCHR8BBDI8iUGeV2/O1A/qqoR3yi62Z0= +github.com/aler9/webrtc/v3 v3.0.0-20240527213244-d3ff0bd9230f/go.mod h1:1CaT2fcZzZ6VZA+O1i9yK2DU4EOcXVvSbWG9pr5jefs= github.com/asticode/go-astikit v0.30.0 h1:DkBkRQRIxYcknlaU7W7ksNfn4gMFsB0tqMJflxkRsZA= github.com/asticode/go-astikit v0.30.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0= github.com/asticode/go-astits v1.13.0 h1:XOgkaadfZODnyZRR5Y0/DWkA9vrkLLPLeeOvDwfKZ1c= @@ -143,8 +143,8 @@ github.com/pion/interceptor v0.1.29/go.mod h1:ri+LGNjRUc5xUNtDEPzfdkmSqISixVTBF/ github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/mdns v0.0.7/go.mod h1:4iP2UbeFhLI/vWju/bw6ZfwjJzk0z8DNValjGxR/dD8= -github.com/pion/mdns v0.0.9 h1:7Ue5KZsqq8EuqStnpPWV33vYYEH0+skdDN5L7EiEsI4= -github.com/pion/mdns v0.0.9/go.mod h1:2JA5exfxwzXiCihmxpTKgFUpiQws2MnipoPK09vecIc= +github.com/pion/mdns v0.0.12 h1:CiMYlY+O0azojWDmxdNr7ADGrnZ+V6Ilfner+6mSVK8= +github.com/pion/mdns v0.0.12/go.mod h1:VExJjv8to/6Wqm1FXK+Ii/Z9tsVk/F5sD/N70cnYFbk= github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I= @@ -156,8 +156,9 @@ github.com/pion/rtp v1.8.3/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU github.com/pion/rtp v1.8.7-0.20240429002300-bc5124c9d0d0 h1:yPAphilskTN7U3URvBVxlVr0PzheMeWqo7PaOqh//Hg= github.com/pion/rtp v1.8.7-0.20240429002300-bc5124c9d0d0/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0= -github.com/pion/sctp v1.8.8 h1:5EdnnKI4gpyR1a1TwbiS/wxEgcUWBHsc7ILAjARJB+U= github.com/pion/sctp v1.8.8/go.mod h1:igF9nZBrjh5AtmKc7U30jXltsFHicFCXSmWA2GWRaWs= +github.com/pion/sctp v1.8.16 h1:PKrMs+o9EMLRvFfXq59WFsC+V8mN1wnKzqrv+3D/gYY= +github.com/pion/sctp v1.8.16/go.mod h1:P6PbDVA++OJMrVNg2AL3XtYHV4uD6dvfyOovCgMs0PE= github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw= github.com/pion/sdp/v3 v3.0.9 h1:pX++dCHoHUwq43kuwf3PyJfHlwIj4hXA7Vrifiq0IJY= github.com/pion/sdp/v3 v3.0.9/go.mod h1:B5xmvENq5IXJimIO4zfp6LAe1fD9N+kFv+V/1lOdz8M= @@ -169,8 +170,9 @@ github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40 github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI= github.com/pion/transport/v2 v2.0.0/go.mod h1:HS2MEBJTwD+1ZI2eSXSvHJx/HnzQqRy2/LXxt6eVMHc= github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= -github.com/pion/transport/v2 v2.2.3 h1:XcOE3/x41HOSKbl1BfyY1TF1dERx7lVvlMCbXU7kfvA= github.com/pion/transport/v2 v2.2.3/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= +github.com/pion/transport/v2 v2.2.4 h1:41JJK6DZQYSeVLxILA2+F4ZkKb4Xd/tFJZRFZQ9QAlo= +github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= github.com/pion/transport/v3 v3.0.2 h1:r+40RJR25S9w3jbA6/5uEPTzcdn7ncyU44RWCbHkLg4= github.com/pion/transport/v3 v3.0.2/go.mod h1:nIToODoOlb5If2jF9y2Igfx3PFYWfuXi37m0IlWa/D0= @@ -215,7 +217,6 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -236,7 +237,6 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -268,7 +268,6 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -280,7 +279,6 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -293,7 +291,6 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= diff --git a/internal/protocols/webrtc/incoming_track.go b/internal/protocols/webrtc/incoming_track.go index 269863407dc..9146e80884c 100644 --- a/internal/protocols/webrtc/incoming_track.go +++ b/internal/protocols/webrtc/incoming_track.go @@ -20,20 +20,36 @@ const ( ) var incomingVideoCodecs = []webrtc.RTPCodecParameters{ + { + RTPCodecCapability: webrtc.RTPCodecCapability{ + MimeType: webrtc.MimeTypeAV1, + ClockRate: 90000, + SDPFmtpLine: "profile-id=1", + }, + PayloadType: 96, + }, { RTPCodecCapability: webrtc.RTPCodecCapability{ MimeType: webrtc.MimeTypeAV1, ClockRate: 90000, }, - PayloadType: 96, + PayloadType: 97, }, { RTPCodecCapability: webrtc.RTPCodecCapability{ MimeType: webrtc.MimeTypeVP9, ClockRate: 90000, - SDPFmtpLine: "profile-id=0", + SDPFmtpLine: "profile-id=3", }, - PayloadType: 97, + PayloadType: 98, + }, + { + RTPCodecCapability: webrtc.RTPCodecCapability{ + MimeType: webrtc.MimeTypeVP9, + ClockRate: 90000, + SDPFmtpLine: "profile-id=2", + }, + PayloadType: 99, }, { RTPCodecCapability: webrtc.RTPCodecCapability{ @@ -41,14 +57,22 @@ var incomingVideoCodecs = []webrtc.RTPCodecParameters{ ClockRate: 90000, SDPFmtpLine: "profile-id=1", }, - PayloadType: 98, + PayloadType: 100, + }, + { + RTPCodecCapability: webrtc.RTPCodecCapability{ + MimeType: webrtc.MimeTypeVP9, + ClockRate: 90000, + SDPFmtpLine: "profile-id=0", + }, + PayloadType: 101, }, { RTPCodecCapability: webrtc.RTPCodecCapability{ MimeType: webrtc.MimeTypeVP8, ClockRate: 90000, }, - PayloadType: 99, + PayloadType: 102, }, { RTPCodecCapability: webrtc.RTPCodecCapability{ @@ -56,7 +80,7 @@ var incomingVideoCodecs = []webrtc.RTPCodecParameters{ ClockRate: 90000, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f", }, - PayloadType: 100, + PayloadType: 103, }, { RTPCodecCapability: webrtc.RTPCodecCapability{ @@ -64,7 +88,7 @@ var incomingVideoCodecs = []webrtc.RTPCodecParameters{ ClockRate: 90000, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f", }, - PayloadType: 101, + PayloadType: 104, }, } @@ -85,6 +109,22 @@ var incomingAudioCodecs = []webrtc.RTPCodecParameters{ }, PayloadType: 9, }, + { + RTPCodecCapability: webrtc.RTPCodecCapability{ + MimeType: webrtc.MimeTypePCMU, + ClockRate: 8000, + Channels: 2, + }, + PayloadType: 118, + }, + { + RTPCodecCapability: webrtc.RTPCodecCapability{ + MimeType: webrtc.MimeTypePCMA, + ClockRate: 8000, + Channels: 2, + }, + PayloadType: 119, + }, { RTPCodecCapability: webrtc.RTPCodecCapability{ MimeType: webrtc.MimeTypePCMU, @@ -166,19 +206,39 @@ func newIncomingTrack( t.format = &format.G722{} case strings.ToLower(webrtc.MimeTypePCMU): + channels := track.Codec().Channels + if channels == 0 { + channels = 1 + } + + payloadType := uint8(0) + if channels > 1 { + payloadType = 118 + } + t.format = &format.G711{ - PayloadTyp: 0, + PayloadTyp: payloadType, MULaw: true, SampleRate: 8000, - ChannelCount: 1, + ChannelCount: int(channels), } case strings.ToLower(webrtc.MimeTypePCMA): + channels := track.Codec().Channels + if channels == 0 { + channels = 1 + } + + payloadType := uint8(8) + if channels > 1 { + payloadType = 119 + } + t.format = &format.G711{ - PayloadTyp: 8, + PayloadTyp: payloadType, MULaw: false, SampleRate: 8000, - ChannelCount: 1, + ChannelCount: int(channels), } default: diff --git a/internal/protocols/webrtc/outgoing_track.go b/internal/protocols/webrtc/outgoing_track.go index f02c66fe4f4..9c67d0d7e41 100644 --- a/internal/protocols/webrtc/outgoing_track.go +++ b/internal/protocols/webrtc/outgoing_track.go @@ -33,7 +33,7 @@ func (t *OutgoingTrack) codecParameters() (webrtc.RTPCodecParameters, error) { ClockRate: 90000, SDPFmtpLine: "profile-id=1", }, - PayloadType: 98, + PayloadType: 96, }, nil case *format.VP8: @@ -42,7 +42,7 @@ func (t *OutgoingTrack) codecParameters() (webrtc.RTPCodecParameters, error) { MimeType: webrtc.MimeTypeVP8, ClockRate: 90000, }, - PayloadType: 99, + PayloadType: 96, }, nil case *format.H264: @@ -52,17 +52,21 @@ func (t *OutgoingTrack) codecParameters() (webrtc.RTPCodecParameters, error) { ClockRate: 90000, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f", }, - PayloadType: 101, + PayloadType: 96, }, nil case *format.Opus: + if forma.ChannelCount > 2 { + return webrtc.RTPCodecParameters{}, fmt.Errorf("unsupported Opus channel count: %d", forma.ChannelCount) + } + return webrtc.RTPCodecParameters{ RTPCodecCapability: webrtc.RTPCodecCapability{ MimeType: webrtc.MimeTypeOpus, ClockRate: 48000, Channels: 2, }, - PayloadType: 111, + PayloadType: 96, }, nil case *format.G722: @@ -75,7 +79,22 @@ func (t *OutgoingTrack) codecParameters() (webrtc.RTPCodecParameters, error) { }, nil case *format.G711: + if forma.SampleRate != 8000 { + return webrtc.RTPCodecParameters{}, fmt.Errorf("unsupported G711 sample rate") + } + if forma.MULaw { + if forma.ChannelCount != 1 { + return webrtc.RTPCodecParameters{ + RTPCodecCapability: webrtc.RTPCodecCapability{ + MimeType: webrtc.MimeTypePCMU, + ClockRate: uint32(forma.SampleRate), + Channels: uint16(forma.ChannelCount), + }, + PayloadType: 96, + }, nil + } + return webrtc.RTPCodecParameters{ RTPCodecCapability: webrtc.RTPCodecCapability{ MimeType: webrtc.MimeTypePCMU, @@ -85,6 +104,17 @@ func (t *OutgoingTrack) codecParameters() (webrtc.RTPCodecParameters, error) { }, nil } + if forma.ChannelCount != 1 { + return webrtc.RTPCodecParameters{ + RTPCodecCapability: webrtc.RTPCodecCapability{ + MimeType: webrtc.MimeTypePCMA, + ClockRate: uint32(forma.SampleRate), + Channels: uint16(forma.ChannelCount), + }, + PayloadType: 96, + }, nil + } + return webrtc.RTPCodecParameters{ RTPCodecCapability: webrtc.RTPCodecCapability{ MimeType: webrtc.MimeTypePCMA, diff --git a/internal/servers/webrtc/read_index.html b/internal/servers/webrtc/read_index.html index 78a2026c61d..4ae88043061 100644 --- a/internal/servers/webrtc/read_index.html +++ b/internal/servers/webrtc/read_index.html @@ -107,6 +107,20 @@ return ret; }; +const enableStereoPcmau = (section) => { + let lines = section.split('\r\n'); + + lines[0] += " 118"; + lines.splice(lines.length - 1, 0, "a=rtpmap:118 PCMU/8000/2"); + lines.splice(lines.length - 1, 0, "a=rtcp-fb:118 transport-cc"); + + lines[0] += " 119"; + lines.splice(lines.length - 1, 0, "a=rtpmap:119 PCMA/8000/2"); + lines.splice(lines.length - 1, 0, "a=rtcp-fb:119 transport-cc"); + + return lines.join('\r\n'); +}; + const enableStereoOpus = (section) => { let opusPayloadFormat = ''; let lines = section.split('\r\n'); @@ -142,7 +156,7 @@ for (let i = 0; i < sections.length; i++) { const section = sections[i]; if (section.startsWith('audio')) { - sections[i] = enableStereoOpus(section); + sections[i] = enableStereoPcmau(enableStereoOpus(section)); } } diff --git a/internal/servers/webrtc/server_test.go b/internal/servers/webrtc/server_test.go index 38727792bb4..b87e63c01ae 100644 --- a/internal/servers/webrtc/server_test.go +++ b/internal/servers/webrtc/server_test.go @@ -423,7 +423,7 @@ func TestServerRead(t *testing.T) { Header: rtp.Header{ Version: 2, Marker: true, - PayloadType: 101, + PayloadType: 104, SequenceNumber: pkt.SequenceNumber, Timestamp: pkt.Timestamp, SSRC: pkt.SSRC, diff --git a/internal/servers/webrtc/session.go b/internal/servers/webrtc/session.go index e921a4b098c..4d582582063 100644 --- a/internal/servers/webrtc/session.go +++ b/internal/servers/webrtc/session.go @@ -216,10 +216,6 @@ func findAudioTrack( if opusFormat != nil { return opusFormat, func(track *webrtc.OutgoingTrack) error { - if opusFormat.ChannelCount > 2 { - return fmt.Errorf("unsupported Opus channel count: %d", opusFormat.ChannelCount) - } - stream.AddReader(writer, media, opusFormat, func(u unit.Unit) error { for _, pkt := range u.GetRTPPackets() { track.WriteRTP(pkt) //nolint:errcheck @@ -252,14 +248,6 @@ func findAudioTrack( if g711Format != nil { return g711Format, func(track *webrtc.OutgoingTrack) error { - if g711Format.SampleRate != 8000 { - return fmt.Errorf("unsupported G711 sample rate") - } - - if g711Format.ChannelCount != 1 { - return fmt.Errorf("unsupported G711 channel count") - } - stream.AddReader(writer, media, g711Format, func(u unit.Unit) error { for _, pkt := range u.GetRTPPackets() { track.WriteRTP(pkt) //nolint:errcheck