2024-9-19
梳理信令处理的函数嵌套及实现思路

一对一视频通话

New_peer信令处理

ZeroRTCEngine.prototype.onMessage = function (event) {
    console.log("onMessage: " + event.data);
    var jsonMsg = null;
    try {
         jsonMsg = JSON.parse(event.data);//解序列化
    } catch(e) {
        console.warn("onMessage parse Json failed:" + e);
        return;
    }

    switch (jsonMsg.cmd) {//解析信令(图中橙色框)
        case SIGNAL_TYPE_NEW_PEER:
            handleRemoteNewPeer(jsonMsg);
            break;
        case SIGNAL_TYPE_RESP_JOIN:
            handleResponseJoin(jsonMsg);
            break;
        case SIGNAL_TYPE_PEER_LEAVE:
            handleRemotePeerLeave(jsonMsg);
            break;
        case SIGNAL_TYPE_OFFER:
            handleRemoteOffer(jsonMsg);
            break;
        case SIGNAL_TYPE_ANSWER:
            handleRemoteAnswer(jsonMsg);
            break;
        case SIGNAL_TYPE_CANDIDATE:
                handleRemoteCandidate(jsonMsg);
            break;
    }
}           



function handleRemoteNewPeer(message) {
    console.info("handleRemoteNewPeer, remoteUid: " + message.remoteUid);
    remoteUserId = message.remoteUid;
    doOffer();
}

function doOffer() {
    // 创建RTCPeerConnection
    if (pc == null) {
        createPeerConnection();
    }
    pc.createOffer().then(createOfferAndSendMessage).catch(handleCreateOfferError);
}

function createPeerConnection() {
    pc = new RTCPeerConnection(null);
    pc.onicecandidate = handleIceCandidate;
    pc.ontrack = handleRemoteStreamAdd;

    localStream.getTracks().forEach((track) => pc.addTrack(track, localStream));
 
 
 function handleIceCandidate(event) {
    console.info("handleIceCandidate");
    if (event.candidate) {
        var jsonMsg = {
            'cmd': 'candidate',
            'roomId': roomId,
            'uid': localUserId,
            'remoteUid': remoteUserId,
            'msg': JSON.stringify(event.candidate)
        };
        var message = JSON.stringify(jsonMsg);
        zeroRTCEngine.sendMessage(message);
        // console.info("handleIceCandidate message: " + message);
        console.info("send candidate message");
    } else {
        console.warn("End of candidates");
    }
}

function handleRemoteStreamAdd(event) {
    console.info("handleRemoteStreamAdd");
    remoteStream = event.streams[0];
    remoteVideo.srcObject = remoteStream;
}

function createOfferAndSendMessage(session) {
    pc.setLocalDescription(session)
        .then(function () {
            var jsonMsg = {
                'cmd': 'offer',
                'roomId': roomId,
                'uid': localUserId,
                'remoteUid': remoteUserId,
                'msg': JSON.stringify(session)
            };
            var message = JSON.stringify(jsonMsg);
            zeroRTCEngine.sendMessage(message);
            // console.info("send offer message: " + message);
            console.info("send offer message");
        })
        .catch(function (error) {
            console.error("offer setLocalDescription failed: " + error);
        });

}


function handleCreateOfferError(error) {
    console.error("handleCreateOfferError: " + error);
}

当执行信令 handleRemoteNewPeer 时,表示有一个新的远程对等体加入了房间,并且这个信息已经通过 WebSocket 接收并被解析为 JSON 对象 message
handleRemoteNewPeer 信令的详细执行流程:

  1. 记录日志

    • console.info("handleRemoteNewPeer, remoteUid: " + message.remoteUid);:在控制台输出一条信息,表明一个新的远程对等体已经加入,同时显示这个对等体的用户 ID。
  2. 保存远程用户 ID

    • remoteUserId = message.remoteUid;:将消息中的 remoteUid 保存到全局变量 remoteUserId 中。这个 ID 用于标识远程对等体,后续的 WebRTC 操作(如发送 offer)会使用这个 ID 来指定目标用户。
  3. 创建 WebRTC 连接

    • doOffer();:调用 doOffer 函数,开始创建 WebRTC 连接并发送 offer。这个函数的作用是初始化 RTCPeerConnection 对象(如果尚未创建),并创建一个 offer 来开始协商过程。
  4. 创建 RTCPeerConnection 对象

    • 如果 pcRTCPeerConnection 对象)为 null,则调用 createPeerConnection 函数来创建一个新的 RTCPeerConnection 对象。这个对象负责管理 WebRTC 连接的协商和维护。
  5. 设置 ICE 候选者和远程媒体流事件处理

    • createPeerConnection 函数中,为 RTCPeerConnection 对象设置了 onicecandidateontrack 事件处理函数。onicecandidate 处理本地 ICE 候选者的生成,而 ontrack 处理远程媒体流的添加。
      在 WebRTC 中,ICE(Interactive Connectivity Establishment)协议用于在对等体之间建立连接。这个过程需要通过一系列的步骤来发现并验证不同的网络路径,以找到可以用于媒体传输的最佳路径。以下是设置 ICE 候选者和远程媒体流事件处理的详细解析:

  1. ICE 候选者(ICE Candidates)

    • ICE 候选者是网络接口的描述,可以用来在对等体之间传输媒体流。每个候选者包括一个网络地址和一个端口号,以及可能的其他元数据,如传输协议类型(如 UDP 或 TCP)。
  2. 收集 ICE 候选者

    • RTCPeerConnection 对象在创建时会开始 ICE 候选者的收集过程。这个过程是异步的,会在不同的时间点生成多个候选者。
  3. 设置 onicecandidate 事件处理函数

    • pc.onicecandidate = handleIceCandidate;:为 RTCPeerConnection 对象设置 onicecandidate 事件处理函数。每当有新的 ICE 候选者生成时,这个事件处理函数会被调用。
  4. 处理 ICE 候选者事件

    • handleIceCandidate(event):这个函数会在 onicecandidate 事件触发时执行。它检查事件对象 event 是否包含 candidate 属性。
  5. 发送 ICE 候选者

    • 如果 event.candidate 存在,表示有一个可用的 ICE 候选者。这个候选者会被序列化为 JSON 格式,并封装在一个信令消息中,然后通过 WebSocket 发送给远程对等体。
    • var jsonMsg = { 'cmd': 'candidate', ... };:创建一个包含信令类型、房间 ID、用户 ID 和候选者数据的 JSON 对象。
    • var message = JSON.stringify(jsonMsg);:将 JSON 对象转换为字符串,以便通过网络发送。
    • zeroRTCEngine.sendMessage(message);:调用 ZeroRTCEngine 实例的 sendMessage 方法,将消息发送给远程对等体。
  6. 结束候选者收集

    • 如果 event.candidate 不存在,表示候选者收集过程已经结束。这时,可以发送一个特殊的信令消息,告知远程对等体没有更多的候选者。
  7. 远程媒体流事件处理

    • pc.ontrack = handleRemoteStreamAdd;:为 RTCPeerConnection 对象设置 ontrack 事件处理函数。每当远程媒体流的第一帧数据到达时,这个事件处理函数会被调用。
  8. 处理远程媒体流

    • handleRemoteStreamAdd(event):这个函数会在 ontrack 事件触发时执行。它获取事件对象 event 中的远程媒体流,并将其绑定到远程视频元素上,以便在网页上显示远程视频。
  9. 显示远程视频

    • remoteVideo.srcObject = remoteStream;:将远程媒体流 remoteStream 绑定到远程视频元素 remoteVideo 上。这样,远程视频流就会在视频元素中播放。

  1. 添加本地媒体流到 RTCPeerConnection

    • localStream.getTracks().forEach((track) => pc.addTrack(track, localStream));:将本地媒体流 localStream 的轨道添加到 RTCPeerConnection 对象中。这样,当连接建立后,本地媒体流可以被远程对等体接收。
  2. 创建并发送 offer

    • pc.createOffer().then(createOfferAndSendMessage).catch(handleCreateOfferError);:调用 RTCPeerConnection 对象的 createOffer 方法来创建一个新的 offer。创建成功后,通过 createOfferAndSendMessage 函数将 offer 封装为 JSON 消息并通过 WebSocket 发送给远程对等体。
  3. 处理创建 offer 错误

    • 如果在创建 offer 过程中出现错误,catch 块会捕获这个错误,并调用 handleCreateOfferError 函数来记录错误信息。

总结来说,当执行 handleRemoteNewPeer 信令时,应用程序会为新加入的远程对等体创建一个 WebRTC 连接,并开始协商过程,以便进行音频和视频通信。这个过程包括创建 RTCPeerConnection 对象、添加本地媒体流、创建 offer 并发送给远程对等体。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部