使用flv.js作直播

为何要在这个时候探索flv.js作直播呢?缘由在于各大浏览器厂商已经默认禁用Flash,以前常见的Flash直播方案须要用户赞成使用Flash后才能够正常使用直播功能,这样的用户体验很致命。html

在介绍flv.js以前先介绍下常见的直播协议以及给出我对它们的延迟与性能所作的测试得出的数据。
若是你看的很吃力能够先了解下音视频技术的一些基础概念react

常见直播协议

  • RTMP: 底层基于TCP,在浏览器端依赖Flash。git

  • HTTP-FLV: 基于HTTP流式IO传输FLV,依赖浏览器支持播放FLV。github

  • WebSocket-FLV: 基于WebSocket传输FLV,依赖浏览器支持播放FLV。WebSocket创建在HTTP之上,创建WebSocket链接前还要先创建HTTP链接。web

  • HLS: Http Live Streaming,苹果提出基于HTTP的流媒体传输协议。HTML5能够直接打开播放。npm

  • RTP: 基于UDP,延迟1秒,浏览器不支持。浏览器

常见直播协议延迟与性能数据如下数据只作对比参考

传输协议 播放器 延迟 内存 CPU
RTMP Flash 1s 430M 11%
HTTP-FLV Video 1s 310M 4.4%
HLS Video 20s 205M 3%

在支持浏览器的协议里,延迟排序是:
RTMP = HTTP-FLV = WebSocket-FLV < HLS
而性能排序刚好相反:
RTMP > HTTP-FLV = WebSocket-FLV > HLS
也就是说延迟小的性能很差。缓存

能够看出在浏览器里作直播,使用HTTP-FLV协议是不错的,性能优于RTMP+Flash,延迟能够作到和RTMP+Flash同样甚至更好。服务器

flv.js 简介

flv.js是来自Bilibli的开源项目。它解析FLV文件喂给原生HTML5 Video标签播放音视频数据,使浏览器在不借助Flash的状况下播放FLV成为可能。websocket

flv.js 优点

  • 因为浏览器对原生Video标签采用了硬件加速,性能很好,支持高清。

  • 同时支持录播和直播

  • 去掉对Flash的依赖

flv.js 限制

  • FLV里所包含的视频编码必须是H.264,音频编码必须是AACMP3, 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基本是不能用的。

flv.js依赖的浏览器特性兼容列表

flv.js 原理

flv.js只作了一件事,在获取到FLV格式的音视频数据后经过原生的JS去解码FLV数据,再经过Media Source Extensions API 喂给原生HTML5 Video标签。(HTML5 原生仅支持播放 mp4/webm 格式,不支持 FLV)

flv.js 为何要绕一圈,从服务器获取FLV再解码转换后再喂给Video标签呢?缘由以下:

  1. 兼容目前的直播方案:目前大多数直播方案的音视频服务都是采用FLV容器格式传输音视频数据。

  2. FLV容器格式相比于MP4格式更加简单,解析起来更快更方便。

flv.js兼容方案

因为目前flv.js兼容性还不是很好,要用在产品中必要要兼顾到不支持flv.js的浏览器。兼容方案以下:

PC端

  1. 优先使用 HTTP-FLV,由于它延迟小,性能也不差1080P都很流畅。

  2. 不支持 flv.js 就使用 Flash播放器播 RTMP 流。Flash兼容性很好,可是性能差默认被不少浏览器禁用。

  3. 不想用Flash兼容也能够用HLS,可是PC端只有Safari支持HLS

移动端

  1. 优先使用 HTTP-FLV,由于它延迟小,支持HTTP-FLV的设备性能运行 flv.js 足够了。

  2. 不支持 flv.js 就使用 HLS,可是 HLS延迟很是大。

  3. HLS 也不支持就无法直播了,由于移动端都不支持Flash。

flv.js实战

说了这么多介绍与原理,接下来教你们如何用flv.js搭建一个完整的直播系统。
我已经搭建好了一个demo能够供你们体验。

搭建音视频服务

主播推流到音视频服务,音视频服务再转发给全部链接的客户端。为了让你快速搭建服务推荐我用go语言实现的livego,由于它能够运行在任何操做系统上。

  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
      />
    )
  }
}

让以上代码在浏览器里运行。这是你还看不到直播,是由于尚未主播推流。

  • 你可使用OBS来推流,注意要配置好OBS:
    <img width="961" alt="screen shot 2017-06-07 at 5 41 32 pm" src="https://user-images.githubuse...

  • 也可使用ffmpeg来推流,推流命令ffmpeg -f avfoundation -i "0" -vcodec h264 -acodec aac -f flv rtmp://localhost/live/test

flv.js延迟优化

按照上面的教程运行起来的直播延迟大概有3秒,通过优化能够到1秒。在教你怎么优化前先要介绍下直播运行流程:

  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,
}

这里是优化后的完整代码

阅读原文

相关文章
相关标签/搜索