新版本的WebRTC支持在已经建立连接的情况下,推流端动态修改编码器。在Chrome119版本中可以体验这个功能了。可以在chrome 119版本,通过两个网页进行webrtc通信,使用chrome://webrtc-internals来查看使用的编码器。
效果
实现方法
核心代码
在RTCPeerConnection建立连接之后,在推流端通过RTPSender.setParameters方法,可以支持动态切换编码器
let sender = pc_pub.getSenders()[0];
let param = sender.getParameters();
param.encodings[0].codec = codec;
sender.setParameters(param).then(() => {
console.log("change encoder suc");
}).catch((err) => {
console.log("change encoder fail");
})
步骤
使用WebRTC建立连接的部分可以参考: 前端使用WebRTC———局域网内单向通信。本文的代码就是在这个代码的基础上增加了切换编码器的逻辑。
- 获取RTCRtpSender
在RTCPeerConnection建立连接完成以后,可以通过RTCPeerConnection.getSender方法来获取RTCRtpSender对象。因为例子中只有一个发送流,所以在返回的数据中直接取第一个就可以
let sender = pc_pub.getSenders()[0];
- 获取RTCRtpSendParameters
通过RTCRtpSender.getParameters方法来获取RTCRtpSendParameters对象。
let param = sender.getParameters();
- 获取当前支持的编码器
RTCRtpSendParameters.codecs字段可以看到当前连接支持的所有编码器,如下图
mimeType字段的内容是video/VP8、video/VP9、video/AV1、video/H264这些是编码器。其他的不是编码器。 - 设置新的编码器
RTCRtpSendParameters.codecs中选择好编码器之后,将编码器赋值param.encodings[0].codec;然后通过RTCRtpSendParameters.setParameters方法将param设置给RTCRtpSender,通过返回的Promise来判断设置是否生效了。
// codec是从RTCRtpSendParameters.codecs中选择好的内容
param.encodings[0].codec = codec;
sender.setParameters(param).then(() => {
console.log("change encoder suc");
}).catch((err) => {
console.log("change encoder fail");
})
实际应用
当使用WebRTC进行通信时,有可能在拉流端有些异常的行为,比如解码失败、解码耗时高等情况,此时可以通过以上方法动态的切换编码器,对应的拉流端也会切换到新的解码器进行解码
代码
可以直接从[gittee](https://gitee.com/doubaoa/web-media/tree/master/webrtc-demo/changeencoder)
获取源代码,也可以直接使用下面的代码
服务端
要注意server依赖了nodejs-websocket模块。
var ws = require("nodejs-websocket");
var pub_ws = null;
var sub_ws = null;
function start() {
var msg = JSON.stringify({
type: "start" });
pub_ws.send(msg);
}
var server = ws.createServer(function (conn) {
// 收到websocket连接
conn.on("text", function (str) {
if (pub_ws === conn) {
if (sub_ws) {
sub_ws.send(str);
}
} else if (sub_ws === conn) {
if (pub_ws) {
pub_ws.send(str);
}
} else {
let obj = JSON.parse(str);
if (obj.type === 'publish') {
pub_ws