webrtc实现点对点视频通讯

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

建立连接的过程:

1⃣️两个浏览器都打开该页面,连接到同一个socket('wss://www.ecoblog.online/wss');

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

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

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

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

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

2⃣️两个c端已经和socket建立连接,然后任意其中一端点击“建立连接”

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

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

3⃣️candidata信息的发送

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

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

            Connection.addStream(stream)                

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

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

theirVideo.srcObject = e.stream; 

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

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

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

猜你喜欢

转载自www.cnblogs.com/eco-just/p/11324768.html