手牵手之流媒体视频协议前端解决方案详参

1. 前言

因本人厚积薄发,忽然对流媒体来了兴致😄,机缘巧合须要整理方案,因而乎整理了关于流媒体协议,前端基本解决方案的一些见解。javascript

2. 流媒体背景

流媒体就是指采用流式传输技术在网络上连续实时播放的媒体格式,如音频、视频或多媒体文件。流媒体技术也称流式媒体技术。若有疑惑能够先了解下音视频技术的一些基础概念css

3. 流媒体协议

流媒体协议是服务器与客户端之间通讯遵循的规定。当前网络上主要的流媒体协议如图表所示。html

名称 推出机构 传输层协议 客户端 使用领域 优缺点
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),拉流、保密性不强。

延迟、性能排序:前端

在支持浏览器的协议里,延迟排序(由高到低)是:java

HLS > WebSocket-FLV >RTMP = HTTP-FLVreact

而性能排序(由高到低)刚好相反:nginx

RTMP > HTTP-FLV = WebSocket-FLV > HLSgit

也就是说延迟小的性能很差。github

对比分析:web

  • 在浏览器里作直播,使用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编写,使用BabelECMAScript5中编译。

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依赖的浏览器特性兼容列表

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
复制代码

案例:

入门demo

搭建音视频服务:

gwuhaolin 用go语言实现的livego,由于它能够运行在任何操做系统上,对Golang感兴趣?请看Golang 中文学习资料汇总

  1. 下载livego,注意选对你的操做系统和位数。
  2. 解压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。

    6b12348fbc7d13903c39a8b2f141b6bc.png

  • 也可使用ffmpeg来推流,推流命令

    ffmpeg -f avfoundation -i "0" -vcodec h264 -acodec aac -f flv rtmp://localhost/live/test
    复制代码

参考:

flv.js延迟优化:

优化前先要介绍下直播运行流程:

  1. 主播端在采集到一段时间的音视频原数据后,由于音视频原数据庞大须要先压缩数据:

    • 经过H264视频编码压缩数据数据
    • 经过PCM音频编码压缩音频AAC数据
  2. 压缩完后再经过FLV容器格式封装压缩后的数据,封装成一个FLV TAG。

  3. 再把FLV TAG经过RTMP协议推流到音视频服务器,音视频服务器再从RTMP协议里解析出FLV TAG。

  4. 音视频服务器再经过HTTP协议经过和浏览器创建的长连接流式把FLV TAG传给浏览器。

  5. 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原理

参考: H5播放器源码解读 (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
复制代码

案例:

入门demo

Video.js 踩坑简单入门:

采坑 采坑2

参考:

video.js文档

5. HTML5视频播放器

如下几款HTML5视频播放器,可配置插件,皮肤,自带UI,支持弹幕,支持FLV,HLS按需引入,集成配置功能。可参考使用。更多功能可参考文档。

xgplayer

xgplayer是一个网络视频播放器库。它基于一切都是组件化的原则设计了一个独立的,可拆卸的UI组件。更重要的是,它不只在UI层中具备灵活性,并且在功能上也大胆:它消除了视频加载,缓冲和视频依赖的格式支持。特别是在mp4上它能够分阶段加载,由于它不支持流mp4。这意味着无缝切换,清晰度,负载控制和视频节省。它还集成了FLV,HLS和dash的按需和实时支持。

DPlayer

DPlayer是一个可爱的HTML5 danmaku视频播放器,能够帮助人们轻松地构建视频和danmaku。

6. 流媒体测试

6.1 流媒体测试工具

要播放视频直播流,或者测试一个直播视频地址是否可使用。这里推荐 VLC 媒体播放器。功能强大且跨平台。支持 Windows、Mac OS、Linux、Android、iOS。

官网地址:连接

使用:

6.1 流媒体直播测试源

于2019年6月21日经测试可用。

HLS直播源地址:

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. 参考

8. 小结

声明:部份内容从网络获取,若有侵权行为,请与做者联系,做者将于2日内删除。

Peace: 👋 祝大家明天也是元气慢慢的一天哦~~ 😄

相关文章
相关标签/搜索