软硬皆施

扫盲笔记--H5视频直播

项目需要,这里做一个简单的笔记梳理

视频直播流程:采集端 ==> 服务器端 ==> 播放端

image

流程图用的一个Chrome插件,Gliffy Diagrams。

先把这些协议讲一讲

1. RTMP(Real Time Messaging Protocol)

RTMP是Adobe Systems公司为Flash播放器和服务器之间音频、视频和数据传输开发的开放协议。该协议基于TCP,是一个协议族,包括RTMP基本协议及RTMPT/RTMPS/RTMPE等多种变种。

工作原理:

在RTMP协议中的基本数据单元称为Message(消息),在传输数据的过程中,Message会被拆分成更小快的Chunk(消息块)。

传输媒体流的过程:

1.发送端将媒体数据封装成Message

2.再把Message切分成Chunk

3.基于TCP协议发送

4.接收端通过TCP收到Chunk

5.将Chunk重组成Message

6.对Message解包得到媒体数据

特点

  • 延迟低
    • RTMP协议基于TCP底层通讯协议,属于长链接,收到数据后立即发送
  • 延迟累积
    • 还是因为基于TCP,丢包少(TCP重传机制),网络差的时候服务器将包缓存,等到网络好的时候在一并发给服务器。
  • 隐私性理想

2. HLS(HTTP Live Streaming)

关键词:切片

HLS协议规定:

  • 视频的封装格式是TS。
  • 视频的编码格式为H264,音频编码格式为MP3、AAC或者AC-3。
  • 定义了用来存放流配置和路径的m3u8索引文件。

先来show一段基于HLS协议的视频播放code

1
2
3
4
5
6
7
...
<div id="player">
<video width="640" height="320" controls>
<source src="http://..url../live/livestream.m3u8" type="application/x-mpegURL">
</video>
</div>
...

如果要兼容所有浏览器,需要接第三方播放器,比如video.js

工作原理:

把整个流切分成一个个基于HTTP的小文件(ts文件),用m3u8索引表来管理这些小切片。可以看到上面👆这段code中的source,是一个.m3u8文件,所以当视频播放的时候,video标签解析这个索引文件(动态更新),然后按序去找到对应的ts文件(真正存放视频数据的文件)并连续播放。

特点:

  • 跨平台(ios、Android、pc)
    • RTMP基于flash,ios不支持
  • 基于HTTP,容易接CDN
  • 实时性差(延迟一般在10s-30s左右)
    • 由于流被切片下载,假设.m3u8索引列表里有n个ts文件,每个ts文件包含m秒视频内容,同时推流端又有新的流推上来,但拉流端才刚刚看到下载下来的切片流,所以延迟就是n*m秒。想要延迟小,理想就让n和m的值最小到1,几乎零延迟,由于HLS基于HTTP协议,所以随之而来的就是请求次数增加,server端压力大。因此要平衡取舍。

PS:苹果官方推荐的ts时长为10s,列表3个ts文件,因此会有大概30s的延迟。
https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/StreamingMediaGuide/FrequentlyAskedQuestions/FrequentlyAskedQuestions.html

3.What duration should media files be?

The main point to consider is that shorter segments result in more frequent refreshes of the index file, which might create unnecessary network overhead for the client. Longer segments will extend the inherent latency of the broadcast and initial startup time. A duration of 10 seconds of media per file seems to strike a reasonable balance for most broadcast content.

4.How many files should be listed in the index file during a continuous, ongoing session?

The normal recommendation is 3, but the optimum number may be larger…

3. WebRTC(Web Real-Time Communication)

是一个支持网页浏览器进行实时语音对话或视频对话的 API。它于 2011 年 6 月 1 日开源并在 Google、Mozilla、Opera 支持下被纳入万维网联盟的 W3C 推荐标准。

浏览器兼容性

image

可以看到,截止目前(2017.2.14),WebRTC的兼容性还是惨不忍睹,只在PC端的Chrome比较好(毕竟是谷歌2010年以6820万美元收购Global IP Solutions公司而获得的一项技术)。不过风头火热,xxxx,指日可待。

工作原理

简单的一句话就是,让浏览器提供JS的即时通信API。通过一系列的信令建立浏览器之间的信道,来传输音频视频数据。与WebSocket的区别就是,少了中间的WebSocket服务器。

其实没那么simple

先来看看用WebRTC实现一场会议直播的正常流程

其实p2p(peer to peer)就能跑起来了

  1. 推流端(如Chrome浏览器)调用相关的媒体API来获取音视频源
  2. 中转的MCU服务器(不是说不需要么?因为chrome给超过10个用户推流的时候很容易崩),对音视频做一些简单的处理。
  3. 客户端(如Chrome)连接MCU,并获取媒体流。

之前在项目里用过声网的WebRTC的SDK,所以感觉这项技术还是牛honghong的。

4. HTTP-FLV (补充)

顾名思义,就是将音视频数据流封装成FLV,再通过HTTP协议传输给客户端。

特点

  1. 延时低(与RTMP媲美)
  2. 穿透性强(基于HTTP80端口通信)
  3. 可以使用HTTPS做加密通道

上面讲得差不多了,这里就做个小总结。

采集端(推流端)

如开头的流程图中所述,一般常用的就是RTMP推流,因为延迟较小。

补充:几个主流的 web直播平台,几乎都是以HTTP-FLV为直播协议。

推荐一个推流工具:OBS

Server端

简单的说就是一台流媒体服务器,用来接收流和分发流。

e.g. 比如一台Nginx服务器,要扩展支持RTMP,用的较多是这个: https://github.com/arut/nginx-rtmp-module

播放端(拉流端)

  • FlashPlayer浏览器支持(RTMP)
  • h5的video标签(HLS)
  • 火爆的flv.js(那个B站工资5000的大神,可惜走了)(HTTP-FLV)
    • 实现了H5端对FLV格式的播放,终于解脱了臃肿的Flash。

说了这么多,大厂都有了视频直播的解决方案,直接拿来用也挺省心。

参考文章:

  1. http://www.cnblogs.com/luconsole/p/6079534.html
  2. https://www.nihaoshijie.com.cn/index.php/archives/615

这篇笔记做下来,真的是觉得视频这块领域很大呢,要想更深入还是需要花大力气学习的。肯定有很多不妥当的地方,希望多批评,文章也会持续更新…

PalmerYe wechat
世界很大,圈子很小,欢迎关注,相互进步。
Fork me on GitHub