1. 前言
因本人厚积薄发,突然对流媒体来了兴致😄,机缘巧合需要整理方案,于是乎整理了关于流媒体协议,前端基本解决方案的一些看法。
2. 流媒体背景
流媒体就是指采用流式传输技术在网络上连续实时播放的媒体格式,如音频、视频或多媒体文件。流媒体技术也称流式媒体技术。如有疑惑可以先了解下音视频技术的一些基础概念。
3. 流媒体协议
流媒体协议是服务器与客户端之间通信遵循的规定。当前网络上主要的流媒体协议如图表所示。
名称 | 推出机构 | 传输层协议 | 客户端 | 使用领域 | 优缺点 |
---|---|---|---|---|---|
RTSP+RTP | IETF | TCP+UDP | VLC,WMP | IPTV | 支持组播,效率较高,存在丢包问题,浏览器不支持。 |
RTMP | Adobe Inc | TCP | Flash | 互联网直播 | Adobe支持度高,适合长时间播放,延迟低(1s),有累积延迟。 |
RTMFP | Adobe Inc | UDP | Flash | 互联网直播 | 带宽消耗低,数据传输速率高,但需安装Flash Player 10。 |
HLS | Apple | TCP | Video | 互联网点播 | Apple支持度高,兼容性好,但延时高(20S),缓存,存储有难度。 |
HTTP-FLV | Adobe Inc | TCP | Video | 互联网直播/点播 | 兼容性好,延迟低(1s),拉流、保密性不强。 |
延迟、性能排序:
在支持浏览器的协议里,延迟排序(由高到低)是:
HLS > WebSocket-FLV >RTMP = HTTP-FLV
而性能排序(由高到低)恰好相反:
RTMP > HTTP-FLV = WebSocket-FLV > HLS
也就是说延迟小的性能不好。
对比分析:
- 在浏览器里做直播,使用HTTP-FLV协议是不错的,性能优于RTMP+Flash,延迟可以做到和RTMP+Flash一样甚至更好。
- HLS 延迟大,适合视频点播。
- RTMP强在浏览器支持好,加载Flash插件后就能直接播放。
4. 基于流媒体视频前端解决方案
4.1 hls.js
4.1.1 hls.js简介
hls.js是一个实现HTTP Live Streaming客户端的JavaScript库。它依靠HTML5视频和MediaSource扩展进行播放。
它的工作原理是将MPEG-2传输流和AAC / MP3流转换为ISO BMFF(MP4)片段。如果在浏览器中可用,则可以使用Web Worker
异步执行此传输。hls.js也支持HLS+fmp4
,正如在WWDC2016
期间宣布的那样hls.js不需要任何播放器,它直接在标准的HTML <video>
元素之上工作。hls.js 使用ECMAScript6
编写,使用Babel
在ECMAScript5
中编译。
4.1.2 hls.js的优缺点及兼容性
优势:
- 体积比较小,很纯净。
- 原生支持Video标签。
- HTMLVideoElement控件和事件可以无缝使用。
- UI可以根据自己的业务自扩展,自己封装功能和UI。
限制:
- 没有封装好的UI,功能上也需要自己去实现。
- 有一定延迟。
兼容性:
hls.js与支持MediaSource扩展(MSE)API的浏览器兼容,带有'video / MP4'mimetypes输入。
- Chrome for Android 34+
- Chrome for Desktop 34+
- 适用于Android 41+的Firefox
- Firefox for Desktop 42+
- IE11 +适用于Windows 8.1+
- 适用于Windows 10+的Edge
- Opera for Desktop
- Vivaldi for Desktop
- Safari for Mac 8+(测试版)
- 最新兼容详情
请注意: iOS Safari“Mobile”不支持MediaSource API。然而,Safari浏览器通过普通视频“标记”源URL支持内置HLS。当平台既没有MediaSource也没有本机HLS支持时,您将无法播放HLS。
4.1.3 hls.js原理
事件流:
由于内部通信都是基于 EventEmitter
来实现,通过事件流,你可以了解到代码运行的整体流程。
hls整体流程如下:
hls实际会先通过 ajax(loader 是可以完成自定义的) 请求 m3u8文件,然后会读取到文件的分片列表,以及视频的编码格式,时长等。随后会按照顺序(非 seek )去对分片进行请求,这些也是通过 ajax 请求二进制的文件,然后借助 Media Source Extensions
将 buffer 内容进行合流,然后组成一个可播的媒体资源文件。
由于内部通过自定事件进行数据传递和流程控制,参考下面的图:
4.1.4 hls.js使用
安装:
npm install hls.js --save
npm install @types/hls.js -dev
或者
https://cdnjs.cloudflare.com/ajax/libs/hls.js/0.12.4/hls.min.js
案例:
参考:
事件基本使用:
const hls = new Hls();
hls.on(Hls.Events.ERROR, (data) => {
// do something~~
});
注意:
声明hls实例 const hls = new Hls()
,一定要在组件销毁前,使用 hls.destroy()
注销hls实例,否则会造成内存泄漏(都是坑出来的o(╥﹏╥)o)
4.2 flv.js
4.2.1 flv.js简介
flv.js是来自Bilibli的开源项目。它解析FLV文件喂给原生HTML5 Video标签播放音视频数据,使浏览器在不借助Flash的情况下播放FLV成为可能。
4.2.2 flv.js的优缺点及兼容
优势:
- 由于浏览器对原生Video标签采用了硬件加速,性能很好,支持高清。
- 同时支持录播和直播。
- 去掉对Flash的依赖。
- FLV over WebSocket直播流播放。
- HTTP FLV低延迟直播流播放。
- 支持ts编译。
限制:
- FLV里所包含的视频编码必须是H.264,音频编码必须是AAC或MP3, IE11和Edge浏览器不支持MP3音频编码,所以FLV里采用的编码最好是H.264+AAC,这个让音视频服务兼容不是问题。
- 对于录播,依赖 原生HTML5 Video标签 和 Media Source Extensions API
- 对于直播,依赖录播所需要的播放技术,同时依赖
HTTP FLV
或者WebSocket
中的一种协议来传输FLV。其中HTTP FLV
需通过流式IO去拉取数据,支持流式IO的有fetch或者stream - flv.min.js 文件大小 164Kb,gzip后 35.5Kb,flash播放器gzip后差不多也是这么大。
- 由于依赖
Media Source Extensions
,目前所有iOS和Android4.4.4以下里的浏览器都不支持,也就是说目前对于移动端flv.js基本是不能用的。。 - HTTP FLV实时流当前不适用于所有浏览器,请参阅livestream.md
兼容性:
- 由于IO限制,flv.js可以支持HTTP FLV直播流Chrome 43+,FireFox 42+,Edge 15.15048+和Safari 10.1+现在。
- HTTP FLV直播,必须Access-Control-Allow-Origin在流服务器上正确配置标头。有关详细信息,请参阅cors.md。
- flv.js依赖的浏览器特性兼容列表
- HTML5 Video
- Media Source Extensions
- WebSocket
- HTTP FLV: fetch 或 stream
flv.js兼容方案:
由于目前flv.js兼容性还不是很好,要用在产品中必要要兼顾到不支持flv.js的浏览器。兼容方案如下:
PC端:
- 优先使用 HTTP-FLV,因为它延迟小,性能也不差1080P都很流畅。
- 不支持 flv.js 就使用 Flash播放器播 RTMP 流。Flash兼容性很好,但是性能差默认被很多浏览器禁用。
- 不想用Flash兼容也可以用HLS,但是PC端只有Safari支持HLS。
移动端:
- 优先使用 HTTP-FLV,因为它延迟小,支持HTTP-FLV的设备性能运行 flv.js 足够了。
- 不支持 flv.js 就使用 HLS,但是 HLS延迟非常大。
- HLS 也不支持就没法直播了,因为移动端都不支持Flash。
4.2.3 flv.js原理
flv.js只做了一件事,在获取到FLV格式的音视频数据后通过原生的JS去解码FLV数据,再通过Media Source Extensions API 喂给原生HTML5 Video标签。(HTML5 原生仅支持播放 mp4/webm 格式,不支持 FLV)
flv.js 为什么要绕一圈,从服务器获取FLV再解码转换后再喂给Video标签呢?原因如下:
- 兼容目前的直播方案:目前大多数直播方案的音视频服务都是采用FLV容器格式传输音视频数据。
- FLV容器格式相比于MP4格式更加简单,解析起来更快更方便。
4.2.4 flv.js使用
安装:
npm install --save flv.js
案例:
搭建音视频服务:
gwuhaolin 用go语言实现的livego,因为它可以运行在任何操作系统上,对Golang感兴趣?请看Golang 中文学习资料汇总。
- 下载livego,注意选对你的操作系统和位数。
- 解压
livego
,服务就启动好了。它会启动RTMP(1935端口)服务用于主播推流,以及HTTP-FLV(7001端口)服务用于播放。
实现播放页:
在react体系里使用react flv.js 组件reflv 快速实现。
先安装npm i reflv
,再写代码:
import React, { PureComponent } from 'react';
import Reflv from 'reflv';
export class HttpFlv extends PureComponent {
render() {
return (
<Reflv
url={`http://localhost:7001/live/test.flv`}
type="flv"
isLive
cors
/>
)
}
}
注: reflv是个人封装flv.js,可以参考,不建议直接使用。
让以上代码在浏览器里运行。这是你还看不到直播,是因为还没有主播推流。
-
你可以使用OBS来推流,注意要配置好OBS。
-
也可以使用ffmpeg来推流,推流命令
ffmpeg -f avfoundation -i "0" -vcodec h264 -acodec aac -f flv rtmp://localhost/live/test
参考:
flv.js延迟优化:
优化前先要介绍下直播运行流程:
-
主播端在采集到一段时间的音视频原数据后,因为音视频原数据庞大需要先压缩数据:
- 通过H264视频编码压缩数据数据
- 通过PCM音频编码压缩音频AAC数据
-
压缩完后再通过FLV容器格式封装压缩后的数据,封装成一个FLV TAG。
-
再把FLV TAG通过RTMP协议推流到音视频服务器,音视频服务器再从RTMP协议里解析出FLV TAG。
-
音视频服务器再通过HTTP协议通过和浏览器建立的长链接流式把FLV TAG传给浏览器。
-
flv.js 获取FLV TAG后解析出压缩后的音视频数据喂给Video播放。
知道流程后我们就知道从哪入手优化了:
- 主播端采集时收集了一段时间的音视频原数据,它专业的叫法是GOP。缩短这个收集时间(也就是减少GOP长度)可以优化延迟,但这样做的坏处是导致视频压缩率不高,传输效率低。
- 关闭音视频服务器的
I桢
缓存可以优化延迟,坏处是用户看到直播首屏的时间变大。 - 减少音视频服务器的buffer可以优化延迟,坏处是音视频服务器处理效率降低。
- 减少浏览器端flv.js的buffer可以优化延迟,坏处是浏览器端处理效率降低。
- 浏览器端开启flv.js的Worker,多线程运行flv.js提升解析速度可以优化延迟,这样做的flv.js配置代码是:
{ enableWorker: true, enableStashBuffer: false, stashInitialSize: 128,// 减少首桢显示等待时长 }
4.3 video.js
4.3.1 video.js简介
Video.js是一款基于HTML5的网络视频播放器。它支持HTML5和Flash视频,以及YouTube和Vimeo(通过插件)。支持在桌面和移动设备上播放视频。这个项目从2010年中期开始,现已经在40多万个网站上使用。
4.3.2 video.js的优缺点
优势:
- 开源免费,可以在github很容易的获取它的最新代码。
- 兼容主流浏览器。
- 界面可以定制,纯javascript和css打造。
- 支持HLS, RTMP需引入插件支持。
- 灵活插件机制。
- 比较完善的文档。
- 项目热度,开源作者对项目的维护比较积极。
限制:
- 内置hls.js,体积偏大。
4.3.3 video.js原理
4.3.4 video.js使用
安装:
CDN
<link href="//vjs.zencdn.net/7.3.0/video-js.min.css" rel="stylesheet">
<script src="//vjs.zencdn.net/7.3.0/video.min.js"></script>
// 支持RTMP
<script src="https://cdn.jsdelivr.net/npm/videojs-flash@2/dist/videojs-flash.min.js"></script>
npm
yarn add video.js --save
// 支持RTMP
yarn add videojs-flash -- save
案例:
Video.js 踩坑简单入门:
参考:
5. HTML5视频播放器
以下几款HTML5视频播放器,可配置插件,皮肤,自带UI,支持弹幕,支持FLV,HLS按需引入,集成配置功能。可参考使用。更多功能可参考文档。
xgplayer是一个网络视频播放器库。它基于一切都是组件化的原则设计了一个独立的,可拆卸的UI组件。更重要的是,它不仅在UI层中具有灵活性,而且在功能上也大胆:它消除了视频加载,缓冲和视频依赖的格式支持。特别是在mp4上它可以分阶段加载,因为它不支持流mp4。这意味着无缝切换,清晰度,负载控制和视频节省。它还集成了FLV,HLS和dash的按需和实时支持。
DPlayer是一个可爱的HTML5 danmaku视频播放器,可以帮助人们轻松地构建视频和danmaku。
6. 流媒体测试
6.1 流媒体测试工具
要播放视频直播流,或者测试一个直播视频地址是否可以使用。这里推荐 VLC 媒体播放器。功能强大且跨平台。支持 Windows、Mac OS、Linux、Android、iOS。
官网地址:链接
使用:
6.1 流媒体直播测试源
于2019年6月21日经测试可用。
HLS直播源地址:
-
CCTV1高清:ivi.bupt.edu.cn/hls/cctv1hd…
-
CCTV3高清:ivi.bupt.edu.cn/hls/cctv3hd…
-
CCTV6高清:ivi.bupt.edu.cn/hls/cctv6hd…
RTMP直播源地址:
-
香港卫视1:rtmp://live.hkstv.hk.lxdns.com/live/hks1
-
香港卫视2:rtmp://live.hkstv.hk.lxdns.com/live/hks2
-
湖南卫视:rtmp://58.200.131.2:1935/livetv/hunantv
-
美国1:rtmp://ns8.indexforce.com/home/mystream
-
美国中文电视:rtmp://media3.sinovision.net:1935/live/livestream
-
香港财经:rtmp://202.69.69.180:443/webcast/bshdlive-pc
-
韩国GoodTV:rtmp://mobliestream.c3tv.com:554/live/goodtv.sdp
7. 参考
- 基于HLS流媒体协议视频加密的解决方案
- 流媒体加密
- FFmpeg-录制、转换和流式传输音频和视频
- HLS协议详解
- 七牛云视频直播云解决方案
- 支持HTTP-FLV方式直播的开源模块nginx-http-flv-module
8. 小结
声明:部分内容从网络获取,如有侵权行为,请与作者联系,作者将于2日内删除。
Peace: 👋 祝你们明天也是元气慢慢的一天哦~~ 😄