websocket连通本地webrtc

  最近各大直播网站都比较火,想探究一下是怎么玩的。但是看了几个大牛的回答,感觉有太多陌生的东西,尝试起来成本略高。发现了有个东西叫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 他写的比较细节,清新脱俗

时间: 2024-10-31 03:21:56

websocket连通本地webrtc的相关文章

javaweb + websocket实现客户端

最近需要完成一个javaweb项目,但是没有和数据库连接而是通过websocket通讯实现和服务器端数据交互.我搜了好多,网上大部分都是通过页面websocket连接本地服务器或连接异地服务器,但是这些都把连接地址暴露在了外面,不是我想要的.本人希望websocket连接.数据处理等都是在java后端完成的,结合网上的一些参考资料终于实现了此功能. 这里有个比较好的Java后端WebSocket的Tomcat实现栗子,不过是将本地tomcat作为服务器,websocket连接也暴露在页面. 接下

Docker 集群环境实现方式

Docker 集群环境实现的新方式 近几年来,Docker 作为一个开源的应用容器引擎,深受广大开发者的欢迎.随着 Docker 生态圈的不断建设,应用领域越来越广.云计算,大数据,移动技术的快速发展,加之企业业务需求的不断变化,紧随技术更新的步伐,导致企业架构要随时更改以适合业务需求.当前,越来越多的公司都已将以 Docker 为代表的容器技术用于企业级业务平台,比如:腾讯,京东,美团,新浪,阿里巴巴等互联网公司.数据的安全.Docker 容器的稳定运行是众多用户关注的,这就要求我们提供一套行

Android SDK Manager和AVD Manager使用

Android SDK Manager和AVD Manager使用(win7_64bit下测试) 目录 1.概述 2.本文用到的工具 3.安卓开发基础工具包下载 4.Android SDK Manager使用 5.AVD Manager使用 6.注意事项 7.相关博文(AndroidStudio.IDEA.Eclipse安卓环境配置) >>看不清的图片可在新标签打开查看大图 1.概述 顾名思义,Android SDK Manager就是一个Android软件开发工具包管理器,就像一个桥梁,连通

Docker 集群环境实现的新方式

近几年来,Docker 作为一个开源的应用容器引擎,深受广大开发者的欢迎.随着 Docker 生态圈的不断建设,应用领域越来越广.云计算,大数据,移动技术的快速发展,加之企业业务需求的不断变化,紧随技术更新的步伐,导致企业架构要随时更改以适合业务需求.当前,越来越多的公司都已将以 Docker 为代表的容器技术用于企业级业务平台,比如:腾讯,京东,美团,新浪,阿里巴巴等互联网公司.数据的安全.Docker 容器的稳定运行是众多用户关注的,这就要求我们提供一套行之有效的管理大型容器集群的整体解决方

Bigbluebutton安装过程

BigBlueButton安装过程(翻译) 欢迎来到BigBlueButton 1.0-beta安装指南(以下简称BigBlueButton 1.0).BigBlueButton是一个开放源代码的网络会议系统进行在线学习.有关概述了本版本中新的,请参阅概述. 建议将bigbluebutton 1.0安装在没有运行任何其他Web应用程序的 Ubuntu 14.04的64位服务器上(最好是独立服务器).这将避免微妙的冲突(如潜在的配置文件),可能导致bigbluebutton安装和运行误差. 安装前

搭建属于你的在线实时采集系统 ——HTML5 在嵌入式系统中的应用

※已刊登在<无线电>04月刊上   搭建属于你的在线实时采集系统--HTML5 在嵌入式系统中的应用   作者:刘琛,徐洋   摘要: 本应用摆脱了以往嵌入式系统的数据采集方式,借助于最新的HTML5的Canvas API及WebSocket API两大特性,实现了数据的在线实时采集功能.提升了嵌入式采集系统的性能及体验.为嵌入式开发工作者提供参考.   关键字:HTML5:HTTP Server:Canvas:WebSocket:W5500:实时:采集系统:      当今信息社会,信息就是

Blazor(WebAssembly) + .NETCore 实现斗地主

原文:Blazor(WebAssembly) + .NETCore 实现斗地主 之前群里大神发了一个 html5+ .NETCore的斗地主,刚好在看Blazor WebAssembly 就尝试重写试试. 还有就是有些标题党了,因为文章里几乎没有斗地主的相关实现:),这里主要介绍一些Blazor前端的一些方法实现而斗地主的实现总结来说就是获取数据绑定UI,语法上基本就是Razor,页面上的注入语法等不在重复介绍,完整实现可以查看github:https://github.com/saber-wa

2.Android-sdk目录介绍、ADT使用介绍、创建helloworld

1.android中常用名词介绍 ADT:  ADT为Eclipse的插件.为Eclipse和SDK之间起了一个桥梁的作用. SDK: 软件开发工具包(Soft Development Kit),它为开发者提供了Android库文件以及其它开发所用到的工具 JDK:  java开发工具包,提供java工具和java库以及运行环境. NDK: Native Development Kit, 帮助开发者快速开发C(或C++)的动态库, 并能自动将so和java应用一起打包成apk(后面再使用) 2.

websocket+webrtc+tomcat 实现视频监考功能

最近几天笔试,发现好多的线上笔试都会有视频监考的功能,个人对其挺感兴趣,所以花了一天时间,研究了一下,写了一个小demo,下面说的有任何纰漏希望大家多多指正,下面开说了,大多数的视频监考就是通过浏览器,获取你电脑上的摄像头,来实现视频监考的功能的,所以相当于你的电脑是客户端,而公司那边是服务器,所以这大体上是一个客户端服务器模式,但是要通过浏览器来做客户端,通过浏览器来做服务端,这时候就要涉及到浏览器和浏览器之间的通信了,但是浏览器和浏览器之间直接通信比较困难,所以还是要用一个中间服务器来做转发