webrtc實現點對點視頻通信

html: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.jsjquery

  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

 

創建鏈接的過程:nginx

1⃣️兩個瀏覽器都打開該頁面,鏈接到同一個socket('wss://www.ecoblog.online/wss');web

注意:webrtc只能在localhost或者https下使用,因此線上環境的話,咱們的socket服務以及html頁面都必須是要有https證書的;json

對於wss,利用反向代理,在nginx的站點配置下以下配置/wss:centos

正如你所看到的那樣,socket服務開在12345端口,因此還要去阿里雲網站開一個這個端口的出入站規則;瀏覽器

另外centos的防火牆對該端口開放,或者直接關閉防火牆(自行百度)服務器

socket服務寫得比較簡陋,但已夠用,功能就是把收到的信息發給當前鏈接的全部c端websocket

2⃣️兩個c端已經和socket創建鏈接,而後任意其中一端點擊「創建鏈接」session

此時點擊創建鏈接的端就是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服務器

相關文章
相關標籤/搜索