【发布时间】:2014-02-19 14:20:57
【问题描述】:
嘿,我想知道在 WebRTC 中创建报价/答案时是否有任何方法可以选择编解码器。目前可供选择的视频编解码器不多,但有Opus、PCMU、PCMA等音频编解码器可供选择。
【问题讨论】:
标签: webrtc codec getusermedia
嘿,我想知道在 WebRTC 中创建报价/答案时是否有任何方法可以选择编解码器。目前可供选择的视频编解码器不多,但有Opus、PCMU、PCMA等音频编解码器可供选择。
【问题讨论】:
标签: webrtc codec getusermedia
选择 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
【讨论】:
一般来说,是的。这是在建立连接期间如何首选 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;
};
【讨论】: