视频聊天大厅 WebRTC实现网页版多人视频聊天室

编辑:
发布时间: 2020-12-17 00:20:37
分享:

因为产品中要加入网页中网络会议的功能,这几天都在倒腾 WebRTC,现在分享下工作成果。

话说 WebRTC

Real Time Communication 简称 RTC,是谷歌若干年前收购的一项技术,后来把这项技术应用到浏览器中并开源出来,而且搞了一套标准提交给W3C,称为WebRTC,官方地址是:http://www.webrtc.org/。WebRTC要求浏览器内置实时传输音视频的功能,并提供一致的API供JS使用。目前实现这套标准的浏览器有:Chrome、FireFox、Opera。微软虽然也在对WebRTC标准的制定做贡献,但仍然没有在任何版本的IE中支持WebRTC,所以,对于IE浏览器,不得不安装Chrome Frame插件来支持WebRTC;对于Safari浏览器,可以使用WebRtc4all这个插件,地址是:https://code.google.com/p/webrtc4all/。

WebRTC基础WebRTC提供了三个API:MediaStream、RTCPeerConnection、RTCDataChannel。 MediaStream 用于获取本地的 音视频流。不同的浏览器名称不一样,但参数一样,谷歌和Opera是navigator.webkitGetUserMedia,火狐是 navigator.mozGetUserMedia。 RTCPeerConnection:和 getUserMedia 一样 谷歌和火狐分别会有webkit、moz前缀。这个对象主要用于两个浏览器之间建立连接以及传输音视频流。 RTCDataChannel 用于两个浏览器之间传输自定义的数据,用这个对象可以实现互发消息,而不用经过服务端的中转。

WebRTC的实现是建立浏览器之间的直接连接,而不需要其他服务器的中转,即P2P,这就要求彼此之间需要知道对方的外网地址。但大多数计算机都位于NAT之后,只有少部分主机拥有外网地址,这就要求一种方式可以穿透NAT,STUN和TURN就是这样的技术。对于STUN和TURN的详细介绍,可以查看这里。

WebRTC会使用默认的或程序指定的SUTN服务器,获取指向当前主机的外网地址和端口。谷歌浏览器默认的是谷歌域名下的一个STUN,国内可能不大稳定,于是我找到了这个stunserver.org/ ,连接速度比较快,据说当年飞信就是使用的这个,应该比较可靠。如果信不过第三方的STUN服务,也可以自己搭建一台,搭建过程也挺简单。

P2P的建立过程需要依赖服务端中转外网IP及端口、音视频设备配置信息,所以服务端需要使用可以双工通讯的手段,比如WebSocket,来实现信令的中转,称之为信令服务器。

WebRTC会话的建立详解

会话的建立主要有两个过程:网络信息的交换、音视频设备信息的交换。以下以 lilei 要和 Lucy 开视频为例描述这两个过程。

网络信息的交换:

view sourceprint?01.publicclassSession : WebSocketHandler02.{03.privatestaticWebSocketCollection sessions =newWebSocketCollection;04.05.publicString UserId { get; set; }06.07.publicoverridevoidOnOpen08.{09.this.UserId = Guid.NewGuid.ToString;10.var message =new{ type = SignalMessageType.Conect, userId =this.UserId };11.sessions.Broadcast);12.13.sessions.Add; margin: 0px; padding: 0px; border: 0px; outline: 0px; background-image: none; float: none; vertical-align: baseline; position: static; left: auto; top: auto; right: auto; bottom: auto; height: auto; width: auto; font-family: "Courier New", 宋体;">this);14.}15.16.publicoverridevoidOnMessage17.{18.var obj = Json.Decode;19.var messageType = obj.type;20.21.switch22.{23.caseSignalMessageType.Offer:24.caseSignalMessageType.Answer:25.caseSignalMessageType.IceCandidate:26.var session = sessions.Cast.FirstOrDefault;27.var message =new{ type = messageType, userId =this.UserId, description = obj.description };28.session.Send);29.break;30.}31.}32.}33.34.publicenumSignalMessageType35.{36.Conect,37.DisConnect,38.Offer,39.Answer,40.IceCandidate41.}

WebAPI控制器需要引用命名空间“Microsoft.Web.WebSockets;”代码如下:

view sourceprint?01.publicclassSignalServerController : ApiController02.{03.[HttpGet]04.publicHttpResponseMessage Connect05.{06.var session =newWebRTCDemo.Session;07.HttpContext.Current.AcceptWebSocketRequest;08.09.returnnewHttpResponseMessage;10.}11.}JS脚本:view sourceprint?001.var RtcConnect = function {002.003.var config = { iceServers: [{ url:"stun:stunserver.org"}] };004.var peerConnection =null;005.var userId = _userId;006.var webSocketHelper = _webSocketHelper;007.008.var createVideo = function {009.var src = window.webkitURL.createObjectURL;010.var video = $.attr;011.var container = $.addClass.append.appendTo);012.013.video[0].play;014.returncontainer;015.};016.017.var init = function {018.019.window.RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection;020.peerConnection = window.RTCPeerConnection;021.022.peerConnection.addEventListener {023.createVideo;024.});025.peerConnection.addEventListener {026.var description = JSON.stringify;027.var message = JSON.stringify; margin: 0px; padding: 0px; border: 0px; outline: 0px; background-image: none; float: none; vertical-align: baseline; position: static; left: auto; top: auto; right: auto; bottom: auto; height: auto; width: auto; font-family: "Courier New", 宋体;">4, userId: userId, description: description });028.webSocketHelper.send;029.});030.031.navigator.getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;032.var localStream = navigator.getMedia; margin: 0px; padding: 0px; border: 0px; outline: 0px; background-image: none; float: none; vertical-align: baseline; position: static; left: auto; top: auto; right: auto; bottom: auto; height: auto; width: auto; font-family: "Courier New", 宋体;">true, audio:true}, getUserMediaSuccess, getUserMediaFail);033.peerConnection.addStream;034.035.};036.037.this.connect = function {038.peerConnection.createOffer {039.peerConnection.setLocalDescription;040.041.var description = JSON.stringify;042.var message = JSON.stringify; margin: 0px; padding: 0px; border: 0px; outline: 0px; background-image: none; float: none; vertical-align: baseline; position: static; left: auto; top: auto; right: auto; bottom: auto; height: auto; width: auto; font-family: "Courier New", 宋体;">2, userId: userId, description: description });043.webSocketHelper.send;044.});045.046.};047.048.this.acceptOffer = function {049.peerConnection.setRemoteDescription; margin: 0px; padding: 0px; border: 0px; outline: 0px; background-image: none; float: none; vertical-align: baseline; position: static; left: auto; top: auto; right: auto; bottom: auto; height: auto; width: auto; font-family: "Courier New", 宋体;">newRTCSessionDescription);050.peerConnection.createAnswer {051.peerConnection.setLocalDescription;052.var description = JSON.stringify;053.054.var message = JSON.stringify; margin: 0px; padding: 0px; border: 0px; outline: 0px; background-image: none; float: none; vertical-align: baseline; position: static; left: auto; top: auto; right: auto; bottom: auto; height: auto; width: auto; font-family: "Courier New", 宋体;">3, userId: userId, description: description });055.webSocketHelper.send;056.});057.};058.059.this.acceptAnswer = function {060.peerConnection.setRemoteDescription; margin: 0px; padding: 0px; border: 0px; outline: 0px; background-image: none; float: none; vertical-align: baseline; position: static; left: auto; top: auto; right: auto; bottom: auto; height: auto; width: auto; font-family: "Courier New", 宋体;">newRTCSessionDescription);061.062.};063.064.this.addIceCandidate = function {065.peerConnection.addIceCandidate; margin: 0px; padding: 0px; border: 0px; outline: 0px; background-image: none; float: none; vertical-align: baseline; position: static; left: auto; top: auto; right: auto; bottom: auto; height: auto; width: auto; font-family: "Courier New", 宋体;">newRTCIceCandidate);066.};067.068.init;069.070.};071.072.var WebSocketHelper = function {073.var ws =null;074.var url ="ws://"+ document.location.host +"/api/Signal/Connect";075.076.var init = function {077.ws =newWebSocket;078.ws.onmessage = onmessage;079.ws.onerror = onerror;080.ws.onopen = onopen;081.};082.083.var onmessage = function {084.callback);085.};086.087.this.send = function {088.ws.send;089.};090.091.init;092.};093.094.$ {095.096.var rtcConnects = {};097.var webSocketHelper =newWebSocketHelper {098.var rtcConnect = getOrCreateRtcConnect;099.switch {100.case0://Conect101.rtcConnect.connect;102.break;103.case2://Offer104.rtcConnect.acceptOffer);105.break;106.case3://Answer107.rtcConnect.acceptAnswer);108.break;109.case4://IceCandidate110.rtcConnect.addIceCandidate);111.break;112.default:113.break;114.}115.});116.117.var init = function {118.navigator.getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;119.var stream = navigator.getMedia; margin: 0px; padding: 0px; border: 0px; outline: 0px; background-image: none; float: none; vertical-align: baseline; position: static; left: auto; top: auto; right: auto; bottom: auto; height: auto; width: auto; font-family: "Courier New", 宋体;">true, audio:true}, function {120.var src = window.webkitURL.createObjectURL;121.var video = $.attr;122.$.addClass.append.appendTo);123.124.video[0].play;125.}, function { console.error; });126.};127.128.var getOrCreateRtcConnect = function {129.var rtcConnect = rtcConnects[userId];130.if =="undefined") {131.rtcConnect =newrtcConnect;132.rtcConnects[userId] = rtcConnect;133.}134.returnrtcConnect;135.};136.init;137.});View代码:view sourceprint?01.02.03.07.08.09.10.编译后部署到IIS上,让同事都来试试,略有激动。其他

如果想部署自己专用的STUN服务器,这里有STUN服务器的完整开源实现,原生是运行在Linux上的,但也提供了cgwin下编译的windwos版本。如何编译、运行等在它的github主页上说的比较清楚:https://github.com/jselbie/stunserver。

如果觉得自己写那一坨js比较繁琐,这里有一个封装库,简单了解了一下,功能挺强大的。

延伸阅读:1、ASP.NET 使用application和session对象写的简单聊天室程序2、ASP.NET列印所显示的网页内容3、升级ASP.NET 4.5 网页开发技术的新助力4、ASP.net MVC ckeditor网页编辑器 字型、图片上传功能的快速安装笔记5、ASP.NET MVC显示WebForm网页或UserControl控件
相关阅读
热门精选
孩子 皮肤