【问题标题】:Is there a way to choose codecs in WebRTC PeerConnection?有没有办法在 WebRTC PeerConnection 中选择编解码器?
【发布时间】:2014-02-19 14:20:57
【问题描述】:

嘿,我想知道在 WebRTC 中创建报价/答案时是否有任何方法可以选择编解码器。目前可供选择的视频编解码器不多,但有Opus、PCMU、PCMA等音频编解码器可供选择。

【问题讨论】:

    标签: webrtc codec getusermedia


    【解决方案1】:

    选择 Opus 只会让你成功一半。即使使用编解码器,它也可能默认为单声道和大约 42 kb/s,因为它主要是为语音设计的。

    如果您不使用语音输入,并且想要一致的音乐,您可以使用约束禁用音频处理功能:

    navigator.mediaDevices.getUserMedia({
      audio: {
        autoGainControl: false,
        channelCount: 2,
        echoCancellation: false,
        latency: 0,
        noiseSuppression: false,
        sampleRate: 48000,
        sampleSize: 16,
        volume: 1.0
      }
    });
    

    然后设置SDP为stereo,增加maxaveragebitrate

    let answer = await peer.conn.createAnswer(offerOptions);
    answer.sdp = answer.sdp.replace('useinbandfec=1', 'useinbandfec=1; stereo=1; maxaveragebitrate=510000');
    await peer.conn.setLocalDescription(answer);
    

    这应该输出一个如下所示的字符串:

    a=fmtp:111 minptime=10;useinbandfec=1; stereo=1; maxaveragebitrate=510000
    

    这为立体声提供了 520kb/s 的潜在最大比特率,即每通道 260kps。实际比特率取决于您的网络速度和信号强度。

    您可以阅读更多关于其他可用属性的信息:https://www.rfc-editor.org/rfc/rfc7587

    【讨论】:

      【解决方案2】:

      一般来说,是的。这是在建立连接期间如何首选 Opus 编解码器的示例。 您应该从 createAnswer 或 createOffer 的回调函数中调用“preferOpus”。

      var preferOpus = function(sdp) {
        var sdpLines = sdp.split('\r\n');
      
        for (var i = 0; i < sdpLines.length; i++) {
          if (sdpLines[i].search('m=audio') !== -1) {
            var mLineIndex = i;
            break;
          }
        }
      
        if (mLineIndex === null) return sdp;
      
        for (i = 0; i < sdpLines.length; i++) {
          if (sdpLines[i].search('opus/48000') !== -1) {
            var opusPayload = extractSdp(sdpLines[i], /:(\d+) opus\/48000/i);
            if (opusPayload) 
              sdpLines[mLineIndex] = setDefaultCodec(sdpLines[mLineIndex], opusPayload);
            break;
          }
        }
      
        sdpLines = removeCN(sdpLines, mLineIndex);
      
        sdp = sdpLines.join('\r\n');
        return sdp;
      };
      
      var extractSdp = function(sdpLine, pattern) {
        var result = sdpLine.match(pattern);
        return (result && result.length == 2)? result[1]: null;
      };
      
      var setDefaultCodec = function(mLine, payload) {
        var elements = mLine.split(' ');
        var newLine = new Array();
        var index = 0;
        for (var i = 0; i < elements.length; i++) {
          if (index === 3) newLine[index++] = payload;
          if (elements[i] !== payload) newLine[index++] = elements[i];
        }
        return newLine.join(' ');
      };
      
      var removeCN = function(sdpLines, mLineIndex) {
        var mLineElements = sdpLines[mLineIndex].split(' ');
        for (var i = sdpLines.length-1; i >= 0; i--) {
          var payload = extractSdp(sdpLines[i], /a=rtpmap:(\d+) CN\/\d+/i);
          if (payload) {
            var cnPos = mLineElements.indexOf(payload);
            if (cnPos !== -1) mLineElements.splice(cnPos, 1);
            sdpLines.splice(i, 1);
          }
        }
        sdpLines[mLineIndex] = mLineElements.join(' ');
        return sdpLines;
      };
      

      【讨论】:

      • 非常感谢这个伟大的代码。您能否用简单的英语详细说明您想要实现的目标?
      • @AdrianBer 的主要思想是采用 SDP 数据包并以这种方式更改相应的字段,以便默认情况下您希望使用的编解码器将出现在可用编解码器列表中。
      • 因此,实际上您可以找到 opus 编解码器的有效负载,并将其添加为以“m=audio”开头的行中的第三个元素(按优先顺序排列的第一个编解码器)。为什么还要删除带有 CN 的行?顺便说一句,在某处有解释 sdp 字符串格式的文档吗?
      • @AdrianBer 我有一个简短的博客笔记,其中包含另一个使用 SDP 的示例/案例:webrtcexample.com/blog/?go=all/… - 还有 SDP 的 RFC:tools.ietf.org/html/rfc4566 - 希望这对您有用
      • 同时,我写了一个 SDP 解析器来更好地处理这种事情:github.com/beradrian/sdpparser
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-18
      • 1970-01-01
      • 2011-08-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多