前面写的一系列总结都是讲webrtc如何下载,编译,开发的,有些人可能有点云里雾里了,WEBRTC不是用来搞跨浏览器开发的吗,怎么我讲的这些跟浏览器扯不上任何关系,其实看看下面这个架构图,你就明白了
我前面讲的这些内容都封装在browser里面了,如音视频的采集,编码,传输,回声消除,丢包重传.所以如果你想将这些功能集成到你的产品里面就必须理解这些东西.
如果你只想做基于浏览器的视频通话功能,上面这些你可以不理解,更不需要去下载编译WEBRTC代码,因为实现这些功能所需要的JS接口浏览器已经帮你实现了,你只需要简单调用即可,我们先看看实现下面这样一个功能主要涉及哪些步骤?
1,信令交互:开始视频通话前发起端和接收端需要一些交互,如通知对方开始视频,接收视频,视频参数协商(SDP信息),NAT地址交换,这个过程我们称之为信令交互,WEBRTC没有定义标准信令格式,既可以使用SIP也可以使用XMPP,还可以使用自定义的信令格式,最简单的方式就是使用websocket或XMLHttpRequest,自定义格式完成信令交互过程.
2,获取本地视频流:navigator.getUserMedia(constraints, successCallback, errorCallback);
- navigator.getUserMedia = navigator.getUserMedia ||
- navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
- // Callback to be called in case of success...
- function successCallback(gotStream) {
- video.src = window.URL.createObjectURL(stream);
- // Start playing video
- video.play();
- }
- // Callback to be called in case of failure...
- function errorCallback(error){ console.log("navigator.getUserMedia error: ", error);
- }
- // Constraints object for low resolution video
- var qvgaConstraints = { video: {
- mandatory: {
- maxWidth: 320,
- maxHeight: 240
- } }
- };
- // Constraints object for standard resolution video
- var vgaConstraints = { video: {
- mandatory: {
- maxWidth: 640,
- maxHeight: 480
- } }
- };
- // Constraints object for high resolution video
- var hdConstraints = { video: {
- mandatory: {
- minWidth: 1280,
- minHeight: 960
- } }
- };
- function getMedia(constraints){
- if (!!stream) { video.src = null; stream.stop();
- }
- navigator.getUserMedia(constraints, successCallback, errorCallback);
- }
3,SDP协商:createOffer,createAnswer.
- localPeerConnection.createOffer(gotLocalDescription, onSignalingError);
- // Handler to be called when the 'local' SDP becomes available
- function gotLocalDescription(description){
- // Add the local description to the local PeerConnection
- localPeerConnection.setLocalDescription(description);
- log("Offer from localPeerConnection: \n" + description.sdp);
- // ...do the same with the 'pseudoremote' PeerConnection
- // Note: this is the part that will have to be changed if you want // the communicating peers to become remote
- // (which calls for the setup of a proper signaling channel) remotePeerConnection.setRemoteDescription(description);
- // Create the Answer to the received Offer based on the 'local' description
- remotePeerConnection.createAnswer(gotRemoteDescription, onSignalingError);
- }
- // Handler to be called when the remote SDP becomes available
- function gotRemoteDescription(description){
- // Set the remote description as the local description of the
- // remote PeerConnection.
- remotePeerConnection.setLocalDescription(description);
- log("Answer from remotePeerConnection: \n" + description.sdp);
- // Conversely, set the remote description as the remote description of the // local PeerConnection
- localPeerConnection.setRemoteDescription(description);
- }
4,ICE协商:
- // Add a handler associated with ICE protocol events
- localPeerConnection.onicecandidate = gotLocalIceCandidate;
- remotePeerConnection.onicecandidate = gotRemoteIceCandidate;
- // Handler to be called whenever a new local ICE candidate becomes available
- function gotLocalIceCandidate(event){ if (event.candidate) {
- // Add candidate to the remote PeerConnection
- remotePeerConnection.addIceCandidate(new RTCIceCandidate(event.candidate));
- log("Local ICE candidate: \n" + event.candidate.candidate);
- }
- }
- // Handler to be called whenever a new remote ICE candidate becomes available
- function gotRemoteIceCandidate(event){ if (event.candidate) {
- // Add candidate to the local PeerConnection
- localPeerConnection.addIceCandidate(new RTCIceCandidate(event.candidate));
- log("Remote ICE candidate: \n " + event.candidate.candidate);
- }
- }
5,使用RTCPeerConnection对象在浏览器之间交换媒体流数据.
- function call() {
- log("Starting call");
- // Note well: getVideoTracks() and getAudioTracks() are not currently supported in Firefox...
- // ...just use them with Chrome
- if (navigator.webkitGetUserMedia) {
- // Log info about video and audio device in use
- if (localStream.getVideoTracks().length > 0) {
- log('Using video device: ' + localStream.getVideoTracks()[0].label);
- }
- if (localStream.getAudioTracks().length > 0) {
- log('Using audio device: ' + localStream.getAudioTracks()[0].label);
- }
- }
- // Chrome
- if (navigator.webkitGetUserMedia) {
- RTCPeerConnection = webkitRTCPeerConnection;
- // Firefox
- }else if(navigator.mozGetUserMedia){
- RTCPeerConnection = mozRTCPeerConnection;
- RTCSessionDescription = mozRTCSessionDescription;
- RTCIceCandidate = mozRTCIceCandidate;
- }
- log("RTCPeerConnection object: " + RTCPeerConnection);
- // This is an optional configuration string, associated with NAT traversal setup
- var servers = null;
- // Create the local PeerConnection object
- localPeerConnection = new RTCPeerConnection(servers);
- log("Created local peer connection object localPeerConnection");
- // Add a handler associated with ICE protocol events
- localPeerConnection.onicecandidate = gotLocalIceCandidate;
- // Create the remote PeerConnection object
- remotePeerConnection = new RTCPeerConnection(servers);
- log("Created remote peer connection object remotePeerConnection");
- // Add a handler associated with ICE protocol events...
- remotePeerConnection.onicecandidate = gotRemoteIceCandidate;
- // ...and a second handler to be activated as soon as the remote stream becomes available
- remotePeerConnection.onaddstream = gotRemoteStream;
- // Add the local stream (as returned by getUserMedia() to the local PeerConnection
- localPeerConnection.addStream(localStream);
- log("Added localStream to localPeerConnection");
- // We're all set! Create an Offer to be 'sent' to the callee as soon as the local SDP is ready
- localPeerConnection.createOffer(gotLocalDescription, onSignalingError);
- }
- function onSignalingError(error) {
- console.log('Failed to create signaling message : ' + error.name);
- }
- // Handler to be called when the 'local' SDP becomes available
- function gotLocalDescription(description){
- // Add the local description to the local PeerConnection
- localPeerConnection.setLocalDescription(description);
- log("Offer from localPeerConnection: \n" + description.sdp);
- // ...do the same with the 'pseudo-remote' PeerConnection
- // Note well: this is the part that will have to be changed if you want the communicating peers to become
- // remote (which calls for the setup of a proper signaling channel)
- remotePeerConnection.setRemoteDescription(description);
- // Create the Answer to the received Offer based on the 'local' description
- remotePeerConnection.createAnswer(gotRemoteDescription, onSignalingError);
- }
- // Handler to be called when the 'remote' SDP becomes available
- function gotRemoteDescription(description){
- // Set the 'remote' description as the local description of the remote PeerConnection
- remotePeerConnection.setLocalDescription(description);
- log("Answer from remotePeerConnection: \n" + description.sdp);
- // Conversely, set the 'remote' description as the remote description of the local PeerConnection
- localPeerConnection.setRemoteDescription(description);
- }
- // Handler to be called as soon as the remote stream becomes available
- function gotRemoteStream(event){
- // Associate the remote video element with the retrieved stream
- if (window.URL) {
- // Chrome
- remoteVideo.src = window.URL.createObjectURL(event.stream);
- } else {
- // Firefox
- remoteVideo.src = event.stream;
- }
- log("Received remote stream");
- }
- // Handler to be called whenever a new local ICE candidate becomes available
- function gotLocalIceCandidate(event){
- if (event.candidate) {
- // Add candidate to the remote PeerConnection
- remotePeerConnection.addIceCandidate(new RTCIceCandidate(event.candidate));
- log("Local ICE candidate: \n" + event.candidate.candidate);
- }
- }
- // Handler to be called whenever a new 'remote' ICE candidate becomes available
- function gotRemoteIceCandidate(event){
- if (event.candidate) {
- // Add candidate to the local PeerConnection
- localPeerConnection.addIceCandidate(new RTCIceCandidate(event.candidate));
- log("Remote ICE candidate: \n " + event.candidate.candidate);
- }
上面基本上就是浏览器上视频通话涉及的主要对象.
对应到手机端就是webrtc编译成功后的appRTCDemo.apk.
转载请注明:IT十万为什么 » Android IOS WebRTC 音视频开发总结(六)