>> So I’m not sure how ffmpeg parses SDP files or if it uses a library but when you step back and take a look, you haven’t put in any specifics for either codec besides from maybe their names. >> >> v=0 >> o=- 0 0 IN IP4 127.0.0.1 >> s=- >> c=IN IP4 127.0.0.1 >> t=0 0 >> m=audio 5006 RTP/AVP 109 >> a=rtpmap:109 opus/48000/2 >> m=video 5004 RTP/AVP 120 >> a=rtpmap:120 VP8/90000 > > You can try reading the rfc’s and filling in the extra codec info it needs, but if you’re the one setting up the session, why not just use a simpler protocol? (I’m assuming the localhost is just a stand-in) > >> However, the issue persists when trying to record Opus audio; it is just >> not possible to play it back, supposedly due to missing headers (but >> then how is it possible to record incoming RTP Opus audio?) > > Like, you told ffmpeg it was going to be 48khz, 2 chs it believed your copy codec and just dumped everything into a file. But when you open up the file, does it really have two channels? is the audio interleaved? Nobody knows. >
I just want to have a working command to record RTP media received from an RTP router, in this case it is MediaSoup, which receives a WebRTC stream from Chrome, then redistributes it as plain RTP. I first tried using plain "rtp://" URL, but the ffmpeg command itself told me that an SDP input file would be needed to use dynamic Payload Types (which is totally sensible). This is a standard SDP Offer as generated by Chrome to create a WebRTC session: v=0 o=- 6323209318560568134 2 IN IP4 127.0.0.1 s=- t=0 0 a=group:BUNDLE 0 1 a=msid-semantic: WMS XAb2pgeSAM6YZw6uCRj11AE5Raf3cKHPNGl0 m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126 c=IN IP4 0.0.0.0 a=rtcp:9 IN IP4 0.0.0.0 a=ice-ufrag:Ao6s a=ice-pwd:h3NoIquJSZ8L/yQUSy7nme5Y a=ice-options:trickle a=fingerprint:sha-256 21:D2:14:1E:49:95:70:0B:A6:0B:93:5C:E5:A9:35:B0:8A:48:3C:95:75:06:62:74:5A:2B:99:29:0F:D0:3E:FB a=setup:actpass a=mid:0 a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level a=extmap:2 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01 a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id a=sendrecv a=msid:XAb2pgeSAM6YZw6uCRj11AE5Raf3cKHPNGl0 816c42db-7d97-4053-86a0-bae0e5010985 a=rtcp-mux a=rtpmap:111 opus/48000/2 a=rtcp-fb:111 transport-cc a=fmtp:111 minptime=10;useinbandfec=1 a=rtpmap:103 ISAC/16000 a=rtpmap:104 ISAC/32000 a=rtpmap:9 G722/8000 a=rtpmap:0 PCMU/8000 a=rtpmap:8 PCMA/8000 a=rtpmap:106 CN/32000 a=rtpmap:105 CN/16000 a=rtpmap:13 CN/8000 a=rtpmap:110 telephone-event/48000 a=rtpmap:112 telephone-event/32000 a=rtpmap:113 telephone-event/16000 a=rtpmap:126 telephone-event/8000 a=ssrc:3169356447 cname:XZAw22pKY7Y9bCph a=ssrc:3169356447 msid:XAb2pgeSAM6YZw6uCRj11AE5Raf3cKHPNGl0 816c42db-7d97-4053-86a0-bae0e5010985 a=ssrc:3169356447 mslabel:XAb2pgeSAM6YZw6uCRj11AE5Raf3cKHPNGl0 a=ssrc:3169356447 label:816c42db-7d97-4053-86a0-bae0e5010985 m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102 122 127 121 125 107 108 109 124 120 123 c=IN IP4 0.0.0.0 a=rtcp:9 IN IP4 0.0.0.0 a=ice-ufrag:Ao6s a=ice-pwd:h3NoIquJSZ8L/yQUSy7nme5Y a=ice-options:trickle a=fingerprint:sha-256 21:D2:14:1E:49:95:70:0B:A6:0B:93:5C:E5:A9:35:B0:8A:48:3C:95:75:06:62:74:5A:2B:99:29:0F:D0:3E:FB a=setup:actpass a=mid:1 a=extmap:14 urn:ietf:params:rtp-hdrext:toffset a=extmap:13 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time a=extmap:12 urn:3gpp:video-orientation a=extmap:2 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01 a=extmap:11 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing a=extmap:8 http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07 a=extmap:9 http://www.webrtc.org/experiments/rtp-hdrext/color-space a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id a=sendrecv a=msid:XAb2pgeSAM6YZw6uCRj11AE5Raf3cKHPNGl0 0c05ddde-b52e-4776-97f0-755ded96e15d a=rtcp-mux a=rtcp-rsize a=rtpmap:96 VP8/90000 a=rtcp-fb:96 goog-remb a=rtcp-fb:96 transport-cc a=rtcp-fb:96 ccm fir a=rtcp-fb:96 nack a=rtcp-fb:96 nack pli a=rtpmap:97 rtx/90000 a=fmtp:97 apt=96 a=rtpmap:98 VP9/90000 a=rtcp-fb:98 goog-remb a=rtcp-fb:98 transport-cc a=rtcp-fb:98 ccm fir a=rtcp-fb:98 nack a=rtcp-fb:98 nack pli a=fmtp:98 profile-id=0 a=rtpmap:99 rtx/90000 a=fmtp:99 apt=98 a=rtpmap:100 VP9/90000 a=rtcp-fb:100 goog-remb a=rtcp-fb:100 transport-cc a=rtcp-fb:100 ccm fir a=rtcp-fb:100 nack a=rtcp-fb:100 nack pli a=fmtp:100 profile-id=2 a=rtpmap:101 rtx/90000 a=fmtp:101 apt=100 a=rtpmap:102 H264/90000 a=rtcp-fb:102 goog-remb a=rtcp-fb:102 transport-cc a=rtcp-fb:102 ccm fir a=rtcp-fb:102 nack a=rtcp-fb:102 nack pli a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f a=rtpmap:122 rtx/90000 a=fmtp:122 apt=102 a=rtpmap:127 H264/90000 a=rtcp-fb:127 goog-remb a=rtcp-fb:127 transport-cc a=rtcp-fb:127 ccm fir a=rtcp-fb:127 nack a=rtcp-fb:127 nack pli a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f a=rtpmap:121 rtx/90000 a=fmtp:121 apt=127 a=rtpmap:125 H264/90000 a=rtcp-fb:125 goog-remb a=rtcp-fb:125 transport-cc a=rtcp-fb:125 ccm fir a=rtcp-fb:125 nack a=rtcp-fb:125 nack pli a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f a=rtpmap:107 rtx/90000 a=fmtp:107 apt=125 a=rtpmap:108 H264/90000 a=rtcp-fb:108 goog-remb a=rtcp-fb:108 transport-cc a=rtcp-fb:108 ccm fir a=rtcp-fb:108 nack a=rtcp-fb:108 nack pli a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f a=rtpmap:109 rtx/90000 a=fmtp:109 apt=108 a=rtpmap:124 red/90000 a=rtpmap:120 rtx/90000 a=fmtp:120 apt=124 a=rtpmap:123 ulpfec/90000 a=ssrc-group:FID 3597912382 1560435023 a=ssrc:3597912382 cname:XZAw22pKY7Y9bCph a=ssrc:3597912382 msid:XAb2pgeSAM6YZw6uCRj11AE5Raf3cKHPNGl0 0c05ddde-b52e-4776-97f0-755ded96e15d a=ssrc:3597912382 mslabel:XAb2pgeSAM6YZw6uCRj11AE5Raf3cKHPNGl0 a=ssrc:3597912382 label:0c05ddde-b52e-4776-97f0-755ded96e15d a=ssrc:1560435023 cname:XZAw22pKY7Y9bCph a=ssrc:1560435023 msid:XAb2pgeSAM6YZw6uCRj11AE5Raf3cKHPNGl0 0c05ddde-b52e-4776-97f0-755ded96e15d a=ssrc:1560435023 mslabel:XAb2pgeSAM6YZw6uCRj11AE5Raf3cKHPNGl0 a=ssrc:1560435023 label:0c05ddde-b52e-4776-97f0-755ded96e15d If you notice, there is a lot of metadata about the RTP session (ssrc, cname), some about the ICE protocol (for WebRTC), but there isn't much information there about the specifics of the codecs. In this case, the preferred audio payload type is 111, which corresponds to the OPUS codec. The specification "opus/48000/2" is expected to already convey enough information to let the other peer know what codec it is going to receive, and it allows for some (much) variance in the actual encoding parameters that are going to be used; the receiver is just able to auto-detect those and decode the stream. For the cases where the codec has really incompatible profiles, to the point where trying to decode with the wrong profile would fail, then that information is also transmitted in the SDP; this is the case of the H.264 profile levels (Baseline, Main, High, etc.), which are then accordingly transmitted in the SDP Offer as totally different Payload Types. But you'll notice that other codecs, like VP8, don't really need such distinction. Of course, such an SDP Offer is not really missing any crucial detail; another browser such as Chrome, Firefox, Safari, etc. will be able to receive and decode the incoming audio and video. So what I'm really trying to do is doing the same with FFmpeg... now if you compare Chrome's SDP with mine, it turns out mine does already have all relevant details that are included in a "full-blown" SDP message. _______________________________________________ ffmpeg-user mailing list [email protected] https://ffmpeg.org/mailman/listinfo/ffmpeg-user To unsubscribe, visit link above, or email [email protected] with subject "unsubscribe".
