WebRTC是什么
WebRTC是一个开源项目,包含相关协议及API具体实现。WebRTC的作用是实现浏览器端到端的实时数据传输。
端到端媒体传输的建立过程(eg A with B)
- A获取媒体流(MediaStream)或数据流
一般通过MediaDevices.getUserMedia()获取媒体流,媒体流包含了请求媒体类型的(音视频)轨道MediaStreamTrack。一个流可以包含视频轨道,音频轨道或其他。关于MediaDevices参考这里。
通过MediaStream的addTrack方法可以添加轨道(有坑)。 - A生成一个RTCPeerConnection接口对象
RTCPeerConnection接口代表一个由本地计算机到远端的WebRTC连接。该接口提供了创建,保持,监控,关闭连接的方法的实现。
pc = new RTCPeerConnection([RTCConfiguration dictionary]) 可选参数包括ice服务器等。 - A将流加入到RTCPeerConnection对象中
pc.addStream(stream);
//或者加入轨道
stream.getTracks().forEach(track => pc.addTrack(track, stream));
- A生成Offer信息
pc.createOffer(function(offer)=>{
//创建完成 TODO 5
},error)
- A将生成的Offer设置为本地描述
RTCSessionDescription描述了连接或者待连接的端和这端的配置信息。
pc.setLocalDescription(new RTCSessionDescription(offer),function(){
//设置完成 TODO 6
},error);
- A将生成的Offer发给另一端B(服务器中转)
send json.stringify(offer)
- B生成RTCPeerConnection,并按需求设置流
new RTCPeerConnection()
- B将收到的Offer设置为远端描述
pc.setRemoteDescription(new RTCSessionDescription(Json.parse(offerString)),function(){
//设置完成 TODO 9
},error);
- B生成Answer,并设置为本地描述
pc.createAnswer(function(answer){
pc.setLocalDescription(new RTCSessionDescription(answer),function(){
//设置完成,TODO 10
})
},error)
- B把Answer发送给发起方A(服务器中转)
send json.stringify(answer)
- A将Answer设置为远端描述
pc.setRemoteDescription(new RTCSessionDescription(Json.parse(answerString)),function(){
//设置完成
},error);
- 交换ICE 候选地址信息
建立连接过程中,会回调onicecandidate事件,传递ICE候选地址,我们需要将其转发至另一端,并通过另一端的方法addIceCandidate方法设置对方的候选地址。
pc.onicecandidate = function(event) {
if (event.candidate) {
// 发送 let iceinfo = event.candidate 至另一端
} else {
// All ICE candidates have been sent
}
}
//另一端
//接收到上面的iceinfo
pc.addIceCandidate(new RTCIceCandidate(iceinfo));
理想情况下,现在已经建立连接了。
交换与使用媒体流
当一方addStream或addTrack后,另一方的RTCPeerConnection会触发onaddstream或addTrack事件回调,通过事件参数可以获取对面的流或轨道数据,以此进行媒体显示等。
当前版本的协议已经不再推荐addStream方法,应使用addTrack方法。
mozilla对于addStream的解释:
当类型为MediaStreamEvent的addstream 事件发生时,通过RTCPeerConnection触发RTCPeerConnection.onaddstream 事件处理函数。当远程媒体流MediaStream 添加到连接后发送事件。当RTCPeerConnection.setRemoteDescription() 后此事件立即被调用而不需要等待SDP交换完成。
创建数据通道(未测试)
//from https://developer.mozilla.org/zh-CN/docs/Web/API/RTCPeerConnection
var pc = new PeerConnection();
var channel = pc.createDataChannel("Mydata");
channel.onopen = function(event) {
channel.send('sending a message');
}
channel.onmessage = function(event) { console.log(event.data); }
遇到的一些问题
- 关于一个MediaSteam添加多个轨道的问题(原文)
- 本机测试无法连接
Windows(有时)开两个页面,建立连接后触发了onaddstream事件,但是赋给Video的流不播放。换成本机与虚拟机则正常,原因未知。 - 局域网里两个客户端连接不上
交换了下ice信息,加了个addIceCandidate()就好了,原因不明。
必须交换ice信息。