js中webrtc关键帧

js中使用webrtc,关键帧发送频率怎么设置,在什么地方设置

在 WebRTC 中,发送端(即 RTCPeerConnection 的本地端)可以通过 RTCConfiguration 中的 video 字段来配置关键帧间隔。具体来说,需要设置 RTCVideoEncoderFactory 中的 encoderSpecificSettings 属性,以指定编码器的相关参数,其中包括关键帧间隔。例如:

// 创建编码器工厂对象
const encoderFactory = new RTCVideoEncoderFactory({
  encoderSpecificSettings: {
    // 设置关键帧间隔为 30 帧
    keyFrameInterval: 30
  }
});

// 创建 PeerConnection 对象,并指定编码器工厂
const pc = new RTCPeerConnection({
  video: {
    encoderFactory
  }
});

在上面的示例中,我们创建了一个 RTCVideoEncoderFactory 对象,并将关键帧间隔设置为 30 帧。然后,我们将该编码器工厂对象传递给 RTCPeerConnection 的构造函数中,以指定使用该编码器工厂进行视频编码。

需要注意的是,不同的编码器可能会有不同的参数配置方式。如果你使用的是不同的编码器,可以查看该编码器的文档,以了解如何设置关键帧间隔。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这篇文章:webrtc打开默认音频设备 也许有你想要的答案,你可以看看
  • 除此之外, 这篇博客: 纯JS实现WebRTC点对点视频通话用于学习WebRTC中的 1. 页面代码主要的实现逻辑 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    先看页面代码,这里使用的webRTC浏览器原生的API。目前信令服务器使用的是Java SpringBoot WebSocket实现的。这里是在内网环境下测试,如果在公网环境中测试还需要配置STUN\TURN服务器,在代码iceServers处配置。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>video</title>
    </head>
    <body>
    <h2 style="text-align: center;">播放页面</h2>
    <h3 id="userId" style="text-align: center;"></h3>
    <center>
        <div>
            <video id="localVideo" class="video" autoplay="autoplay"></video>
            <video id="remoteVideo" class="video" height="500px" autoplay="autoplay"></video>
        </div>
    </center>
    </br>
    <div style="text-align: center;">
        <button id="callBtn" onclick="requestConnect()">建立连接</button>
        <button id="hangupBtn" onclick="hangupHandle()">断开连接</button>
    </div>
    </br>
    <div style="text-align: center;">
        对方id: <input id="toUserId">
    </div>
    </body>
    </html>
    <script src="./adapter-latest.js"></script>
    <script>
        const localVideo = document.querySelector('#localVideo');
        const remoteVideo = document.querySelector('#remoteVideo');
    
        const callBtn = document.getElementById('callBtn')
        const hangupBtn = document.getElementById('hangupBtn')
    
        const config = {
            iceServers: [
                { urls: 'stun:global.stun.twilio.com:3478?transport=udp' }
            ],
        };
    
        let peerConnection;
    
        let socket, userId, toUserId;
        userId = parseInt(Math.random()*10000);
        document.getElementById('userId').innerText = '我的id:' + userId;
    
        // 本地流和远端流
        let localStream, remoteStream;
    
        function requestConnect() {
            toUserId = document.getElementById('toUserId').value
            if(!toUserId){
                alert('请输入对方id')
                return false
            }else if(!socket){
                alert('请先打开websocket')
                return false
            }else if(toUserId == userId){
                alert('自己不能和自己连接')
                return false
            }
            //准备连接
            startHandle().then(() => {
                //发送给远端开启请求
                socket.send(JSON.stringify({ 'userId': userId, 'toUserId': toUserId, 'message': {'type': 'connect'}}))
            })
        }
    
        //开启本地的媒体设备
        async function startHandle() {
            // 1.获取本地音视频流
            // 调用 getUserMedia API 获取音视频流
            let constraints = {
                video: true,
                audio: {
                    // 设置回音消除
                    noiseSuppression: true,
                    // 设置降噪
                    echoCancellation: true,
                }
            }
    
            await navigator.mediaDevices.getUserMedia(constraints)
                .then(gotLocalMediaStream)
                .catch((err) => {
                    console.log('getUserMedia 错误', err);
                    //创建点对点连接对象
                });
    
            createConnection();
        }
    
        // getUserMedia 获得流后,将音视频流展示并保存到 localStream
        function gotLocalMediaStream(mediaStream) {
            localVideo.srcObject = mediaStream;
            localStream = mediaStream;
            callBtn.disabled = false;
        }
    
        function startWebsocket() {
            toUserId = document.getElementById('toUserId').value
            let webSocketUrl = 'wss://' + location.host + '/websocket/' + userId
            if ('WebSocket' in window) {
                // console.log(1)
                socket = new WebSocket(webSocketUrl);
            } else if ('MozWebSocket' in window) {
                // console.log(2)
                socket = new MozWebSocket(webSocketUrl);
            }
            // socket = new SockJS('https://' + location.host + '/websocket/' + userId);
            //连接成功
            socket.onopen = function (e) {
                console.log('连接服务器成功!')
            };
            //server端请求关闭
            socket.onclose = function (e) {
                console.log('close')
                alert(JSON.stringify(e))
    
            };
            //error
            socket.onerror = function (e) {
                console.error(e)
                alert(JSON.stringify(e))
            };
            socket.onmessage = onmessage
        }
        //连接服务器
        startWebsocket();
    
        function onmessage(e) {
    
            const json = JSON.parse(e.data)
            const description = json.message
            toUserId = json.userId
    
            switch (description.type) {
                case 'connect':
                    if(confirm(toUserId + '请求连接!')){
                        //准备连接
                        startHandle().then(() => {
                            socket.send(JSON.stringify({ 'userId': userId, 'toUserId': toUserId, 'message': {'type': 'start'} }));
                        })
                    }
                    break;
                case 'start':
                    //同意连接之后开始连接
                    startConnection()
                    break;
                case 'offer':
                    peerConnection.setRemoteDescription(new RTCSessionDescription(description)).then(() => {
    
                    }).catch((err) => {
                        console.log('local 设置远端描述信息错误', err);
                    });
    
                    peerConnection.createAnswer().then(function (answer) {
    
                        peerConnection.setLocalDescription(answer).then(() => {
                            console.log('设置本地answer成功!');
                        }).catch((err) => {
                            console.error('设置本地answer失败', err);
                        });
    
                        socket.send(JSON.stringify({ 'userId': userId, 'toUserId': toUserId, 'message': answer }));
                    }).catch(e => {
                        console.error(e)
                    });
                    break;
                case 'icecandidate':
                    // 创建 RTCIceCandidate 对象
                    let newIceCandidate = new RTCIceCandidate(description.icecandidate);
    
                    // 将本地获得的 Candidate 添加到远端的 RTCPeerConnection 对象中
                    peerConnection.addIceCandidate(newIceCandidate).then(() => {
                        console.log(`addIceCandidate 成功`);
                    }).catch((error) => {
                        console.log(`addIceCandidate 错误:\n` + `${error.toString()}.`);
                    });
                    break;
                case 'answer':
    
                    peerConnection.setRemoteDescription(new RTCSessionDescription(description)).then(() => {
                        console.log('设置remote answer成功!');
                    }).catch((err) => {
                        console.log('设置remote answer错误', err);
                    });
                    break;
                default:
                    break;
            }
        }
    
        function createConnection() {
            peerConnection = new RTCPeerConnection(config)
    
            if (localStream) {
                // 视频轨道
                const videoTracks = localStream.getVideoTracks();
                // 音频轨道
                const audioTracks = localStream.getAudioTracks();
                // 判断视频轨道是否有值
                if (videoTracks.length > 0) {
                    console.log(`使用的设备为: ${videoTracks[0].label}.`);
                }
                // 判断音频轨道是否有值
                if (audioTracks.length > 0) {
                    console.log(`使用的设备为: ${audioTracks[0].label}.`);
                }
    
                localStream.getTracks().forEach((track) => {
                    peerConnection.addTrack(track, localStream)
                })
            }
    
            // 监听返回的 Candidate
            peerConnection.addEventListener('icecandidate', handleConnection);
            // 监听 ICE 状态变化
            peerConnection.addEventListener('iceconnectionstatechange', handleConnectionChange)
            //拿到流的时候调用
            peerConnection.addEventListener('track', gotRemoteMediaStream);
        }
    
        //创建发起方会话描述对象(createOffer),设置本地SDP(setLocalDescription),并通过信令服务器发送到对等端,以启动与远程对等端的新WebRTC连接。
        function startConnection() {
            callBtn.disabled = true;
            hangupBtn.disabled = false;
            // 发送offer
            peerConnection.createOffer().then(description => {
                console.log(`本地创建offer返回的sdp:\n${description.sdp}`)
    
                // 将 offer 保存到本地
                peerConnection.setLocalDescription(description).then(() => {
                    console.log('local 设置本地描述信息成功');
                    // 本地设置描述并将它发送给远端
                    socket.send(JSON.stringify({ 'userId': userId, 'toUserId': toUserId, 'message': description }));
                }).catch((err) => {
                    console.log('local 设置本地描述信息错误', err)
                });
            })
                .catch((err) => {
                    console.log('createdOffer 错误', err);
                });
        }
    
        function hangupHandle() {
            // 关闭连接并设置为空
            peerConnection.close();
            peerConnection = null;
    
            hangupBtn.disabled = true;
            callBtn.disabled = false;
    
            localStream.getTracks().forEach((track) => {
                track.stop()
            })
        }
    
        // 3.端与端建立连接
        function handleConnection(event) {
            // 获取到触发 icecandidate 事件的 RTCPeerConnection 对象
            // 获取到具体的Candidate
            console.log("handleConnection")
            const peerConnection = event.target;
            const icecandidate = event.candidate;
    
            if (icecandidate) {
    
                socket.send(JSON.stringify({
                    'userId': userId,
                    'toUserId': toUserId,
                    'message': {
                        type: 'icecandidate',
                        icecandidate: icecandidate
                    }
                }));
            }
        }
    
        // 4.显示远端媒体流
        function gotRemoteMediaStream(event) {
            console.log('remote 开始接受远端流')
    
            if (event.streams[0]) {
                remoteVideo.srcObject = event.streams[0];
                remoteStream = event.streams[0];
            }
        }
    
        function handleConnectionChange(event) {
            const peerConnection = event.target;
            console.log('ICE state change event: ', event);
            console.log(`ICE state: ` + `${peerConnection.iceConnectionState}.`);
        }
    
    </script>
    <style>
        .video {
            background-color: black;
            height: 30vh;
        }
    </style>
    
  • 您还可以看一下 杨鑫老师的webrtc入门与实战视频教程课程中的 webrtc房间服务搭建小节, 巩固相关知识点

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^