H5 直播起航
前不久抽空对目前比较火的视频直播,做了下研究与探索,了解其整体实现流程,以及探讨移动端 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" width="400" 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" width="640" height="264" 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)来实现,效果会好一些。
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 标签层级最高的问题,需要申请添加白名单,请参照 http://bbs.mb.qq.com/thread-1242581-1-1.html?ptlang=2052。
八、总结
本文从视频采集上传,服务器处理视频推流,以及 H5 页面播放直播视频一整套流程,具体阐述了直播实现原理,实现过程中会遇到很多性能优化问题。
- H5 HLS 限制必须是 H264+AAC 编码。
- H5 HLS 播放卡顿问题,server 端可以做好分片策略,将 ts 文件放在 CDN 上,前端可尽量做到 DNS 缓存等。
- H5 直播为了达到更好的实时互动,也可以采用 RTMP 协议,通过
video.js
实现播放。
参考资料
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论