<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 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      24 隨筆 :: 0 文章 :: 52 評論 :: 0 Trackbacks
    在學(xué)習(xí)WebRTC時,網(wǎng)上的示例大多代碼較多,以下是參考那些代碼簡化的一個WebRTC一對一的示例,在chrome 37下測試通過。其中iceServer可省略,沒有iceServer時在同一個局域網(wǎng)下仍可通訊。

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

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

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

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

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

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

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

            
    // 發(fā)送offer和answer的函數(shù),發(fā)送本地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標(biāo)簽用于輸出
                document.getElementById('localVideo').src = URL.createObjectURL(stream);
                
    //向PeerConnection中加入需要發(fā)送的流
                pc.addStream(stream);
                
    //如果是發(fā)起方則發(fā)送一個offer信令
                if(isCaller){
                    pc.createOffer(sendOfferFn, 
    function (error) {
                        console.log('Failure callback: ' 
    + error);
                    });
                }
            }, 
    function(error){
                
    //處理媒體流創(chuàng)建失敗錯誤
                console.log('getUserMedia error: ' + error);
            });

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

    實現(xiàn)WebRTC時,信令服務(wù)器是必須的,它幫助客戶端之間進(jìn)行溝通。
    這里使用Node.js的ws模塊來實現(xiàn)一個WebSocket服務(wù)作為信令服務(wù)器。另外使用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的數(shù)組,這里只能有2個socket,每次測試需要重啟,否則會出錯
    var wsc = [],
    index = 1;

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

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

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

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

        // 轉(zhuǎn)發(fā)收到的消息
        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啟動服務(wù)。
    測試時使用Chrome瀏覽器:
    第一個瀏覽器窗口訪問頁面:http://127.0.0.1:3000,在彈出的提示中允許使用攝像頭和麥克風(fēng)。
    第二個瀏覽器窗口訪問頁面:http://127.0.0.1:3000#true,#true表示它是一個發(fā)起方,在彈出的提示中同樣允許使用攝像頭和麥克風(fēng)。
    這時頁面中應(yīng)當(dāng)可以看到2個畫面,一個是本地的,一個是遠(yuǎn)端的。

    將代碼中的IP稍做調(diào)整后部署到外網(wǎng),即可在2個不同的地點訪問這個頁面進(jìn)行實時通訊。


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

    評論

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

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

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

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

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

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

    主站蜘蛛池模板: 亚洲成a人在线看天堂无码| 亚洲一久久久久久久久| 美女被免费网站91色| 亚洲国产成人五月综合网| 亚洲av综合日韩| 免费v片在线观看| 精品女同一区二区三区免费播放| 免费国产高清视频| 一区二区三区在线免费| 狠狠色婷婷狠狠狠亚洲综合| 久久er国产精品免费观看8| 亚洲人成网77777亚洲色| 国产精品免费高清在线观看| 亚洲男人的天堂在线播放| **真实毛片免费观看| 亚洲偷自精品三十六区| 免费人成视频在线观看视频| 一级毛片a女人刺激视频免费| 亚洲熟妇丰满多毛XXXX| 亚欧免费无码aⅴ在线观看| 亚洲综合在线成人一区| 国产香蕉免费精品视频| 亚洲精品美女久久7777777| 亚洲国产一区二区视频网站| 在线毛片片免费观看| 亚洲免费观看网站| 免费va在线观看| 日本一卡精品视频免费| 亚洲欧美国产国产一区二区三区| 免费一级毛片女人图片| 暖暖免费日本在线中文| 亚洲综合精品成人| 亚洲色自偷自拍另类小说| 99视频全部免费精品全部四虎 | 国产AV无码专区亚洲AV男同 | 精品无码一级毛片免费视频观看| 亚洲色大成网站WWW久久九九 | 人人玩人人添人人澡免费| 亚洲videos| 国产成人毛片亚洲精品| 最新欧洲大片免费在线|