文章目录
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(){// 创建RTCPeerConnectionif(pc == null){createPeerConnection();}
pc.createOffer().then(createOfferAndSendMessage).catch(handleCreateOfferError);}
function createPeerConnection(){
pc =newRTCPeerConnection(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
信令的详细执行流程:
- 记录日志:-
console.info("handleRemoteNewPeer, remoteUid: " + message.remoteUid);
:在控制台输出一条信息,表明一个新的远程对等体已经加入,同时显示这个对等体的用户 ID。 - 保存远程用户 ID:-
remoteUserId = message.remoteUid;
:将消息中的remoteUid
保存到全局变量remoteUserId
中。这个 ID 用于标识远程对等体,后续的 WebRTC 操作(如发送 offer)会使用这个 ID 来指定目标用户。 - 创建 WebRTC 连接:-
doOffer();
:调用doOffer
函数,开始创建 WebRTC 连接并发送 offer。这个函数的作用是初始化RTCPeerConnection
对象(如果尚未创建),并创建一个 offer 来开始协商过程。 - 创建
RTCPeerConnection
对象:- 如果pc
(RTCPeerConnection
对象)为null
,则调用createPeerConnection
函数来创建一个新的RTCPeerConnection
对象。这个对象负责管理 WebRTC 连接的协商和维护。 - 设置 ICE 候选者和远程媒体流事件处理:- 在
createPeerConnection
函数中,为RTCPeerConnection
对象设置了onicecandidate
和ontrack
事件处理函数。onicecandidate
处理本地 ICE 候选者的生成,而ontrack
处理远程媒体流的添加。 在 WebRTC 中,ICE(Interactive Connectivity Establishment)协议用于在对等体之间建立连接。这个过程需要通过一系列的步骤来发现并验证不同的网络路径,以找到可以用于媒体传输的最佳路径。以下是设置 ICE 候选者和远程媒体流事件处理的详细解析:
- ICE 候选者(ICE Candidates):- ICE 候选者是网络接口的描述,可以用来在对等体之间传输媒体流。每个候选者包括一个网络地址和一个端口号,以及可能的其他元数据,如传输协议类型(如 UDP 或 TCP)。
- 收集 ICE 候选者:-
RTCPeerConnection
对象在创建时会开始 ICE 候选者的收集过程。这个过程是异步的,会在不同的时间点生成多个候选者。 - 设置
onicecandidate
事件处理函数:-pc.onicecandidate = handleIceCandidate;
:为RTCPeerConnection
对象设置onicecandidate
事件处理函数。每当有新的 ICE 候选者生成时,这个事件处理函数会被调用。 - 处理 ICE 候选者事件:-
handleIceCandidate(event)
:这个函数会在onicecandidate
事件触发时执行。它检查事件对象event
是否包含candidate
属性。 - 发送 ICE 候选者:- 如果
event.candidate
存在,表示有一个可用的 ICE 候选者。这个候选者会被序列化为 JSON 格式,并封装在一个信令消息中,然后通过 WebSocket 发送给远程对等体。-var jsonMsg = { 'cmd': 'candidate', ... };
:创建一个包含信令类型、房间 ID、用户 ID 和候选者数据的 JSON 对象。-var message = JSON.stringify(jsonMsg);
:将 JSON 对象转换为字符串,以便通过网络发送。-zeroRTCEngine.sendMessage(message);
:调用ZeroRTCEngine
实例的sendMessage
方法,将消息发送给远程对等体。 - 结束候选者收集:- 如果
event.candidate
不存在,表示候选者收集过程已经结束。这时,可以发送一个特殊的信令消息,告知远程对等体没有更多的候选者。 - 远程媒体流事件处理:-
pc.ontrack = handleRemoteStreamAdd;
:为RTCPeerConnection
对象设置ontrack
事件处理函数。每当远程媒体流的第一帧数据到达时,这个事件处理函数会被调用。 - 处理远程媒体流:-
handleRemoteStreamAdd(event)
:这个函数会在ontrack
事件触发时执行。它获取事件对象event
中的远程媒体流,并将其绑定到远程视频元素上,以便在网页上显示远程视频。 - 显示远程视频:-
remoteVideo.srcObject = remoteStream;
:将远程媒体流remoteStream
绑定到远程视频元素remoteVideo
上。这样,远程视频流就会在视频元素中播放。
- **添加本地媒体流到
RTCPeerConnection
**:-localStream.getTracks().forEach((track) => pc.addTrack(track, localStream));
:将本地媒体流localStream
的轨道添加到RTCPeerConnection
对象中。这样,当连接建立后,本地媒体流可以被远程对等体接收。 - 创建并发送 offer:-
pc.createOffer().then(createOfferAndSendMessage).catch(handleCreateOfferError);
:调用RTCPeerConnection
对象的createOffer
方法来创建一个新的 offer。创建成功后,通过createOfferAndSendMessage
函数将 offer 封装为 JSON 消息并通过 WebSocket 发送给远程对等体。 - 处理创建 offer 错误:- 如果在创建 offer 过程中出现错误,
catch
块会捕获这个错误,并调用handleCreateOfferError
函数来记录错误信息。
总结来说,当执行
handleRemoteNewPeer
信令时,应用程序会为新加入的远程对等体创建一个 WebRTC 连接,并开始协商过程,以便进行音频和视频通信。这个过程包括创建
RTCPeerConnection
对象、添加本地媒体流、创建 offer 并发送给远程对等体。
版权归原作者 Rookie也要加油 所有, 如有侵权,请联系我们删除。