webrtc实现点对点视频通讯

匿名 (未验证) 提交于 2019-12-02 23:53:01

html:

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <meta http-equiv="X-UA-Compatible" content="ie=edge">     <title>webrtc</title>     <style>         #yours{             width:300px;             position:absolute;             top:200px;             left:100px;         }         #theirs{             width:300px;             position:absolute;             top:200px;             left:400px;         }     </style> </head> <body>     <button onclick="createOffer()">建立连接</button>     <video id="yours" autoplay></video>     <video id="theirs" autoplay></video>  </body>  <script src="./lib/jquery.min.js"></script> <script src="./lib/webrtc.js"></script>  </html>
View Code

webrtc.js

  1 var websocket;   2    3 function randomNum(minNum,maxNum){    4     switch(arguments.length){    5         case 1:    6             return parseInt(Math.random()*minNum+1,10);    7         break;    8         case 2:    9             return parseInt(Math.random()*(maxNum-minNum+1)+minNum,10);   10         break;   11             default:   12                 return 0;   13             break;   14     }   15 }   16 const userid = 'user' + randomNum(0,100000);  17   18 function hasUserMedia() {  19     navigator.getUserMedia = navigator.getUserMedia || navigator.msGetUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;  20     return !!navigator.getUserMedia;  21 }  22 function hasRTCPeerConnection() {  23     window.RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection || window.msRTCPeerConnection;  24     return !!window.RTCPeerConnection;  25 }  26   27 var yourVideo = document.getElementById("yours");  28 var theirVideo = document.getElementById("theirs");  29 var Connection;  30   31   32 function startPeerConnection() {  33     //return;  34     var config = {  35         'iceServers': [  36             //{ 'urls': 'stun:stun.xten.com:3478' },  37             //{ 'urls': 'stun:stun.voxgratia.org:3478' },  38             { 'url': 'stun:stun.l.google.com:19302' }  39         ]  40     };  41     config = {   42         iceServers: [  43             { urls: 'stun:stun.l.google.com:19302' },   44             { urls: 'stun:global.stun.twilio.com:3478?transport=udp' }  45         ],  46         //sdpSemantics: 'unified-plan'  47     };  48     // {  49     //     "iceServers": [{  50     //         "url": "stun:stun.1.google.com:19302"  51     //     }]  52     // };  53     Connection = new RTCPeerConnection(config);  54     Connection.onicecandidate = function(e) {  55         console.log('onicecandidate');  56         if (e.candidate) {  57             websocket.send(JSON.stringify({  58                 "userid":userid,  59                 "event": "_ice_candidate",  60                 "data": {  61                     "candidate": e.candidate  62                 }  63             }));  64         }  65     }  66     Connection.onaddstream = function(e) {  67         console.log('onaddstream');  68   69         //theirVideo.src = window.URL.createObjectURL(e.stream);  70         theirVideo.srcObject = e.stream;   71     }  72 }  73   74   75 createSocket();  76 startPeerConnection();  77   78 if (hasUserMedia()) {  79     navigator.getUserMedia({ video: true, audio: false },  80         stream => {  81             yourVideo.srcObject = stream;   82             window.stream = stream;  83             Connection.addStream(stream)                  84         },  85         err => {  86             console.log(err);  87         })  88 }         89   90   91 function createOffer(){  92     //发送offer和answer的函数,发送本地session描述  93     Connection.createOffer().then(offer => {  94         Connection.setLocalDescription(offer);  95         websocket.send(JSON.stringify({  96             "userid":userid,  97             "event": "offer",  98             "data": {  99                 "sdp": offer 100             } 101         })); 102     }); 103 } 104  105  106  107 function createSocket(){ 108     //websocket = null; 109     websocket = new WebSocket('wss://www.ecoblog.online/wss'); 110     eventBind(); 111 }; 112 function eventBind() { 113     //连接成功 114     websocket.onopen = function(e) { 115         console.log('连接成功') 116     }; 117     //server端请求关闭 118     websocket.onclose = function(e) { 119       console.log('close') 120     }; 121     //error 122     websocket.onerror = function(e) { 123  124     }; 125     //收到消息 126     websocket.onmessage = (event)=> { 127         if(event.data == "new user") { 128             location.reload(); 129         } else { 130             var json = JSON.parse(event.data); 131             console.log('onmessage: ', json); 132             if(json.userid !=userid){ 133                 //如果是一个ICE的候选,则将其加入到PeerConnection中,否则设定对方的session描述为传递过来的描述 134                 if(json.event === "_ice_candidate"&&json.data.candidate) { 135                     Connection.addIceCandidate(new RTCIceCandidate(json.data.candidate)); 136                 }else if(json.event ==='offer'){ 137                     Connection.setRemoteDescription(json.data.sdp); 138                     Connection.createAnswer().then(answer => { 139                             Connection.setLocalDescription(answer); 140                             console.log(window.stream) 141                             websocket.send(JSON.stringify({ 142                                 "userid":userid, 143                                 "event": "answer", 144                                 "data": { 145                                     "sdp": answer 146                                 } 147                             })); 148                     }) 149                 }else if(json.event ==='answer'){ 150                     Connection.setRemoteDescription(json.data.sdp);    151                     console.log(window.stream) 152  153                 } 154             } 155         } 156     }; 157 } 
View Code

建立连接的过程:

注意:webrtc只能在localhost或者https下使用,所以线上环境的话,我们的socket服务以及html页面都必须是要有https证书的;

对于wss,利用代理,在nginx的站点配置下如下配置/wss:

正如你所看到的那样,socket服务开在12345端口,所以还要去阿里云网站开一个这个端口的出入站规则;

另外centos的防火墙对该端口开放,或者直接关闭防火墙(自行百度)

socket服务写得比较简陋,但已够用,功能就是把收到的信息发给当前连接的所有c端

此时点击建立连接的端就是offer(携带信号源信息),发给另外一个端,另外一个端收到offer之后,发出响应answer(携带信号源信息),offer端收到answer端信息进行存储;

这样每个端都有了自己的信息和对方的信息,

其实这块,网上有的说法是offer发出answer发出后设置了localDescription和remoteDescription后就会触发onicecandidate,但是我测试的时候貌似没有,所以

我这里是在获取摄像头信息后通过

            Connection.addStream(stream)                

来触发Connection.onicecandidate,在这个事件监听的回调里,发出自身端的candidata给对方,如此一来,双方都有了对方的localDescription、remoteDescription和candidata;

三者齐全之后,就会触发Connection.onaddstream,这样,直接通过:

theirVideo.srcObject = e.stream; 

把流写到video里面去,这样就能展示对方的视频信息了:

但是这样,只能在局域网内使用,如果要在公网使用的话,还要一个穿透服务器,网上找的一些免费的好像都不能用了?还是说我写得有问题?

具体的可百度,webrtc搭建stun服务器

来源: https://www.cnblogs.com/eco-just/p/11324768.html

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!