<!DOCTYPE html><html><head><title></title><style type="text/css">p.MsoNormal,p.MsoNoSpacing{margin:0}</style></head><body><div>I am trying to write the contents of an RTP-OPUS stream to an OGG-OPUS file. The purpose is to send a WebRTC session to Google's Speech-to-text API, which accepts OGG-OPUS as input.<br></div><div><br></div><div>The opus muxer requires that an opus header be present in extradata. It seems that the demuxer from my RTP stream doesn't include this.<br></div><div><br></div><div>If I construct the opus header myself and insert it into extradata, everything works great. This seems like a hack though. Is this something that the RTP demuxer should be doing?<br></div><div><br></div><div>Here is the code. I'm using some node bindings for libavformat called "beamcoder". I can reproduce the same issue with the ffmpeg commandline.<br></div><div><br></div><div> const demuxer = await beamcoder.demuxer({<br></div><div> url: 'file:input.sdp',<br></div><div> options: {<br></div><div> protocol_whitelist: "file,rtp,udp"<br></div><div> }<br></div><div> });<br></div><div><br></div><div><br></div><div> // Construct an Oups Header.<br></div><div> // This seems like a hack, but is required to get the opux muxer to work<br></div><div> const opusHeader = Buffer.alloc(19);<br></div><div> // <a href="https://www.opus-codec.org/docs/opusfile_api-0.4/structOpusHead.html#details">https://www.opus-codec.org/docs/opusfile_api-0.4/structOpusHead.html#details</a><br></div><div> // <a href="https://github.com/xiph/opusfile/blob/4174c26e0aaab19d01afdea0a46f7f95fdc6b3e6/src/info.c#L40">https://github.com/xiph/opusfile/blob/4174c26e0aaab19d01afdea0a46f7f95fdc6b3e6/src/info.c#L40</a><br></div><div> // magic bytes for opus<br></div><div> opusHeader.write('OpusHead', 0, 8, "ascii");<br></div><div> // Version<br></div><div> opusHeader.writeUInt8(1, 8);<br></div><div> // Channel count<br></div><div> opusHeader.writeUInt8(2, 9);<br></div><div> // Pre skip<br></div><div> opusHeader.writeUInt16LE(0, 10);<br></div><div> // Sample rate<br></div><div> opusHeader.writeUInt32LE(48000, 12);<br></div><div> // Output gain (db)<br></div><div> opusHeader.writeUInt16LE(0, 16);<br></div><div> // Mapping family<br></div><div> opusHeader.writeUInt8(0, 18);<br></div><div><br></div><div> const streamConfig = demuxer.streams[0];<br></div><div> streamConfig.codecpar.extradata = opusHeader;<br></div><div><br></div><div> const muxer = await beamcoder.muxer({ filename: 'file:test.opus' });<br></div><div><br></div><div> const stream = muxer.newStream(demuxer.streams[0]);<br></div><div> await muxer.openIO();<br></div><div><br></div><div> // This invokes avformat_write_header, which will raise a "no extradata present" error unless I build my own opus header.<br></div><div> // The error is raised from inside oggenc.c / ogg_init<br></div><div> await muxer.writeHeader();<br></div><div><br></div><div> while (true) {<br></div><div> const packet = await demuxer.read();<br></div><div> if (packet == null)<br></div><div> break;<br></div><div> await muxer.writeFrame(packet);<br></div><div> }<br></div><div> await muxer.writeTrailer();<br></div><div><br></div><div>This is my SDP file:<br></div><div><br></div><div> v=0<br></div><div> o=- 0 0 IN IP4 127.0.0.1<br></div><div> s=Mediasoup<br></div><div> c=IN IP4 127.0.0.1<br></div><div> t =0 0<br></div><div> m=audio 5004 RTP/AVPF 100<br></div><div> a=rtcp:5005<br></div><div> a=rtpmap:100 opus/48000/2<br></div><div><br></div><div>I asked a similar question yesterday in the ffmpeg-users list, but I think it may be more appropriate here:<br></div><div><br></div><div><a href="http://www.ffmpeg-archive.org/Error-raised-in-oggenc-c-when-trying-to-create-opus-file-from-RTP-stream-td4694549.html">http://www.ffmpeg-archive.org/Error-raised-in-oggenc-c-when-trying-to-create-opus-file-from-RTP-stream-td4694549.html</a><br></div></body></html>