您当前的位置:首页 > 计算机 > 编程开发 > Html+Div+Css(前端)

H5 直播起航

时间:12-14来源:作者:点击数:

前不久抽空对目前比较火的视频直播,做了下研究与探索,了解其整体实现流程,以及探讨移动端 HTML5 直播可行性方案。

发现目前 WEB 上主流的视频直播方案有 HLS 和 RTMP,移动 WEB 端目前以 HLS 为主(HLS 存在延迟性问题,也可以借助 video.js 采用 RTMP),PC 端则以 RTMP 为主实时性较好,接下来将围绕这两种视频流协议来展开 H5 直播主题分享。

一、视频流协议 HLS 与 RTMP

1. HTTP Live Streaming

HTTP Live Streaming(简称 HLS)是一个基于 HTTP 的视频流协议,由 Apple 公司实现,Mac OS 上的 QuickTime、Safari 以及 iOS 上的 Safari 都能很好的支持 HLS,高版本 Android 也增加了对 HLS 的支持。一些常见的客户端如:MPlayerX、VLC 也都支持 HLS 协议。

HLS 协议基于 HTTP,而一个提供 HLS 的服务器需要做两件事:

  • 编码:以 H.263 格式对图像进行编码,以 MP3 或者 HE-AAC 对声音进行编码,最终打包到 MPEG-2 TS(Transport Stream)容器之中;
  • 分割:把编码好的 TS 文件等长切分成后缀为 ts 的小文件,并生成一个 .m3u8 的纯文本索引文件;

浏览器使用的是 m3u8 文件。m3u8 跟音频列表格式 m3u 很像,可以简单的认为 m3u8 就是包含多个 ts 文件的播放列表。播放器按顺序逐个播放,全部放完再请求一下 m3u8 文件,获得包含最新 ts 文件的播放列表继续播,周而复始。整个直播过程就是依靠一个不断更新的 m3u8 和一堆小的 ts 文件组成,m3u8 必须动态更新,ts 可以走 CDN。一个典型的 m3u8 文件格式如下:

#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=200000
gear1/prog_index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=311111
gear2/prog_index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=484444
gear3/prog_index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=737777
gear4/prog_index.m3u8

可以看到 HLS 协议本质还是一个个的 HTTP 请求 / 响应,所以适应性很好,不会受到防火墙影响。但它也有一个致命的弱点:延迟现象非常明显。如果每个 ts 按照 5 秒来切分,一个 m3u8 放 6 个 ts 索引,那么至少就会带来 30 秒的延迟。如果减少每个 ts 的长度,减少 m3u8 中的索引数,延时确实会减少,但会带来更频繁的缓冲,对服务端的请求压力也会成倍增加。所以只能根据实际情况找到一个折中的点。

对于支持 HLS 的浏览器来说,直接这样写就能播放了:

<video src="http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"
height="300"  preload="auto" autoplay="autoplay" loop="loop" webkit-playsinline="true"></video>

注意 :HLS 在 PC 端仅支持 safari 浏览器,类似 chrome 浏览器使用 HTML5 video 标签无法播放 m3u8 格式,可直接采用网上一些比较成熟的方案,如: sewise-player 、 MediaElement 、 videojs-contrib-hls 、 jwplayer 。

2. Real Time Messaging Protocol

Real Time Messaging Protocol(简称 RTMP)是 Macromedia 开发的一套视频直播协议,现在属于 Adobe。这套方案需要搭建专门的 RTMP 流媒体服务如 Adobe Media Server,并且在浏览器中只能使用 Flash 实现播放器。它的实时性非常好,延迟很小,但无法支持移动端 WEB 播放是它的硬伤。

虽然无法在 iOS 的 H5 页面播放,但是对于 iOS 原生应用是可以自己写解码去解析的, RTMP 延迟低、实时性较好。

浏览器端, HTML5 video 标签无法播放 RTMP 协议的视频,可以通过 video.js 来实现。

<link href="http://vjs.zencdn.net/5.8.8/video-js.css" rel="stylesheet">

<video id="example_video_1" class="video-js vjs-default-skin" controls preload="auto" loop="loop" webkit-playsinline>
    <source src="rtmp://10.14.221.17:1935/rtmplive/home" type='rtmp/flv'>
</video>

<script src="http://vjs.zencdn.net/5.8.8/video.js"></script>
<script>
videojs.options.flash.swf = 'video.swf';
videojs('example_video_1').ready(function() {
  this.play();
});
</script>

3. 视频流协议 HLS 与 RTMP 对比

  协议 原理 延时 优点 使用场景
HLS 短链接 Http 集合一段时间数据生成 ts 切片文件更新 m3u8 文件 10s - 30s 跨平台 移动端为主
RTMP 长链接 Tcp 每个时刻的数据收到后立即发送 2s 延时低、实时性好 PC+直播+实时性要求高+互动性强

二、直播形式

直播形式

目前直播展示形式,通常以 YY 直播、映客直播这种页面居多,可以看到其结构可以分成三层:① 背景视频层 ② 关注、评论模块 ③ 点赞动画

而现行 H5 类似直播页面,实现技术难点不大,其可以通过实现方式分为:① 底部视频背景使用 video 视频标签实现播放 ② 关注、评论模块利用 WebScoket 来实时发送和接收新的消息通过 DOM 和 CSS3 实现 ③ 点赞利用 CSS3 动画

了解完直播形式之后,接下来整体了解直播流程。

三、直播整体流程

直播整体流程大致可分为:

  • 视频采集端:可以是电脑上的音视频输入设备、或手机端的摄像头、或麦克风,目前以移动端手机视频为主。
  • 直播流视频服务端:一台 Nginx 服务器,采集视频录制端传输的视频流(H264/ACC 编码),由服务器端进行解析编码,推送 RTMP/HLS 格式视频流至视频播放端。
  • 视频播放端:可以是电脑上的播放器(QuickTime Player、VLC),手机端的 native 播放器,还有就是 H5 的 video 标签等,目前还是以手机端的 native 播放器为主。
直播整体流程

四、H5 录制视频

对于 H5 视频录制,可以使用强大的 webRTC (Web Real-Time Communication)是一个支持网页浏览器进行实时语音对话或视频对话的技术,缺点是只在 PC 的 Chrome 上支持较好,移动端支持不太理想。

1. 使用 webRTC 录制视频基本流程

① 调用 window.navigator.webkitGetUserMedia() 获取用户的 PC 摄像头视频数据。 ② 将获取到视频流数据转换成 window.webkitRTCPeerConnection (一种视频流数据格式)。 ③ 利用 WebScoket 将视频流数据传输到服务端。

注意 :虽然 Google 一直在推 WebRTC,目前已有不少成型的产品出现,但是大部分移动端的浏览器还不支持 webRTC(最新 iOS 10.0 也不支持),所以真正的视频录制还是要靠客户端(iOS,Android)来实现,效果会好一些。

WebRTC 支持度

2. iOS 原生应用调用摄像头录制视频流程

① 音视频的采集,利用 AVCaptureSession 和 AVCaptureDevice 可以采集到原始的音视频数据流。 ② 对视频进行 H264 编码,对音频进行 AAC 编码,在 iOS 中分别有已经封装好的编码库( x264 编码 、 faac 编码 、 ffmpeg 编码 )来实现对音视频的编码。 ③ 对编码后的音、视频数据进行组装封包。 ④ 建立 RTMP 连接并上推到服务端。

视频流程

五、搭建 Nginx+Rtmp 直播流服务

1. 安装 nginx、nginx-rtmp-module

① 先 clone nginx 项目到本地:

brew tap homebrew/nginx

② 执行安装 nginx-rtmp-module

brew install nginx-full --with-rtmp-module

2. nginx.conf 配置文件,配置 RTMP、HLS

查找到 nginx.conf 配置文件(路径 /usr/local/etc/nginx/nginx.conf ​),配置 RTMP、HLS。

① 在 http 节点之前添加 rtmp 的配置内容:

rtmp {
  server {
     #监听的端口
      listen 1935;
      # RTMP 直播流配置
      application rtmplive {
          live on;
          #为 rtmp 引擎设置最大连接数。默认为 off
          max_connections 1024;
       }
      # HLS 直播流配置
      application hls{
          live on;
          hls on;
          hls_path /usr/local/var/www/hls;
          hls_fragment 1s;
      }
   }
}

② 在 http 中添加 hls 的配置

    location /hls {  
        # Serve HLS fragments  
        types {  
            application/vnd.apple.mpegurl m3u8;  
            video/mp2t ts;  
        }  
        root /usr/local/var/www;  
        #add_header Cache-Controll no-cache;
        expires -1;
    }

3. 重启 nginx 服务

重启 nginx 服务,浏览器中输入 http://localhost:8080 ,是否出现欢迎界面确定 nginx 重启成功。

    nginx -s reload

六、直播流转换格式、编码推流

当服务器端接收到采集视频录制端传输过来的视频流时,需要对其进行解析编码,推送 RTMP/HLS 格式视频流至视频播放端。通常使用的常见编码库方案,如 x264 编码 、 faac 编码 、 ffmpeg 编码 等。

鉴于 FFmpeg 工具集合了多种音频、视频格式编码,我们可以优先选用 FFmpeg 进行转换格式、编码推流。

1.安装 FFmpeg 工具

brew install ffmpeg

2.推流 MP4 文件

视频文件地址: /Users/gao/Desktop/video/test.mp4 ​ 推流拉流地址: rtmp://localhost:1935/rtmplive/home ​, rtmp://localhost:1935/rtmplive/home ​

//RTMP 协议流
ffmpeg -re -i /Users/gao/Desktop/video/test.mp4 -vcodec libx264 -acodec aac -f flv rtmp://10.14.221.17:1935/rtmplive/home

//HLS 协议流
ffmpeg -re -i /Users/gao/Desktop/video/test.mp4 -vcodec libx264 -vprofile baseline -acodec aac -ar 44100 -strict -2 -ac 1 -f flv  -q 10 rtmp://10.14.221.17:1935/hls/test

注意 : 当我们进行推流之后,可以安装 VLC 、ffplay(支持 rtmp 协议的视频播放器)本地拉流进行演示

3.FFmpeg 推流命令

① 视频文件进行直播

ffmpeg -re -i /Users/gao/Desktop/video/test.mp4 -vcodec libx264 -vprofile baseline -acodec aac -ar 44100 -strict -2 -ac 1 -f flv  -q 10 rtmp://192.168.1.101:1935/hls/test
ffmpeg -re -i /Users/gao/Desktop/video/test.mp4 -vcodec libx264 -vprofile baseline -acodec aac -ar 44100 -strict -2 -ac 1 -f flv  -q 10 rtmp://10.14.221.17:1935/hls/test

② 推流摄像头+桌面+麦克风录制进行直播

ffmpeg -f avfoundation -framerate 30 -i "1:0" \-f avfoundation -framerate 30 -video_size 640x480 -i "0" \-c:v libx264 -preset ultrafast \-filter_complex 'overlay=main_w-overlay_w-10:main_h-overlay_h-10' -acodec libmp3lame -ar 44100 -ac 1  -f flv rtmp://192.168.1.101:1935/hls/test

更多命令,请参考: FFmpeg 处理 RTMP 流媒体的命令大全 FFmpeg 常用推流命令

七、H5 直播视频播放

移动端 iOS 和 Android 都天然支持 HLS 协议,做好视频采集端、视频流推流服务之后,便可以直接在 H5 页面配置 video 标签播放直播视频。

<video controls preload="auto"  autoplay="autoplay" loop="loop" webkit-playsinline>    
    <source src="http://10.14.221.8/hls/test.m3u8" type="application/vnd.apple.mpegurl" />  
    <p class="warning">Your browser does not support HTML5 video.</p>  
</video>

ps :① video 标签添加 webkit-playsinline 属性(iOS 支持)是保证视频在网页中内嵌播放。 ② 针对微信浏览器,video 标签层级最高的问题,需要申请添加白名单(见微信开发文档)。

八、总结

本文从视频采集上传,服务器处理视频推流,以及 H5 页面播放直播视频一整套流程,具体阐述了直播实现原理,实现过程中会遇到很多性能优化问题。

  1. H5 HLS 限制必须是 H264+AAC 编码。
  2. H5 HLS 播放卡顿问题,server 端可以做好分片策略,将 ts 文件放在 CDN 上,前端可尽量做到 DNS 缓存等。
  3. H5 直播为了达到更好的实时互动,也可以采用 RTMP 协议,通过 video.js 实现播放。
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐