使用 WebRTC 广播 IP 摄像头视频流

使用WebRTC广播IP摄像头视频流

技术上来说,从IP摄像头实现在线广播并不需要WebRTC。IP摄像头本身就是服务器,可以自行连接路由器并传输视频内容。既然这样,我们为什么还需要WebRTC?

有两个原因:
1.随着观看以太网广播的观众增加,他们会逐步感受到带宽的不足,然后是摄像头资源,如果观众持续增加的话;
2.如上面提到的,一个IP摄像头就是一个服务器。但是它使用什么协议传输视频到浏览器或者移动设备?一个使用HTTP的摄像头很有可能基于HTTP传输视频帧或者JPEG图像。但是,HTTP流并不完全适用于实时视频传输。对于请求式视频,它确实工作良好,但是仅限于互动性和延迟要求不高的场合。确实,如果你在线观看一部电影,延迟5-10秒确实不太重要。好吧,除非你在和其他人同时观看:“oh,不,杰克谋杀了她!”爱丽丝给鲍勃发送信息10s之后,鲍勃才看到了这一幕悲剧。

另外一个选项是RTSP/RTP加上H.264。但是这种情况下浏览器需要安装一个视频播放插件,例如VLC或者QuickTime。这类插件将会接受并播放视频,就像播放器一样。但我们需要真实的基于浏览器的流,不需要任何附加的工具。

好,现在让我们“sniff”我们的IP摄像头,学习一下它到底向浏览器发送了什么。我们采用D-Link DCS 7010L来做测试:

D-Link DCS 7010L

你可以获取并控制更多摄像头的配置,但我们只是简单地来看它如何处理视频流。当我们登录到摄像头的管理员界面,我们可以在摄像头的Web接口中看到如下画面:

Web-Interface

The image opens in all browsers and shows nearly the same once per second lags. 假定摄像头和笔记本电脑都连接到同一台路由器,我们期望看到平稳的,流畅的重放,但实际上并不是。看起来HTTP是原因所在。我们运行Wireshark,来确认我们的推测:

这里写图片描述

这里我们可以看到一系列1514字节的TCP片段:

这里写图片描述

和一个结束的HTTP 200 OK响应,包含了接收到的JPEG的字节长度:

这里写图片描述

然后,我们打开 Chrome / Developer Tools / Network 看一下实时的GET请求和通过HTTP传输的图像:

这里写图片描述

我们不需要这样的流。它并不流畅。it jerks HTTP requests back and forth。摄像头可以处理多少这样的请求?我们估计10个观看者就能让摄像头停工,或者变得非常缓慢。

来看一下摄像头管理界面的HTML源代码,我们可以发现如下的代码:

if(browser_IE)
  DW('<OBJECT CLASSID="CLSID:'+AxUuid+'" CODEBASE="/VDControl.CAB?'+AxVer+'#version='+AxVer+'" width="0" height="0" ></OBJECT>');
else
{
  if(mpMode == 1)
    var RTSPName = g_RTSPName1;
  else if(mpMode == 2)
    var RTSPName = g_RTSPName2;
  else if(mpMode == 3)
    var RTSPName = g_RTSPName3;

  var o='';

    if(g_isIPv6)
    //because ipv6 not support rtsp.
        var host = g_netip;
    else
        var host = g_host;

  o+='<object id="qtrtsp_object" width="0" height="0" codebase="http://www.apple.com/qtactivex/qtplugin.cab" ';
        o+='classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" type="video/quicktime">';
  o+='<param name="src" value="http://'+host+":"+g_Port+'/qt.mov" />';
  o+='<param name="autoplay" value="true" />';
  o+='<param name="controller" value="false" />';
  o+='<param name="qtsrc" value="rtsp://'+host+':'+g_RTSPPort+'/'+RTSPName+'"/>';
  o+='</object>';
  //alert(o);
  DW(o);
}

RTSP/RTP 是我们需要用来平稳播放视频的协议。但是它可以在浏览器上工作吗?不可以。它可以配合已安装的QuickTime插件工作,但是我们需要“纯净”的浏览器流。

另一个值得一提的选项是Flash Player,它也可以通过Wowza接收从RTSP,RTP,H.264转换来的RTMP流。但是Flash Player也是一个浏览器插件,尽管比VLC或者QuickTime更流行。

我们测试了相同的RTSP/RTP重传,但是我们使用WebRTC兼容的浏览器作为播放器,没有任何额外的插件或工具。我们搭建了一个“转译”服务器,从IP摄像头抓取视频流,然后通过Internet广播给任意的使用WebRTC浏览器的用户。

连接IP摄像头

如上面提到的,我们选择的是一个非常简单的D-Link DCS 7010L IP摄像头。做这个选择的关键因素是对RTSP的支持,因为基于这个协议,服务器才可以从摄像头抓取流。

用电缆连接摄像头到路由器,摄像头开始启动;它识别到了路由器,然后使用DHCP获取到了IP地址。这里我们的地址是192.168.1.134(你也可以在路由器的连接设备里看到它 - DCS 7010L)。现在我们来测试这个摄像头。

在浏览器中打开这个IP地址,进入摄像头的管理界面。默认的密码为空。

这里写图片描述

你可以看到,摄像头输出的视频在管理界面上播放良好。但是,我们确实看到了周期性的抖动。那正是我们准备使用WebRTC解决的问题。

配置摄像头

出于测试目的,我们禁止掉了身份验证,我们允许所有人看到这个广播。设置步骤:配置 - 网络,禁止授权。

同样在这部分中,我们查看RTSP是否使用正确的端口。默认地,端口号是554。输出视频的格式在配置文件中指定。你可以设置为多达3种格式,但是我们使用第一种 - live1.sdp - 因为它已经被配置为H.264的视频和G.711的音频。任何设定都可以通过: 配置 - 音频和视频 来修改。

这里写图片描述

现在我们可以通过RTSP测试摄像头操作。打开VLC播放器(或者其他支持RTSP的播放器 - QuickTime,Windows Media Player,RealPlayer 或者其他),在打开URL对话框中指定摄像头的RTSP地址: rtsp://192.168.1.34/live1.sdp

这里写图片描述

好的,它开始工作。摄像头使用RTSP发送视频流给播放器。

这里写图片描述

视频非常流畅,完全没有伪影。我们期待在WebRTC上看到同样的效果。

安装服务器

所以,摄像头已经被安装,使用桌面播放器进行了测试,已经准备好通过服务器进行广播。使用 whatismyip.com, 我们可以看到摄像头的外部网络地址:178.51.142.223。现在我们需要告诉路由器,重定向所有通过554端口发出的RTSP请求到IP摄像头。

现在我们在路由器中键入相应的设定…

这里写图片描述

使用telnet来检测外部地址和RTSP端口:

telnet 178.51.142.223 554

在确认端口响应之后,我们开始安装WebRTC服务器。

主机服务由Amazon EC2 Centos 64 bit 服务器提供。为了减少性能问题的可能性,我们选择m3.medium例程,1个VCPU:

这里写图片描述

当然,可选择的还有Linode和DigitalOcean,但我们这次选择使用Amazon。在开始之前,Amazon EC2 控制面板需要特定的端口配置,以便让这个测试工作。这些是WebRTC(SRTP,RTCP,ICE)传输和RTSP/RTP传输需要的端口。如果你也决定测试这些项,要确保Amazon incoming traffic panel 看起来像下面这样:

这里写图片描述

DigitalOcean 相对更简单,你仅需要在防火墙中关闭这些端口,或者完全mute掉它。根据我们使用DO实例的经验,他们仍然提供一个静态的IP地址,而没有跟任何NATs搅和在一起,所以不需要进行像Amazon那样的端口配置。

用来广播RTSP/RTP流到WebRTC的服务器软件,我们使用Flashphoner提供的WebRTC Media & Broadcasting Server。这个流服务器看起来非常像Wowza,一个可以通过Flash广播RTSP/RTP的工具。唯一的不同是流实际上是通过WebRTC传输,而不是Flash。技术上讲,这意味着浏览器和服务器使用DTLS通信,建立SRTP会话,传输VP8编码视频给观众。

安装需要SSH-access。

Sopiler: 如下是完整的命令列表:

  1. 从服务器下载安装包:
    wget flashphoner.com/downloads/builds/WCS/3.0/x8664/wcs3_video_vp8/FlashphonerMediaServerWebRTC-3.0/FlashphonerMediaServerWebRTC-3.0.868.tar.gz
  2. 解压:
    tar -xzf FlashphonerMediaServerWebRTC-3.0.868.tar.gz
  3. 安装:
    cd FlashphonerMediaServerWebRTC-3.0.868
    ./install.sh
    Configure the external IP-address of the server: 54.186.112.111 and the Private IP: 172.31.20.65.
  4. 启动服务:
    service webcallserver start
  5. 查看日志:
    tail — f /usr/local/FlashphonerWebCallServer/logs/server_logs/flashphoner.log
  6. 确认服务运行:
    ps aux | grep Flashphoner
  7. 安装并启动 apache:
    yum install httpd
    service httpd start
  8. 下载 web-files 放置在Apace的默认的目录:
    cd /var/www/html
    wget github.com/flashphoner/flashphoner_client/archive/wcs_media_client.zip
    unzip webrtc_media_client.zip
  9. 在配置文件 flashphoner.xml 中输入服务器IP地址:
  10. 关闭防火墙
    service iptables stop

理论上,最后一步你应该在防火墙中配置端口和规则,这里处于测试目的我们将它关闭。

配置服务

我们的WebRTC广播架构如下:

这里写图片描述

我们已经配置好了这张图中的基本元素。现在我们需要配置“箭头”。

Web 客户端负责WebRTC 服务器和浏览器之间的互联。它可以在 github 下载到。客户端的JS,CSS,HTML文件在安装过程中已经被上传到 /var/www/html (见第九步)。

浏览器-服务器的通信在XML文件 falshphoner.xml 中被配置。我们应该写明服务器的IP地址,这样Web 客户端才可以通过HTML5 Websockets连接到WebRTC 服务器(见第九步)。

好了,我们已经完成了服务器配置,让我们来进行测试:

在浏览器中打开Web 客户端的索引文件 index.html (我们需要在Amazon 服务器上安装 apache:yum -y install httpd):

http://54.186.112.111/wcs_media_client/?id=rtsp://webrtc-ipcam.ddns.net/live1.sdp

webrtc-ipcam.ddns.net — 是个可以通过动态DNS noip.com 获取的免费域名,链接到我们的外部IP地址。同时,我们告诉路由器根据NAT地址转换规则转发发送到192.168.1.24的RTSP请求。

参数 id=rtsp://webrtc-ipcam.ddns.net/live1.sdp 设置将要播放的流的URL地址。WebRTC服务器从IP摄像头抓取流,进行处理,然后使用WebRTC广播到浏览器。可能你的路由器不支持DDNS,如果这样,你可以使用摄像头的选项:

这里写图片描述

这里是路由器支持DDNS的界面:

这里写图片描述

好了,现在来测试整个系统。

测试

浏览器打开连接后,就开始连接到WebRTC服务器。服务器发送请求到IP摄像头来抓取流。这个过程需要几秒钟。

这里写图片描述

浏览器通过webscokets连接到服务器,然后服务器通过RTSP询问摄像头,通过RTP获取H.264流,转码成最终可以兼容WebRTC的浏览器支持的VP8/SRTP格式。

这里写图片描述

短暂的延迟后,我们看到了相似的画面。

这里写图片描述

视频的底部显示出视频流的URL。你可以复制它到另外的浏览器并打开。

确认它确实是WebRTC

我们如何确信视频不是从HTTP传输过来的?让我们不要相信纯粹的图像,来检查下我们实际接收到的是哪种传输。再次运行Wireshark和Chrome 调试控制台。在Chrome 控制台我们可以看到如下信息:

这里写图片描述

这次没有任何信息进来和送出去,没有图像通过HTTP传输。所有看到的都是Websocket 帧,其中大部分都是用来保持活动Websocket会话的ping/pong类型。这里有些有趣的帧:connect, prepareRtspSession and onReadyToPlay — 通过这些精确的步骤建立起的到服务器的连接,首先 Websocket 连接,然后是 playback 请求。

这里是 chrome://webrtc-internals 显示的信息:

这里写图片描述

根据这个图表,we have a bitrate from IP-cam of 1Mbps. 同时也有对外的传输,很有可能是RTCP和ICE包。到Amazon服务器的RTT大概是300毫秒。

现在我们来看下Wireshark。它清楚显示出了从IP地址到服务器的UDP传输。图中底部的包大小是1468字节。这就是WebRTC. 特别是我们可以在浏览器中看到的VP8视频帧对应的SRTP帧。此外,我们可以看到一些STUN请求(图中最下部的包)— 这是WebRTC ICE在仔细地坚持连接状况。

这里写图片描述

值得一提的是视频回放表现出了相对较低的延迟(到数据中心的ping 大概是260ms)。WebRTC 通过SRTP/UDP 工作,和HTTP,RTMP以及其他的类TCP流方式相比,这是用来传输数据包的最快方式。因此,可见的延迟应该来自RTT + 缓冲时间,解码和回放延迟。

实际上裸眼看不到任何延迟,这意味着延迟小于500ms。

接下来的测试是连接其他观众。我们打开了10个Chrome窗口,每个窗口都显示视频。这导致Chrome运行缓慢。但在其他电脑中打开第11个窗口时,视频仍然保持流畅。

移动设备上的WebRTC

如你所知,Chrome和Firefox浏览器的Android版本也支持WebRTC。来看看我们的广播是否可以正常工作:

这里写图片描述

一台HTC智能手机上的Firefox浏览器显示了来自IP摄像头的视频。和PC相比,在流畅性方便没有任何差别。

结论

就这样,我们没有费太多功夫,就运行了从IP摄像头到多个浏览器的WebRTC在线广播。既不需要“rain dancing(祈雨)”或者“voodoo(巫术)”,也不需要“rocket science”(高深的技术),只需要基本的Linux和SSH知识。

广播的质量是完全可以接受的,延迟也是肉眼不可见的。

我们可以得出结论:基于浏览器的WebRTC广播一定只得考虑,就像我们的例子中,WebRTC 并不是附件组件或插件,而是一个在浏览器中播放视频的真实平台。

为什么WebRTC没有被普遍使用

主要的障碍可能是,编解码器的缺乏。WebRTC 社区和供应商应该努力在WebRTC中嵌入H.264。我们不能说VP8有任何不好,但是为什么要忽略掉已经和H.264兼容的设备和软件呢? 这些可恶的专利……

第二个原因是并不是所有浏览器都支持WebRTC。如IE和Safari,在这些平台上,我们还是不得不使用其他方式或者插件(如webrtc4call)来获取/发送流。

我们希望看到更多有趣的方案,不再需要转码,有更多的浏览器可以直接播放来自各种设备的流。

许可

This article, along with any associated source code and files, is licensed under The MIT License

原作者

Alexey Nikolaev

展开阅读全文

没有更多推荐了,返回首页