对于从事某些行业的程序员童鞋们,或多或少会接触到监控视频(摄像头),本系列文章讲述怎样在浏览器上播放摄像头监控画面,并给出简单易行的解决方案。

本系列文章是面向Web研发人员的,不要求对视频有专业的知识储备。在文章中会触碰到例如RTSP、GB28181、H264、H265、HLS等专业名词,我会浅尝辄止的讲解一点,不会阻碍你的阅读和理解,而且文章本来是就为了童鞋们不求甚解拿来就用为目的的,因此这就开始吧。

HLS是一种无需插件的在浏览器上播放视频的协议,html5中的video直接就可以用来播放视频:

<video id="myVideo" class="video-js vjs-default-skin vjs-big-play-centered" controls preload="auto" data-setup='{}' style='width: 100%;height: auto'>
  <source id="source" src="/videoplay/test.m3u8" type="application/x-mpegURL"></source>
</video>

上面代码中的src=“/videoplay/test.m3u8”就是符合HLS协议的视频流,我们打开videoplay目录,看到的是这样的一些文件:

以上就是HLS的组成,一个.m3u8文本文件和几个.ts视频文件。

先说一下HLS播放原理:

1)每个.ts视频文件记录了1~2秒的视频片段,他们衔接在一起就能形成连续的视频流。

2).m3u8文件是个索引文件,里面描述了当前应该播放第几个.ts视频文件和他们的播放顺序。

3)浏览器会周期性的读取.m3u8文件,依据.m3u8文件中的索引,获得相应的.ts文件,并在video标签中组装并播放。

HLS就是这么简单,不需要什么流媒体服务器,也不需要通过什么websocket传输,更不需要安装什么插件,一切都是看得见摸得着的静态文件,只要我们知道怎样动态生成m3u8和ts文件就行,正如我们人生中的大多数问题,大体上就是只要怎样怎样,就能怎样怎样。。。

下来我们就一起来看看怎么来 只要

视频本身的实践性是很强的,所以最好边看边动起手来。

实验需要以下设备和软件:

  • 至少一个rtsp协议的H264摄像头
  • vlc播放软件
  • ffmpeg库程序
  • 摄像头 需要输出RTSP协议并且视频需要H264格式。RTSP协议通常是直接访问摄像头的视频协议,它的地址一般像这样的:

    rtsp://admin:1234@192.168.0.10:554
    

    国内常见的另一种视频协议是国标GB28181,这种协议本文方案不支持,需要通过其他手段先转为RTSP。H264是视频编码格式,可以理解为视频有损压缩算法及其封装格式,目前更先进的是H265,但很可惜HLS还支持不了。

    如果环境里没有符合要求的视频源(摄像头),那就买一个吧,一两百块钱,适当的投资还是必要的,就当掏学费了。

    vlc是播放软件,可以直接播放rtsp视频流。对于HLS它不是必须的,但调试视频环节中是必不可少的,比如出现问题时我们需要判断是摄像头本身的问题还是我们程序的问题,就需要它。vlc软件长这样:

    ffmpeg是著名的开源的视频转码库,说到著名,是因为只要做视频研发就基本离不开它,本文方案中将RTSP转为HLS就是用它。你可以从ffmpeg官网上下载,这里建议下载一会儿要用的rtsp2hls中间件,里面就包含了ffmpeg程序,下载地址:

    https://gitee.com/dyf029/module-proxy/releases/v0.2

    下载其中的 rtsp2hls_win_202111.zip

    windows环境。

    1)打开vlc程序,菜单:媒体--打开网络串流,输入摄像头rtsp地址:

    点击播放按钮,先验证环境中的视频源是可以播放的:

    2)打开cmd,进入rtsp2hls的bin目录(这里有ffmpeg.exe),输入:

    ffmpeg -rtsp_transport tcp -i rtsp://admin:Pass1234@2.36.207.50:554 -fflags flush_packets -max_delay 2 -flags -global_header -hls_init_time 0.5 -hls_time 1 -hls_wrap 5 -acodec copy -vcodec copy -y D:\TMP\test\video.m3u8

    注意,命令行中的rtsp地址是刚才能用vlc播放的地址,并确保D:\TMP\test\目录已经存在。命令行参数很长很复杂,我们先把它们放在一边,第一要务是运行起来。回车,CMD中正常的输出如下:

    再查看D:\TMP\test\目录,ffmpeg已经工作并输出了.m3u8和.ts文件,仔细观察这些文件在随着时间不断地自动更新。

    至此,我们已经完成了将RTSP视频流成功转换成HLS视频,现在把D:\TMP\test\目录配置到http服务器路径中,就可以在浏览器端播放了。

    3)接下来我们用mod_proxy搭建http服务器来实现网页播放(当然这里你也可以用nginx),mod_proxy是一款小巧易用的http服务软件,后面我们还会用到它的特殊功能。下载地址:

    https://gitee.com/dyf029/module-proxy/releases/v0.2

    下载其中的 mod_proxy_0.2.zip

    在mod_proxy的conf目录中,编辑配置文件default,修改以下内容:

    # 本地 html 模块
    module_html = [
      {module = "play",  path = "d:/tmp/test" },   #注意windows目录,路径符不能用'\'
    

    这样配置后,访问  http://127.0.0.1/play/video.m3u8 就能读取到相应的 d:\tmp\test\video.m3u8 文件。

    继续编辑default配置文件,添加另一个配置:

    # 本地html模块
    module_html = [             
      {module = "play",  path = "d:/tmp/test" },   #注意windows目录,路径符不能用'\'
      {module = "test",   path = "d:/tmp/example" },   
    

    在d:\tmp\example\目录中添加播放HLS的html、js、css等文件,这些文件可从下面网站获取:

    https://gitee.com/dyf029/module-proxy/tree/master/example/hls_html

    这些css、js文件是播放HLS必要的,其中video.html有点复杂,先不用它,我们重新编写个简单入门的hello.html来进行测试:

    <!DOCTYPE html>
    <html lang="zh-CN">
        <meta charset="UTF-8">
        <title>播放hls视频</title>
        <link href="video-js.css" rel="stylesheet">
        <script src='video.js'></script>
        <script src="videojs-contrib-hls.js" type="text/javascript"></script>
    	<script src="jquery.js"></script>
    </head>
        <style>
            .video-js .vjs-tech {position: relative !important;}
        </style>
            <video id="myVideo" class="video-js vjs-default-skin vjs-big-play-centered" controls preload="auto" data-setup='{}' style='width: 100%;height: auto'>
                <source id="source" src="/play/video.m3u8" type="application/x-mpegURL"></source>
            </video>
    </body>
    <script>
    $(function(){
        var myVideo = videojs('myVideo', {
            bigPlayButon: true,  //注意这里单词'按钮'拼写少了个't',太无语,加上这个't'敏感词检查过不去
            textTrackDisplay: false,
            posterImage: false,
            errorDisplay: false,
    	myVideo.play(); //播放
    </script>

    其中 video标签中的src地址指向了HLS生成的video.m3u8,网页加载时会自动调用 myVideo.play(),此函数用来播放HLS视频。(注意上面的注释行,需要手动加上个字母't',再次无语)

    最后,双击mod_proxy中间件中的start.bat,启动http服务,浏览器访问 http://127.0.0.1/test/hello.html

    至此,我们完成了通过浏览器播放摄像头视频的操作,恭喜!

    hello world从来不能称之为项目,它只是对我们想法的一个初级版验证,作为合格的程序员很容易会想到还有以下坑需要去填:

    1)怎样把前面的过程包装成服务,可以面向web用户并发使用,并能支持同时监控多路摄像头?

    2)前面用的独立的ffmpeg.exe程序来转换RTSP视频流到HLS,怎样在Web服务中去启动并控制它?

    3)我们要搭建的服务性能怎样,并发能支持多少路视频同时播放,要占用多少CPU多少内存?

    如果你已经开始考虑上面几点建设性意见,就已经有了成为架构师的基本能力,那么下个章节我们将一步步讲述怎样把hello搭建成服务。

    展开阅读全文