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

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

        <script>
            
    // 僅僅用于控制哪一端的瀏覽器發(fā)起offer,#號(hào)后面有值的一方發(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í)例 (參數(shù)為null則沒(méi)有iceserver,即使沒(méi)有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
                        }
                    }));
                }
            };

            
    // 如果檢測(cè)到媒體流連接到本地,將其綁定到一個(gè)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ā)送一個(gè)offer信令
                if(isCaller){
                    pc.createOffer(sendOfferFn, 
    function (error) {
                        console.log('Failure callback: ' 
    + error);
                    });
                }
            }, 
    function(error){
                
    //處理媒體流創(chuàng)建失敗錯(cuò)誤
                console.log('getUserMedia error: ' + error);
            });

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

    實(shí)現(xiàn)WebRTC時(shí),信令服務(wù)器是必須的,它幫助客戶端之間進(jìn)行溝通。
    這里使用Node.js的ws模塊來(lái)實(shí)現(xiàn)一個(gè)WebSocket服務(wù)作為信令服務(wù)器。另外使用express模塊讓它提供html頁(yè)面的訪問(wèn)。
    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});

    // 存儲(chǔ)socket的數(shù)組,這里只能有2個(gè)socket,每次測(cè)試需要重啟,否則會(huì)出錯(cuò)
    var wsc = [],
    index = 1;

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

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

        // 記下對(duì)方socket在數(shù)組中的下標(biāo),因?yàn)檫@個(gè)測(cè)試程序只允許2個(gè)socket
        // 所以第一個(gè)連入的socket存入0,第二個(gè)連入的就是存入1
        // otherIndex就反著來(lái),第一個(gè)socket的otherIndex下標(biāo)為1,第二個(gè)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啟動(dòng)服務(wù)。
    測(cè)試時(shí)使用Chrome瀏覽器:
    第一個(gè)瀏覽器窗口訪問(wèn)頁(yè)面:http://127.0.0.1:3000,在彈出的提示中允許使用攝像頭和麥克風(fēng)。
    第二個(gè)瀏覽器窗口訪問(wèn)頁(yè)面:http://127.0.0.1:3000#true,#true表示它是一個(gè)發(fā)起方,在彈出的提示中同樣允許使用攝像頭和麥克風(fēng)。
    這時(shí)頁(yè)面中應(yīng)當(dāng)可以看到2個(gè)畫面,一個(gè)是本地的,一個(gè)是遠(yuǎn)端的。

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


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

    評(píng)論

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

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

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

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

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

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

    主站蜘蛛池模板: 免费A级毛片在线播放不收费| 又黄又爽又成人免费视频| 在线播放免费播放av片| 亚洲av午夜福利精品一区人妖| 深夜久久AAAAA级毛片免费看| 久久WWW色情成人免费观看| 久久亚洲日韩精品一区二区三区 | 伊人久久亚洲综合影院| 亚洲理论片在线观看| 男女午夜24式免费视频 | 日本一道高清不卡免费| 亚洲国产精品综合久久2007| 无码精品人妻一区二区三区免费看 | 亚洲综合图片小说区热久久| 国产成人AV片无码免费| 国产AV无码专区亚洲AVJULIA| 97超高清在线观看免费视频| 国产亚洲精品成人AA片新蒲金| 一级黄色免费网站| 亚洲无码视频在线| 国产精品免费在线播放| 国产L精品国产亚洲区久久| 一区视频免费观看| 国产成人综合亚洲亚洲国产第一页| 一区二区三区在线免费| 国产国拍亚洲精品福利 | 人成午夜免费视频在线观看| 亚洲区视频在线观看| 毛片免费在线播放| 亚洲AV综合色区无码一二三区| 国产老女人精品免费视频| 国产精品亚洲а∨无码播放麻豆| 俄罗斯极品美女毛片免费播放| 无码日韩人妻AV一区免费l | 中国极品美軳免费观看| 亚洲av无码潮喷在线观看| 免费观看国产网址你懂的| 日本亚洲免费无线码 | 我们的2018在线观看免费高清 | 免费人成大片在线观看播放| 国产亚洲精品资在线|