打通一下 1v1 音视频通话的流程。
基本知识
端到端连接基本流程:
客户端信令消息设计:
- join 加入房间
- leave 离开房间
- message 端到端消息
- offer 消息
- answer 消息
- candidate 消息
服务端信令消息设计:
- joined 已成功加入房间
- otherjoin 其他用户加入此房间
- full 要加入的房间已满
- leave 已成功离开房间
- bye 对方离开房间
消息处理流程:
客户端状态机:
客户端加入相关流程:
客户端离开流程图:
代码逻辑
连接
网页加载完毕,用户初始状态为
init
。点击连接按钮,进入 start() 函数,获取权限并开启本地音视频,然后进入 conn() 函数和信令服务器建立连接,并向信令服务器发送一个 join 信号,当收到服务器返回的 joined 后,客户端的状态变为 joined 。然后执行 createPeerConnection() 函数,创建 pc 并绑定媒体流,等待第二个人加入。注意:addTrack 将采集的音视频轨道添加并发送给远端。
当有第二个人点击连接按钮,执行完上述步骤后,第一个人的客户端会收到信令服务器发来的一个 otherjoin 信号,这时会触发 call() 函数。在 call() 中执行 createOffer() ,在创建 offer 成功后 setLocalDescription,并将创建好的 desc 信息发给信令 message 给信令服务器。
setLocalDescription 调用后底层会悄悄地向 sturn/turn 服务器发送一个 bind request,这个时候就开始收集所有能和对方连接的候选者了。
当服务器收到 message 后,会将其原封不动的转发给房间内除发送者外的其他成员:
socket.to(room).emit('message', room, data); // 给房间出自己外所有人回消息
然后第二个人会收到信令服务器发来的 message 信息,信息中的
data.type==='offer'
。下来第二个人的客户端会执行 setRemoteDescription,然后 createAnswer,并 setLocalDescription,最后讲创建的 answer 以 message 信息。同样,信令服务器收到这个 answer 后还是原封不动的转发给了第一个连接的人。
第一个人在收到 answer 后 setRemoteDescription,这样两个人的 SDP 就交换好了。
已经根据SDP信息创建好本地的相关 Channel 后会开启Candidate数据的收集,接收由 TURN 服务器收集好的 candidate 信息。
当 candidate 到达第一个连接的人那后会触发 onicecandidate,第一个人的客户端会将这个 candidate 发送给信令服务器,信令服务器发给第二个进来的人,第二个进来的人会 addIceCandidate,然后会触发自己的 onicecandidate,再给信令服务器,信令服务器再给第一个进来的人。
这样两个人就建立了音视频传输的P2P通道,接收对方传送过来的 MediaStream 对象并渲染出来。
onTrack 监听音视频数据的到达,到达后执行 getRemoteStream。
当其他人再加入时,信令服务器发现此房间已满,会发送一个 full 信号,提示当前房间已满,并关闭 pc 和本地音视频流的 Track。
离开
离开的逻辑就简单一些了。
先向服务器发送 leave 信令,收到 leaved 后变更状态然后关闭pc,关闭媒体流。
注意
网络连接要在音视频流数据获取之后,否则有可能绑定音视频流失败。
当一端退出房间后,另一端的 PeerConnection 要关闭重建,否则与新用户互通的时候媒体协商失败。
异步事件处理。
完整代码
Client.html
1 |
|
Client.js
1 | ; |
Signal Server
1 | ; |
其他参考资料:
https://cloud.tencent.com/developer/article/1480648
https://developer.mozilla.org/zh-CN/docs/Web/API/RTCPeerConnection/ontrack
https://developer.mozilla.org/zh-CN/docs/Web/API/RTCPeerConnection/onicecandidate
https://hpbn.co/webrtc/#establishing-a-peer-to-peer-connection
https://www.cnblogs.com/fangkm/p/4364553.html
EOF