码迷,mamicode.com
首页 > Web开发 > 详细

websocket连通本地webrtc

时间:2016-11-14 15:45:51      阅读:441      评论:0      收藏:0      [点我收藏+]

标签:else   error   http   通知   rem   ges   expr   参数   建立   

  最近各大直播网站都比较火,想探究一下是怎么玩的。但是看了几个大牛的回答,感觉有太多陌生的东西,尝试起来成本略高。发现了有个东西叫webrtc,有人分析过他不适合做流量大,人数多的直播。但是我也只是玩一下,感受一下视频连通的感觉。
  一开始在github上面看到了一个,比较全大部分的API都做了demo,还有canva 3d融合webrtc的例子。因为大部分例子都是没有经过网络的通讯,所以想用socket写一个交换信令的demo。其中也找到过demo但是没试通过...然后看一些博客和API自己写一个小demo,帮助理解webrtc
  目录结构就是这样  只拉取了express socket.io
     技术分享


     前端代码:
     html部分
  

        <script src="/socket.io/socket.io.js"></script>  
        Local: <br>
        <video id="localVideo" autoplay style="width:80px"></video><br>
        Remote: <br>
        <video id="remoteVideo" autoplay style="width:80px"></video>

 



  js部分

// 判断发起端  
            var isCaller = window.location.href.split(‘#‘)[1];
            // 信令服务器的Socket连接
            var socket = io.connect(‘http://localhost:3000‘);
            // stun和turn服务器
            var iceServer = null;

            // iceServer在局域网下可以通讯
            var pc = new webkitRTCPeerConnection(iceServer);

            // 发送给的其他端通知
            pc.onicecandidate = function(event){
                if (event.candidate !== null) {
                    debugger
                    console.log(‘onicecandidate -----‘);
                    socket.emit(‘message‘,JSON.stringify({
                        "event": "_ice_candidate",
                        "data": {
                            "candidate": event.candidate
                        }
                    }));
                }
            };

            // 建立好p2p通道以后 会通过OnAddStream返回一个音视频流的对象
            pc.onaddstream = function(event){
                document.getElementById(‘remoteVideo‘).src = URL.createObjectURL(event.stream);
            };

            // offer和answer 
            var sendOfferFn = function(desc){
                pc.setLocalDescription(desc);
                console.log(‘Offer -----‘);
                socket.emit(‘message‘,JSON.stringify(desc));
            },
            sendAnswerFn = function(desc){
                pc.setLocalDescription(desc);
                console.log(‘Answer -----‘);
                socket.emit(‘message‘,JSON.stringify(desc));
            };

            // 获取本地音频和视频流
            navigator.webkitGetUserMedia({
                "audio": true,
                "video": true
            }, function(stream){
                //在localVideo输出音视频
                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.on(‘message‘,function(event){//处理socket请求
                
                if(event.type){
                    console.log(‘请求以返回--------‘+event.type);
                }else{
                    console.log(‘--------‘)
                    console.log(event);
                }

                if(event.type==‘offer‘ && !isCaller){
                    pc.setRemoteDescription(event)
                    pc.createAnswer(sendAnswerFn, function (error) {
                            console.log(‘Failure callback: ‘ + error);
                    });
                }
                if(event.type==‘answer‘  && isCaller){
                    pc.setRemoteDescription(event)
                }
                if(event.event==‘_ice_candidate‘){
                    pc.addIceCandidate(new RTCIceCandidate(event.data.candidate));
                }
            })

  node部分

var express = require(‘express‘);
var app = express()
var server = require(‘http‘).Server(app);
var io = require(‘socket.io‘)(server);

server.listen(3000);
app.use(express.static(__dirname + ‘/js‘));
app.get(‘/‘, function (req, res) {
  res.sendfile(__dirname + ‘/index.html‘);
});
io.on(‘connection‘, function (socket) {
    socket.on(‘message‘,function(data){
        
        var message=JSON.parse(data);
        if(message.type){
            console.log(message.type);
        }else{
            console.log(message.event);
        }
        console.log(‘请求已经广播出去--------‘);
        socket.broadcast.emit(‘message‘,message);            
    })
    

});

访问localhost:3000开启一个端  
然后访问localhost:3000#true (开始进行对localhos:3000进行连接)

    下面具体流程转载 烟雨任平生的

  • ClientA首先创建PeerConnection对象,然后打开本地音视频设备,将音视频数据封装成MediaStream添加到PeerConnection中。
  • ClientA调用PeerConnection的CreateOffer方法创建一个用于offer的SDP对象,SDP对象中保存当前音视频的相关参数。ClientA通过PeerConnection的SetLocalDescription方法将该SDP对象保存起来,并通过Signal服务器发送给ClientB。
  • ClientB接收到ClientA发送过的offer SDP对象,通过PeerConnection的SetRemoteDescription方法将其保存起来,并调用PeerConnection的CreateAnswer方法创建一个应答的SDP对象,通过PeerConnection的SetLocalDescription的方法保存该应答SDP对象并将它通过Signal服务器发送给ClientA。
  • ClientA接收到ClientB发送过来的应答SDP对象,将其通过PeerConnection的SetRemoteDescription方法保存起来。
  • 在SDP信息的offer/answer流程中,ClientA和ClientB已经根据SDP信息创建好相应的音频Channel和视频Channel并开启Candidate数据的收集,Candidate数据可以简单地理解成Client端的IP地址信息(本地IP地址、公网IP地址、Relay服务端分配的地址)。
  • 当ClientA收集到Candidate信息后,PeerConnection会通过OnIceCandidate接口给ClientA发送通知,ClientA将收到的Candidate信息通过Signal服务器发送给ClientB,ClientB通过PeerConnection的AddIceCandidate方法保存起来。同样的操作ClientB对ClientA再来一次。
  • 这样ClientA和ClientB就已经建立了音视频传输的P2P通道,ClientB接收到ClientA传送过来的音视频流,会通过PeerConnection的OnAddStream回调接口返回一个标识ClientA端音视频流的MediaStream对象,在ClientB端渲染出来即可。同样操作也适应ClientB到ClientA的音视频流的传输。


      具体流程可以参考:http://www.cnblogs.com/fangkm/p/4364553.html 他写的比较细节,清新脱俗

websocket连通本地webrtc

标签:else   error   http   通知   rem   ges   expr   参数   建立   

原文地址:http://www.cnblogs.com/meihuanyu/p/6061692.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!