<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    不急不徐,持之以恒。

    http://blog.gopersist.com/

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      24 隨筆 :: 0 文章 :: 52 評論 :: 0 Trackbacks
    在學習WebRTC時,網上的示例大多代碼較多,以下是參考那些代碼簡化的一個WebRTC一對一的示例,在chrome 37下測試通過。其中iceServer可省略,沒有iceServer時在同一個局域網下仍可通訊。

    客戶端代碼:
    <html>
    <body>
        Local: <br>
        <video id="localVideo" autoplay></video><br>
        Remote: <br>
        <video id="remoteVideo" autoplay></video>

        <script>
            
    // 僅僅用于控制哪一端的瀏覽器發起offer,#號后面有值的一方發起
            var isCaller = window.location.href.split('#')[1];

            
    // 與信令服務器的WebSocket連接
            var socket = new WebSocket("ws://127.0.0.1:3000");

            
    // stun和turn服務器
            var iceServer = {
                
    "iceServers": [{
                    
    "url""stun:stun.l.google.com:19302"
                }, {
                    
    "url""turn:numb.viagenie.ca",
                    
    "username""webrtc@live.com",
                    
    "credential""muazkh"
                }]
            };

            
    // 創建PeerConnection實例 (參數為null則沒有iceserver,即使沒有stunserver和turnserver,仍可在局域網下通訊)
            var pc = new webkitRTCPeerConnection(iceServer);

            
    // 發送ICE候選到其他客戶端
            pc.onicecandidate = function(event){
                
    if (event.candidate !== null) {
                    socket.send(JSON.stringify({
                        
    "event""_ice_candidate",
                        
    "data": {
                            
    "candidate": event.candidate
                        }
                    }));
                }
            };

            
    // 如果檢測到媒體流連接到本地,將其綁定到一個video標簽上輸出
            pc.onaddstream = function(event){
                document.getElementById('remoteVideo').src 
    = URL.createObjectURL(event.stream);
            };

            
    // 發送offer和answer的函數,發送本地session描述
            var sendOfferFn = function(desc){
                pc.setLocalDescription(desc);
                socket.send(JSON.stringify({ 
                    
    "event""_offer",
                    
    "data": {
                        
    "sdp": desc
                    }
                }));
            },
            sendAnswerFn 
    = function(desc){
                pc.setLocalDescription(desc);
                socket.send(JSON.stringify({ 
                    
    "event""_answer",
                    
    "data": {
                        
    "sdp": desc
                    }
                }));
            };

            
    // 獲取本地音頻和視頻流
            navigator.webkitGetUserMedia({
                
    "audio"true,
                
    "video"true
            }, 
    function(stream){
                
    //綁定本地媒體流到video標簽用于輸出
                document.getElementById('localVideo').src = URL.createObjectURL(stream);
                
    //向PeerConnection中加入需要發送的流
                pc.addStream(stream);
                
    //如果是發起方則發送一個offer信令
                if(isCaller){
                    pc.createOffer(sendOfferFn, 
    function (error) {
                        console.log('Failure callback: ' 
    + error);
                    });
                }
            }, 
    function(error){
                
    //處理媒體流創建失敗錯誤
                console.log('getUserMedia error: ' + error);
            });

            
    //處理到來的信令
            socket.onmessage = function(event){
                
    var json = JSON.parse(event.data);
                console.log('onmessage: ', json);
                
    //如果是一個ICE的候選,則將其加入到PeerConnection中,否則設定對方的session描述為傳遞過來的描述
                if( json.event === "_ice_candidate" ){
                    pc.addIceCandidate(
    new RTCIceCandidate(json.data.candidate));
                } 
    else {
                    pc.setRemoteDescription(
    new RTCSessionDescription(json.data.sdp));
                    
    // 如果是一個offer,那么需要回復一個answer
                    if(json.event === "_offer") {
                        pc.createAnswer(sendAnswerFn, 
    function (error) {
                            console.log('Failure callback: ' 
    + error);
                        });
                    }
                }
            };
        
    </script>
    </body>
    </html>

    實現WebRTC時,信令服務器是必須的,它幫助客戶端之間進行溝通。
    這里使用Node.js的ws模塊來實現一個WebSocket服務作為信令服務器。另外使用express模塊讓它提供html頁面的訪問。
    server.js代碼如下:
    var express = require('express'),
    app = express(),
    server = require('http').createServer(app);

    server.listen(3000);

    app.get('/', function(req, res) {
        res.sendfile(__dirname + '/webrtc.html');
    });

    var WebSocketServer = require('ws').Server,
    wss = new WebSocketServer({server: server});

    // 存儲socket的數組,這里只能有2個socket,每次測試需要重啟,否則會出錯
    var wsc = [],
    index = 1;

    // 有socket連入
    wss.on('connection', function(ws) {
        console.log('connection');

        // 將socket存入數組
        wsc.push(ws);

        // 記下對方socket在數組中的下標,因為這個測試程序只允許2個socket
        // 所以第一個連入的socket存入0,第二個連入的就是存入1
        // otherIndex就反著來,第一個socket的otherIndex下標為1,第二個socket的otherIndex下標為0
        var otherIndex = index--,
        desc = null;

        if (otherIndex == 1) {
            desc = 'first socket';
        } else {
            desc = 'second socket';
        }

        // 轉發收到的消息
        ws.on('message', function(message) {
            var json = JSON.parse(message);
            console.log('received (' + desc + '): ', json);

            wsc[otherIndex].send(message, function (error) {
                if (error) {
                    console.log('Send message error (' + desc + '): ', error);
                }
            });
        });
    });

    使用npm安裝需要的模塊后使用node server.js啟動服務。
    測試時使用Chrome瀏覽器:
    第一個瀏覽器窗口訪問頁面:http://127.0.0.1:3000,在彈出的提示中允許使用攝像頭和麥克風。
    第二個瀏覽器窗口訪問頁面:http://127.0.0.1:3000#true,#true表示它是一個發起方,在彈出的提示中同樣允許使用攝像頭和麥克風。
    這時頁面中應當可以看到2個畫面,一個是本地的,一個是遠端的。

    將代碼中的IP稍做調整后部署到外網,即可在2個不同的地點訪問這個頁面進行實時通訊。


    微信訂閱號:
    源文地址:http://blog.gopersist.com/2014/10/21/webrtc-simple/
    posted on 2014-10-21 17:21 老林 閱讀(43353) 評論(6)  編輯  收藏 所屬分類: 即時通訊(IM)

    評論

    # re: 最簡單的WebRTC示例[未登錄] 2014-11-17 11:20 eric
    WebRTC需要stun,turn,ice服務器的支持。stun和turn是發現對方公網ip的方式,ice是一個統一的框架,將stun和turn的實現放在一起。但我在網上搜索ice server好像開源的幾乎沒有。希望多多交流:ericmmgg@126.com。  回復  更多評論
      

    # re: 最簡單的WebRTC示例 2014-11-24 18:36 xy.lin
    @eric
    stun用來發現公網IP,也要判斷路由器行為和防火墻。turn是在無法進行p2p時提供數據中轉服務。rfc5766-turn-server是一個開源項目,同時提供了上面的功能。  回復  更多評論
      

    # re: 最簡單的WebRTC示例[未登錄] 2015-05-14 14:08 danny
    請問樓主,當使用new webkitRTCPeerConnection建立connection后,candidate信息是connection主動去探測的么,如果探測有返回,就會調用onicecandidate()?  回復  更多評論
      

    # re: 最簡單的WebRTC示例[未登錄] 2015-11-18 13:39
    挺好的例子,不過我自己測試發現,在同一臺機器上顯示不了對端的視頻,兩臺機器上可以互通。  回復  更多評論
      

    # re: 最簡單的WebRTC示例 2016-05-26 11:27 keithwind
    是不是onicecandidate和onaddstream的代碼內容反調了,我沒測試,但是感覺流程執行不對  回復  更多評論
      

    # re: 最簡單的WebRTC示例 2016-05-26 17:43 keithwind
    if(json.event === "_offer")
    比較錯了,所以看不到,少一個下劃線  回復  更多評論
      

    主站蜘蛛池模板: 91在线老王精品免费播放| 日本不卡免费新一区二区三区| 在人线av无码免费高潮喷水| 亚洲熟妇无码久久精品| 亚洲国产精品免费在线观看| 亚洲在成人网在线看| 免费中文熟妇在线影片| 亚洲精品无码久久| 又粗又大又硬又爽的免费视频| 337P日本欧洲亚洲大胆精品| 亚洲欧洲自拍拍偷精品 美利坚| 一区二区三区免费视频网站| 中文字幕亚洲无线码| 你懂的免费在线观看网站| 337p日本欧洲亚洲大胆色噜噜| 国产精品爱啪在线线免费观看| 久久久国产亚洲精品| 日本高清免费网站| 一级大黄美女免费播放| 亚洲AV无码乱码国产麻豆| 久久ww精品w免费人成| 99热亚洲色精品国产88| 免费国产精品视频| 中文字幕免费不卡二区| 亚洲人成网国产最新在线| 亚洲成网777777国产精品| 你懂的免费在线观看网站| 色天使亚洲综合在线观看| 亚洲精品视频久久久| 久久久久国产免费| 亚洲欧美在线x视频| 亚洲精品中文字幕乱码三区| 国产香蕉免费精品视频| 欧洲精品码一区二区三区免费看| 亚洲AV无码国产丝袜在线观看| 成年女人毛片免费观看97| jizz18免费视频| 亚洲五月午夜免费在线视频| 亚洲AV成人片色在线观看| 成人网站免费观看| 国产午夜成人免费看片无遮挡|