WebRTC伪码实现
此处非真正代码,但是以面向对象的方式思考,有助于之后对源代码的理解,主要了解整个实现过程
由移动设备作为发起呼叫方,以PC端作为接收呼叫发
移动设备:
1.前提(建立信令通道,获取对等端身份)
2.获取本地媒体
PS:[navigator对象包含浏览器信息]
function getMedia(){
//获取本地媒体
get local audio(microphone)
navigator.getUserMedia({“audio":true”},function(stream){microphone=stream;})
//获取本地视频(from应用程序)
//此处假设application已经设置此流
application=stream;
//获得本地视频(前置摄像头)
constraint ={“video”:{“mandatory”:{“facingMode”:“environment”}};
navigator。getUserMedia(constraint,function(stream){front=stream;
});
//获得本地视频(后置摄像头)
constraint ={“video”:{“mandatory”:{“facingMode”:“user”}};
navigator。getUserMedia(constraint,function(stream){frear=stream;
});
3.创建对等连接并设置回调
function createPC(){
pc=new RTCPeerCOnnection(configuration);
//向对等端发送各个ICE候选项
pc.onicecandidate=function(evt){
signailingChannel.send(
JSON.stringify({"candidate":evt.candidate}));
};
//处理添加的远端流
pc.onaddstream=
function(evt){handleIncomingStream(evt.stream);};
}
4.将媒体关联到对等连接(PC)
function attachMedia(){
//创建要发送的流
presentation=
new MediaStream(
[microphone.getAudioTracks()[0], //本地视频流
application.getVideoTracks()[0]]); //
presenter=
new MediaStream(
[microphone.getAudioTracks()[0], /前置摄像头流
front.getVideoTracks()[0]]); //
demonstration=
new MediaStream(
[microphone.getAudioTracks()[0], //后置摄像头流
rear.getVideoTracks()[0]]); //
//将流添加到对等连接
pc.addStream(presentation);
pc.addStream(presenter);
pc.addStream(demonstration);
//在SDP协商之前,即媒体流开始传输之前
//将媒体流ID作为JSON字符串发送到对等端
signalingChannel.send(
JSON.stringify({"presentation":presentation.id,
"presenter":presenter.id,
"demonstration":demonstration.id
}));
}
5.通过创建并发送SDP提议发起呼叫
function call(){
//此时,尚未开始媒体提议/应答过程,因此没有媒体在传输
//基于当前的流和ICE候选项创建SDP模拟
//处理提议时,将调用gotDescription()
pc.createOffer(gotDescription);
//此函数基于浏览器刚刚创建的SDP提议操作
function gotDescription(desc){
//首先,向浏览器指示次SDP提议是我的本地会话描述
pc.setLocalDEscription(desc);
//将此提议作为JSON字符串发送至对等端
signalingChannel.send(JSON.stringify({"sdp":desc}));
}
}
//在远端流出现时执行的一些处理
function handleIncomingStream(s){
//保存所有传入流的句柄。对于av_stream,予以呈现
if (s.getVideoTracks().length==1){
//这是av_stream
av_steam =s;
show_av(av_stream);
}else if (a.getAudioTracks().length==2){
//这是立体声流
stereo= s;
}else{
//这是单声道流
mono=s;
}
}
//通过将流关联到相应元素显示/播放它们
function show_av(s){
//display是视频元素,left和right是音频元素
display.src=URL.createObjectURL(
new MediaStream(s.getVideoTracks()[0]));
left.src=URL.createObjectURL(
new MediaStream(s.getVideoTracks()[0]));
right.src=URL.createObjectURL(
new MediaStream(s.getVideoTracks()[1]));
}
//处理从对等端传入的消息。它们将是SDP或ICE候选项
signalingChannel.onmessage=function(msg){
//先分析JSON事件数据,将其还原为一个对象
var signal=JSON.parse(msg.data);
if (signal.sdp){
//如果这是来自对等端的SDP,则向浏览器指示它是远程端的会话描述
pc.setRemoteDescription(signal.sdp));
}else{
//否则,是来自对等端的候选项
//向浏览器指示它是媒体可用于访问对等端的候选IJ地址
//浏览器随后将使用ICE来尝试访问此地址
pc.addIceCandidate(
new RTCIceCandidate(signal.candidate));
}
};