前不久抽空对目前比较火的视频直播,做了下研究与探索,了解其整体实现流程,以及探讨移动端HTML5直播可行性方案。
发现目前 WEB 上主流的视频直播方案有 HLS 和 RTMP,移动 WEB 端目前以 HLS 为主(HLS存在延迟性问题,也可以借助 video.js 采用RTMP),PC端则以 RTMP 为主实时性较好,接下来将围绕这两种视频流协议来展开H5直播主题分享。
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=”./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。
程序猿的生活:web前端全栈资料粉丝福利(面试题、视频、资料笔记,进阶路线)zhuanlan.zhihu.com/p/136454207
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对比
目前直播展示形式,通常以YY直播、映客直播这种页面居多,可以看到其结构可以分成三层:
① 背景视频层
② 关注、评论模块
③ 点赞动画
而现行H5类似直播页面,实现技术难点不大,其可以通过实现方式分为:
① 底部视频背景使用video视频标签实现播放
② 关注、评论模块利用 WebScoket 来实时发送和接收新的消息通过DOM 和 CSS3 实现
③ 点赞利用 CSS3 动画
了解完直播形式之后,接下来整体了解直播流程。
相关学习资料推荐,点击下方链接免费报名,先码住不迷路~】
音视频免费学习地址:FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发
【免费分享】音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击788280672加群免费领取~
直播整体流程大致可分为:
视频采集端:可以是电脑上的音视频输入设备、或手机端的摄像头、或麦克风,目前以移动端手机视频为主。
直播流视频服务端:一台Nginx服务器,采集视频录制端传输的视频流(H264/ACC编码),由服务器端进行解析编码,推送RTMP/HLS格式视频流至视频播放端。
视频播放端:可以是电脑上的播放器(QuickTime Player、VLC),手机端的native播放器,还有就是 H5 的video标签等,目前还是以手机端的native播放器为主。
(web前端学习交流群:328058344 禁止闲聊,非喜勿进!)
对于H5视频录制,可以使用强大的 webRTC (Web Real-Time Communication)是一个支持网页浏览器进行实时语音对话或视频对话的技术,缺点是只在 PC 的 Chrome 上支持较好,移动端支持不太理想。
使用 webRTC 录制视频基本流程
① 调用 window.navigator.webkitGetUserMedia()
获取用户的PC摄像头视频数据。
② 将获取到视频流数据转换成 window.webkitRTCPeerConnection
(一种视频流数据格式)。
③ 利用 WebScoket
将视频流数据传输到服务端。
注意:
虽然Google一直在推WebRTC,目前已有不少成型的产品出现,但是大部分移动端的浏览器还不支持 webRTC(最新iOS 10.0也不支持),所以真正的视频录制还是要靠客户端(iOS,Android)来实现,效果会好一些。
WebRTC支持度
WebRTC支持度
iOS原生应用调用摄像头录制视频流程
① 音视频的采集,利用AVCaptureSession和AVCaptureDevice可以采集到原始的音视频数据流。
② 对视频进行H264编码,对音频进行AAC编码,在iOS中分别有已经封装好的编码库(x264编码、faac编码、ffmpeg编码)来实现对音视频的编码。
③ 对编码后的音、视频数据进行组装封包。
④ 建立RTMP连接并上推到服务端。
安装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 的配置内容:
② 在http中添加 hls 的配置
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常用推流命令
移动端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>
本文从视频采集上传,服务器处理视频推流,以及H5页面播放直播视频一整套流程,具体阐述了直播实现原理,实现过程中会遇到很多性能优化问题。
① H5 HLS 限制必须是H264+AAC编码。
② H5 HLS 播放卡顿问题,server 端可以做好分片策略,将 ts 文件放在 CDN 上,前端可尽量做到 DNS 缓存等。
③ H5 直播为了达到更好的实时互动,也可以采用RTMP协议,通过video.js 实现播放。
原文 https://zhuanlan.zhihu.com/p/146323842
享 | 刘博(又拍云多媒体开发工程师)
又小拍:
如何实现HTML5直播技术是直播创业团队一直想要攻克的难题。12月1日20:00,深度参与“又拍直播云”开发的工程师刘博就如何利用WebSocket+MSE实现HTML5直播在微信群里进行了分享。小拍马不停蹄将刘博的分享内容整理成了文字,并插入一些PPT便于大家了解。全文整理如下:
下面就是分享内容啦~
当前为了满足比较火热的移动Web端直播需求,一系列的HTML5直播技术迅速的发展起来。
常见的可用于HTML5的直播技术有HLS、WebSocket与WebRTC。今天我向大家介绍WebSocket与MSE相关的技术要点,并在最后通过一个实例来展示具体用法。
分享大纲
⊙WebSocket协议介绍
⊙WebSocket Client/Server API介绍
⊙MSE介绍
⊙fMP4介绍
⊙Demo展示
WebSocket
通常的Web应用都是围绕着HTTP的请求/响应模型构建的。所有的HTTP通信都通过客户端来控制,由客户端向服务器发出一个请求,服务器接收和处理完毕后再返回结果给客户端,客户端将数据展现出来。由于这种模式不能满足实时应用需求,于是出现了SSE、Comet等 "服务器推" 的长连接技术。
WebSocket是基于TCP连接之上的通信协议,可以在单个TCP连接上进行全双工的通信。WebSocket在2011年被IETF定为标准RFC 6455,并被RFC 7936补充规范,WebSocket API被W3C定为标准。
WebSocket是独立地创建在TCP上的协议,HTTP协议中的那些概念都和WebSocket没有关联,唯一关联的是使用HTTP协议的101状态码进行协议切换时,使用的TCP端口是80,可以绕过大多数防火墙的限制。
WebSocket握手
为了更方便地部署新协议,HTTP/1.1引入了Upgrade机制,使得客户端和服务端之间可以借助已有的HTTP语法升级到其它协议。这个机制在RFC7230的6.7 Upgrade一节中有详细描述。
要发起HTTP/1.1协议升级,客户端必须在请求头部中指定这两个字段 ▽
Connection: Upgrade
Upgrade: protocol-name[/protocol-version]
如果服务端同意升级,那么需要这样响应 ▽
HTTP/1.1 101 Switching Protocols
Connection: upgrade
Upgrade: protocol-name[/protocol-version]
[... data defined by new protocol ...]
可以看到,HTTP Upgrade响应的状态码是101,并且响应正文可以使用新协议定义的数据格式。
WebSocket握手就利用了这种HTTP Upgrade机制。一旦握手完成,后续数据传输直接在TCP上完成。
WebSocket JavaScript API
目前主流的浏览器提供了WebSocket的API接口,可以发送消息(文本或者二进制)给服务器,并且接收事件驱动的响应数据。
Step1. 检查浏览器是否支持WebSocket
if(window.WebSocket) {
// WebSocket代码
}
Step2. 建立连接
var ws = new WebSocket('ws://localhost:8327');
Step3. 注册回调函数以及收发数据
分别注册WebSocket对象的onopen、onclose、onerror以及onmessage回调函数。
通过ws.send()来进行发送数据,这里不仅可以发送字符串,也可以发送Blob或ArrayBuffer类型的数据。
如果接收的是二进制数据,需要将连接对象的格式设为blob或arraybuffer。
ws.binaryType = 'arraybuffer';
WebSocket Golang API
服务器端WebSocket库我推荐使用Google自己的golang.org/x/net/websocket,可以非常方便的与net/http一起使用。也可以将WebSocket的handler function通过websocket.Handler转换成http.Handler,这样就可以跟net/http库一起使用了。
然后通过websocket.Message.Receive来接收数据,通过websocket.Message.Send来发送数据。
具体代码可以看下面的Demo部分。
MSE
在介绍MSE之前,我们先看看HTML5<audio>和<video>有哪些限制。
HTML5<audio>和<video>标签的限制
不支持流
不支持DRM和加密
很难自定义控制, 以及保持跨浏览器的一致性
编解码和封装在不同浏览器支持不同
MSE是解决HTML5的流问题。
Media Source Extensions(MSE)是Chrome、Safari、Edge等主流浏览器支持的一个新的Web API。MSE是一个W3C标准,允许JavaScript动态构建<video>和<audio>的媒体流。它定义了对象,允许JavaScript传输媒体流片段到一个 HTMLMediaElement。
通过使用MSE,你可以动态地修改媒体流而不需要任何插件。这让前端JavaScript可以做更多的事情—— 在JavaScript进行转封装、处理,甚至转码。
虽然MSE不能让流直接传输到media tags上,但是MSE提供了构建跨浏览器播放器的核心技术,让浏览器通过JavaScript API来推音视频到media tags上。
Browser Support
通过caniuse来检查是否浏览器支持情况。
通过MediaSource.isTypeSupported()可以进一步地检查codec MIME类型是否支持。
fMP4
比较常用的视频封装格式有WebM和fMP4。
WebM和WebP是两个姊妹项目,都是由Google赞助的。由于WebM是基于Matroska的容器格式,天生是流式的,很适合用在流媒体领域里。
下面着重介绍一下fMP4格式。
我们都知道MP4是由一系列的Boxes组成的。普通的MP4的是嵌套结构的,客户端必须要从头加载一个MP4文件,才能够完整播放,不能从中间一段开始播放。
而fMP4由一系列的片段组成,如果服务器支持byte-range请求,那么,这些片段可以独立的进行请求到客户端进行播放,而不需要加载整个文件。
为了更加形象的说明这一点,下面我介绍几个常用的分析MP4文件的工具。
gpac,原名mp4box,是一个媒体开发框架,在其源码下有大量的媒体分析工具,可以使用testapps;
mp4box.js,是mp4box的Javascript版本;
bento4,一个专门用于MP4的分析工具;
mp4parser,在线MP4文件分析工具。
fragment mp4 VS non-fragment mp4
下面是一个fragment mp4文件通过mp4parser(http://mp4parser.com)分析后的截图 ▽
下面是一个non-fragment mp4文件通过mp4parser分析后的截图 ▽
我们可以看到non-fragment mp4的最顶层box类型非常少,而fragment mp4是由一段一段的moof+mdat组成的,它们已经包含了足够的metadata信息与数据, 可以直接seek到这个位置开始播放。也就是说fMP4是一个流式的封装格式,这样更适合在网络中进行流式传输,而不需要依赖文件头的metadata。
Apple在WWDC 2016大会上宣布会在iOS 10、tvOS、macOS的HLS中支持fMP4,可见fMP4的前景非常的好。
值得一提的是,fMP4、CMAF、ISOBMFF其实都是类似的东西。
MSE JavaScript API
从高层次上看,MSE提供了
一套 JavaScript API 来构建 media streams
一个拼接和缓存模型
识别一些 byte 流类型:
WebM
ISO Base Media File Format
MPEG-2 Transport Streams
MSE内部结构
MSE本身的设计是不依赖任务特定的编解码和容器格式的,但是不同的浏览器支持程度是不一样的。
可以通过传递一个MIME类型的字符串到静态方法:MediaSource.isTypeSupported来检查。比如 ▽
MediaSource.isTypeSupported('audio/mp3'); // false
MediaSource.isTypeSupported('video/mp4'); // true
MediaSource.isTypeSupported('video/mp4; codecs="avc1.4D4028, mp4a.40.2"'); // true
获取Codec MIME string的方法可以通过在线的mp4info(http://nickdesaulniers.github.io/mp4info),或者使用命令行mp4info test.mp4 | grep Codecs,可以得到类似如下结果 ▽
mp4info fmp4.mp4| grep Codec
Codecs String: mp4a.40.2
Codecs String: avc1.42E01E
当前,H.264 + AAC的MP4容器在所有的浏览器都支持。
普通的MP4文件是不能和MSE一起使用的, 需要将MP4进行fragment化。
检查一个MP4是否已经fragment的方法 ▽
mp4dump test.mp4 | grep "\[m"
如果是non-fragment会显示如下信息 ▽
mp4dump nfmp4.mp4 | grep "\[m"
[mdat] size=8+50873
[moov] size=8+7804
[mvhd] size=12+96
[mdia] size=8+3335
[mdhd] size=12+20
[minf] size=8+3250
[mdia] size=8+3975
[mdhd] size=12+20
[minf] size=8+3890
[mp4a] size=8+82
[meta] size=12+78
如果已经fragment,会显示如下的类似信息 ▽
mp4dump fmp4.mp4 | grep "\[m" | head -n 30
[moov] size=8+1871
[mvhd] size=12+96
[mdia] size=8+312
[mdhd] size=12+20
[minf] size=8+219
[mp4a] size=8+67
[mdia] size=8+371
[mdhd] size=12+20
[minf] size=8+278
[mdia] size=8+248
[mdhd] size=12+20
[minf] size=8+156
[mdia] size=8+248
[mdhd] size=12+20
[minf] size=8+156
[mvex] size=8+144
[mehd] size=12+4
[moof] size=8+600
[mfhd] size=12+4
[mdat] size=8+138679
[moof] size=8+536
[mfhd] size=12+4
[mdat] size=8+24490
[moof] size=8+592
[mfhd] size=12+4
[mdat] size=8+14444
[moof] size=8+312
[mfhd] size=12+4
[mdat] size=8+1840
[moof] size=8+600
把一个non-fragment MP4转换成fragment MP4。
可以使用FFmpeg的 -movflags来转换。
对于原始文件为非MP4文件 ▽
ffmpeg -i trailer_1080p.mov -c:v copy -c:a copy -movflags frag_keyframe+empty_moov bunny_fragmented.mp4
对于原始文件已经是MP4文件 ▽
ffmpeg -i non_fragmented.mp4 -movflags frag_keyframe+empty_moov fragmented.mp4
或者使用mp4fragment ▽
mp4fragment input.mp4 output.mp4
DEMO TIME
刘博在分享的最后阶段,展示了两个demo,分别是MSE Vod Demo、MSE Live Demo
MSE Vod Demo
展示利用MSE和WebSocket实现一个点播服务
后端读取一个fMP4文件,通过WebSocket发送给MSE,进行播放
MSE Live Demo
展示利用MSE和WebSocket实现一个直播服务
后端代理一条HTTP-FLV直播流,通过WebSocket发送给MSE,进行播放
前端MSE部分做了很多工作, 包括将flv实时转封装成了fMP4,这里引用了videojs-flow的实现
Q & A
Q1:对于没有公网iIP的客户如何通过RTMP协议推流?
A1:用户客户端进行RTMP推流,不需要公网IP,推到直播系统分配给你的地址就可以了。
Q2:MSE客户端做很多东西,可以转码、解码, 这个会有性能问题吗? 还有这个技术,目前有公司在大批量用吗?
A2:目前该技术在实验阶段,转封装的话,对性能要求不高,我们在各自型号的手机上测试都没有问题。目前除了微信内置浏览器对MSE支持不好,大部分浏览器对MSE支持都比较好。
Q3:没做过相关内容,能简单介绍一下HTTP-FLV么?
A3:HTTP-FLV就是将FLV流以HTTP长连接的形式分发出去,目前在各大直播平台都用的比较多。大家可以关注下又拍云微信公众账号,之前专门有一篇文章介绍HTTP-FLV。
Q4:不大了解HTTP-FLV,既然是长时间的状态性连接,为什么不用tcp/socket呢?
A5: FLV不能在<video>标签直接播放,所以需要通过MSE转封装成MP4,再吐到<video>标签进行播放。
Q5:哔哩哔哩H5播放器是基于WebSocket与MSE技术实现的嘛?
A5:B站开源的flv.js是一个非常好的项目,是基于 MSE 实现的,实时性做的也比较好,B 站自己已经在网站播放器上使用了。
Q6:VLC器播放和网页播放,哪个快啊?
A6:播放器端延时,一个重要指标是播放器的缓存区大小。VLC的默认缓存区比较大,所以,VLC通常延时会大一些。
Q7:可以介绍下秒开技术么,以及秒开的原理?
A7:秒开可以在服务器端多缓存一个GoP来实现,这样播放器请求的第一帧能保证是I帧,可以立即播放,以此达到秒开的效果.
Refs
WebSocket
rfc6455
HTTP Upgrade
WebSocket API
MDN WebSocket
videojs-flow
MSE
W3C
MDN MSE
HTML5 Codec MIME
前,视频直播(尤其是移动端的视频直播)已经火到不行了,基本上各大互联网公司都有了自己的直播产品,所以对于我们而言,了解直播的一些基本知识和主要技术点是有必要的。
可以看到,直播从 PC 到一直发展到移动端,越来越多的直播类 App 上线,同时移动直播进入了前所未有的爆发阶段,但是对于大多数移动直播来说,还是要以 Native 客户端实现为主,但是 HTML5 在移动直播端也承载着不可替代的作用,例如 HTML5 有着传播快,易发布的优势,同时最为关键的时 HTML5 同样可以播放直播视频。
完整的直播可以分为以下几块:
视频录制端:一般是电脑上的音视频输入设备或者手机端的摄像头或者麦克风,目前以移动端的手机视频为主。
视频播放端:可以是电脑上的播放器,手机端的 Native 播放器,还有就是 HTML5 的 video 标签等,目前还是已手机端的 Native 播放器为主。
视频服务器端:一般是一台 nginx 服务器,用来接受视频录制端提供的视频源,同时提供给视频播放端流服务。
流程如下:
1、HLS
HLS 全称是 HTTP Live Streaming。这是 Apple 提出的直播流协议。目前,IOS 和 高版本 Android 都支持 HLS。
那什么是 HLS 呢?
HLS 主要的两块内容是 .m3u8 文件和 .ts 播放文件。接受服务器会将接受到的视频流进行缓存,然后缓存到一定程度后,会将这些视频流进行编码格式化,同时会生成一份 .m3u8 文件和其它很多的 .ts 文件。
根据 wiki 阐述,HLS 的基本架构为:
服务器:后台服务器接受视频流,然后进行编码和片段化。
编码:视频格式编码采用 H.264。音频编码为 AAC, MP3, AC-3,EC-3。然后使用 MPEG-2 Transport Stream 作为容器格式。
分片:将 TS 文件分成若干个相等大小的 .ts 文件。并且生成一个 .m3u8 作为索引文件(确保包的顺序)
分发:由于 HLS 是基于 HTTP 的,所以,作为分发,最常用的就是 CDN 了。
客户端:使用一个 URL 去下载 m3u8 文件,然后,开始下载 ts 文件,下载完成后,使用 playback software(即时播放器) 进行播放。
2、RTMP
RTMP 全称为:Real-Time Messaging Protocol 。它是专门应对实时交流场景而开发出来的一个协议。它爹是 Macromedia,后来卖身给了 Adobe。RTMP 根据不同的业务场景,有很多变种:
纯 RTMP 使用 TCP 连接,默认端口为 1935(有可能被封)。
RTMPS: 就是 RTMP + TLS/SSL
RTMPE: RTMP + encryption。在 RTMP 原始协议上使用,Adobe 自身的加密方法
RTMPT: RTMP + HTTP。使用 HTTP 的方式来包裹 RTMP 流,这样能直接通过防火墙。
RTMFP: RMPT + UDP。该协议常常用于 P2P 的场景中,针对延时有变态的要求。
3、HLS与RTMP
关于音视频采集录制,首先明确下面几个概念:
视频编码:所谓视频编码就是指通过特定的压缩技术,将某个视频格式的文件转换成另一种视频格式文件的方式,我们使用的 iPhone 录制的视频,必须要经过编码,上传,解码,才能真正的在用户端的播放器里播放。
编解码标准:视频流传输中最为重要的编解码标准有国际电联的 H.261、H.263、H.264,其中 HLS 协议支持 H.264 格式的编码。
音频编码:同视频编码类似,将原始的音频流按照一定的标准进行编码,上传,解码,同时在播放器里播放,当然音频也有许多编码标准,例如 PCM 编码,WMA 编码,AAC 编码等等,这里我们 HLS 协议支持的音频编码方式是 AAC 编码。
1、HTML5录制视频
对于HTML5视频录制,可以使用强大的 webRTC (Web Real-Time Communication)是一个支持网页浏览器进行实时语音对话或视频对话的技术,缺点是只在 PC 的 Chrome 上支持较好,移动端支持不太理想。
使用 webRTC 录制视频基本流程是:
调用 window.navigator.webkitGetUserMedia() 获取用户的PC摄像头视频数据。
将获取到视频流数据转换成 window.webkitRTCPeerConnection (一种视频流数据格式)。
利用 webscoket 将视频流数据传输到服务端
由于许多方法都要加上浏览器前缀,所以很多移动端的浏览器还不支持 webRTC,所以真正的视频录制还是要靠客户端(iOS,Android)来实现,效果会好一些。
2、iOS录制视频
利用 iOS 上的摄像头,进行音视频的数据采集,主要分为以下几个步骤:
音视频的采集,iOS 中,利用 AVCaptureSession 和 AVCaptureDevice 可以采集到原始的音视频数据流。
对视频进行 H264 编码,对音频进行 AAC 编码,在 iOS 中分别有已经封装好的编码库来实现对音视频的编码。
对编码后的音、视频数据进行组装封包;
建立 RTMP 连接并上推到服务端。
所谓推流,就是将我们已经编码好的音视频数据发往视频流服务器中,在 iOS 代码里面一般常用的是使用 RTMP 推流,可以使用第三方库 librtmp-iOS 进行推流,librtmp 封装了一些核心的 API 供使用者调用。例如推流 API 等等,配置服务器地址,即可将转码后的视频流推往服务器。
那么如何搭建一个推流服务器呢?
简单的推流服务器搭建,由于我们上传的视频流都是基于 RTMP 协议的,所以服务器也必须要支持 RTMP 才行,大概需要以下几个步骤:
安装一台 nginx 服务器。
安装 nginx 的 RTMP 扩展,目前使用比较多的是 https://github.com/arut/nginx-rtmp-module
配置 nginx 的 conf 文件
重启 nginx,将 RTMP 的推流地址写为 rtmp://ip:1935/hls/mystream, 其中 hls_path 表示生成的 .m3u8 和 ts 文件所存放的地址,hls_fragment 表示切片时长,mysteam 表示一个实例,即将来要生成的文件名可以先自己随便设置一个。
更多配置可以参考:https://github.com/arut/nginx-rtmp-module/wiki/
下面是 nginx 的配置文件
对于视频播放,可以使用 HLS(HTTP Live Streaming)协议播放直播流,iOS和 Android 都天然支持这种协议,配置简单,直接使用 video 标签即可。
下面是简单的代码使用 video 播放直播视频:
本文转载于互联网,如侵犯你的权益,请及时告知。
参考地址:http://geek.csdn.net/news/detail/95188、https://aotu.io/notes/2016/10/09/HTML5-SopCast/
*请认真填写需求信息,我们会在24小时内与您取得联系。