Android IOS WebRTC 音视频开发总结(六)

前面写的一系列总结都是讲webrtc如何下载,编译,开发的,有些人可能有点云里雾里了,WEBRTC不是用来搞跨浏览器开发的吗,怎么我讲的这些跟浏览器扯不上任何关系,其实看看下面这个架构图,你就明白了

我前面讲的这些内容都封装在browser里面了,如音视频的采集,编码,传输,回声消除,丢包重传.所以如果你想将这些功能集成到你的产品里面就必须理解这些东西.

如果你只想做基于浏览器的视频通话功能,上面这些你可以不理解,更不需要去下载编译WEBRTC代码,因为实现这些功能所需要的JS接口浏览器已经帮你实现了,你只需要简单调用即可,我们先看看实现下面这样一个功能主要涉及哪些步骤?
1,信令交互:开始视频通话前发起端和接收端需要一些交互,如通知对方开始视频,接收视频,视频参数协商(SDP信息),NAT地址交换,这个过程我们称之为信令交互,WEBRTC没有定义标准信令格式,既可以使用SIP也可以使用XMPP,还可以使用自定义的信令格式,最简单的方式就是使用websocket或XMLHttpRequest,自定义格式完成信令交互过程.

2,获取本地视频流:navigator.getUserMedia(constraints, successCallback, errorCallback);

  
  
  
  
  1. navigator.getUserMedia = navigator.getUserMedia ||
  2. navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
  3. // Callback to be called in case of success...
  4. function successCallback(gotStream) {
  5. video.src = window.URL.createObjectURL(stream);
  6. // Start playing video
  7. video.play();
  8. }
  9.  
  10. // Callback to be called in case of failure...
  11. function errorCallback(error){ console.log("navigator.getUserMedia error: ", error);
  12. }
  13.  
  14. // Constraints object for low resolution video
  15. var qvgaConstraints = { video: {
  16. mandatory: {
  17. maxWidth: 320,
  18. maxHeight: 240
  19. } }
  20. };
  21.  
  22. // Constraints object for standard resolution video
  23. var vgaConstraints = { video: {
  24. mandatory: {
  25. maxWidth: 640,
  26. maxHeight: 480
  27. } }
  28. };
  29.  
  30. // Constraints object for high resolution video
  31. var hdConstraints = { video: {
  32. mandatory: {
  33. minWidth: 1280,
  34. minHeight: 960
  35. } }
  36. };
  37.  
  38. function getMedia(constraints){
  39. if (!!stream) { video.src = null; stream.stop();
  40. }
  41. navigator.getUserMedia(constraints, successCallback, errorCallback);
  42. }

3,SDP协商:createOffer,createAnswer.

  
  
  
  
  1. localPeerConnection.createOffer(gotLocalDescription, onSignalingError);
  2.  
  3. // Handler to be called when the 'local' SDP becomes available
  4. function gotLocalDescription(description){
  5. // Add the local description to the local PeerConnection
  6.   localPeerConnection.setLocalDescription(description);
  7.   log("Offer from localPeerConnection: \n" + description.sdp);
  8. // ...do the same with the 'pseudoremote' PeerConnection
  9. // Note: this is the part that will have to be changed if you want // the communicating peers to become remote
  10. // (which calls for the setup of a proper signaling channel) remotePeerConnection.setRemoteDescription(description);
  11. // Create the Answer to the received Offer based on the 'local' description
  12. remotePeerConnection.createAnswer(gotRemoteDescription, onSignalingError);
  13. }
  14. // Handler to be called when the remote SDP becomes available
  15. function gotRemoteDescription(description){
  16. // Set the remote description as the local description of the
  17. // remote PeerConnection.
  18.   remotePeerConnection.setLocalDescription(description);
  19. log("Answer from remotePeerConnection: \n" + description.sdp);
  20. // Conversely, set the remote description as the remote description of the // local PeerConnection
  21.   localPeerConnection.setRemoteDescription(description);
  22. }

4,ICE协商:

  
  
  
  
  1. // Add a handler associated with ICE protocol events
  2. localPeerConnection.onicecandidate = gotLocalIceCandidate;
  3.  
  4. remotePeerConnection.onicecandidate = gotRemoteIceCandidate;
  5.  
  6. // Handler to be called whenever a new local ICE candidate becomes available
  7. function gotLocalIceCandidate(event){ if (event.candidate) {
  8. // Add candidate to the remote PeerConnection
  9.        remotePeerConnection.addIceCandidate(new RTCIceCandidate(event.candidate));
  10.    log("Local ICE candidate: \n" + event.candidate.candidate);
  11. }
  12. }
  13.  
  14. // Handler to be called whenever a new remote ICE candidate becomes available
  15. function gotRemoteIceCandidate(event){ if (event.candidate) {
  16. // Add candidate to the local PeerConnection
  17.       localPeerConnection.addIceCandidate(new RTCIceCandidate(event.candidate));
  18. log("Remote ICE candidate: \n " + event.candidate.candidate);
  19. }
  20. }

5,使用RTCPeerConnection对象在浏览器之间交换媒体流数据.
Android IOS WebRTC 音视频开发总结(六)_第1张图片

  
  
  
  
  1. function call() {
  2. log("Starting call");
  3.  
  4. // Note well: getVideoTracks() and getAudioTracks() are not currently supported in Firefox...
  5. // ...just use them with Chrome
  6. if (navigator.webkitGetUserMedia) {
  7. // Log info about video and audio device in use
  8. if (localStream.getVideoTracks().length > 0) {
  9. log('Using video device: ' + localStream.getVideoTracks()[0].label);
  10. }
  11. if (localStream.getAudioTracks().length > 0) {
  12. log('Using audio device: ' + localStream.getAudioTracks()[0].label);
  13. }
  14. }
  15. // Chrome
  16. if (navigator.webkitGetUserMedia) {
  17. RTCPeerConnection = webkitRTCPeerConnection;
  18. // Firefox
  19. }else if(navigator.mozGetUserMedia){
  20. RTCPeerConnection = mozRTCPeerConnection;
  21. RTCSessionDescription = mozRTCSessionDescription;
  22. RTCIceCandidate = mozRTCIceCandidate;
  23. }
  24. log("RTCPeerConnection object: " + RTCPeerConnection);
  25. // This is an optional configuration string, associated with NAT traversal setup
  26. var servers = null;
  27.  
  28. // Create the local PeerConnection object
  29. localPeerConnection = new RTCPeerConnection(servers);
  30. log("Created local peer connection object localPeerConnection");
  31. // Add a handler associated with ICE protocol events
  32. localPeerConnection.onicecandidate = gotLocalIceCandidate;
  33.  
  34. // Create the remote PeerConnection object
  35. remotePeerConnection = new RTCPeerConnection(servers);
  36. log("Created remote peer connection object remotePeerConnection");
  37. // Add a handler associated with ICE protocol events...
  38. remotePeerConnection.onicecandidate = gotRemoteIceCandidate;
  39. // ...and a second handler to be activated as soon as the remote stream becomes available
  40. remotePeerConnection.onaddstream = gotRemoteStream;
  41.  
  42. // Add the local stream (as returned by getUserMedia() to the local PeerConnection
  43. localPeerConnection.addStream(localStream);
  44. log("Added localStream to localPeerConnection");
  45. // We're all set! Create an Offer to be 'sent' to the callee as soon as the local SDP is ready
  46. localPeerConnection.createOffer(gotLocalDescription, onSignalingError);
  47. }
  48.  
  49. function onSignalingError(error) {
  50. console.log('Failed to create signaling message : ' + error.name);
  51. }
  52.  
  53. // Handler to be called when the 'local' SDP becomes available
  54. function gotLocalDescription(description){
  55. // Add the local description to the local PeerConnection
  56. localPeerConnection.setLocalDescription(description);
  57. log("Offer from localPeerConnection: \n" + description.sdp);
  58. // ...do the same with the 'pseudo-remote' PeerConnection
  59. // Note well: this is the part that will have to be changed if you want the communicating peers to become
  60. // remote (which calls for the setup of a proper signaling channel)
  61. remotePeerConnection.setRemoteDescription(description);
  62. // Create the Answer to the received Offer based on the 'local' description
  63. remotePeerConnection.createAnswer(gotRemoteDescription, onSignalingError);
  64. }
  65.  
  66. // Handler to be called when the 'remote' SDP becomes available
  67. function gotRemoteDescription(description){
  68. // Set the 'remote' description as the local description of the remote PeerConnection
  69. remotePeerConnection.setLocalDescription(description);
  70. log("Answer from remotePeerConnection: \n" + description.sdp);
  71. // Conversely, set the 'remote' description as the remote description of the local PeerConnection
  72. localPeerConnection.setRemoteDescription(description);
  73. }
  74.  
  75. // Handler to be called as soon as the remote stream becomes available
  76. function gotRemoteStream(event){
  77. // Associate the remote video element with the retrieved stream
  78. if (window.URL) {
  79. // Chrome
  80. remoteVideo.src = window.URL.createObjectURL(event.stream);
  81. } else {
  82. // Firefox
  83. remoteVideo.src = event.stream;
  84. }
  85. log("Received remote stream");
  86. }
  87.  
  88. // Handler to be called whenever a new local ICE candidate becomes available
  89. function gotLocalIceCandidate(event){
  90. if (event.candidate) {
  91. // Add candidate to the remote PeerConnection
  92. remotePeerConnection.addIceCandidate(new RTCIceCandidate(event.candidate));
  93. log("Local ICE candidate: \n" + event.candidate.candidate);
  94. }
  95. }
  96.  
  97. // Handler to be called whenever a new 'remote' ICE candidate becomes available
  98. function gotRemoteIceCandidate(event){
  99. if (event.candidate) {
  100. // Add candidate to the local PeerConnection
  101. localPeerConnection.addIceCandidate(new RTCIceCandidate(event.candidate));
  102. log("Remote ICE candidate: \n " + event.candidate.candidate);
  103. }

上面基本上就是浏览器上视频通话涉及的主要对象.

对应到手机端就是webrtc编译成功后的appRTCDemo.apk.

转载请注明:IT十万为什么 » Android IOS WebRTC 音视频开发总结(六)

你可能感兴趣的:(Android IOS WebRTC 音视频开发总结(六))