使用flv.js做直播

为什么要在这个时候探索flv.js做直播呢?原因在于各大浏览器厂商已经默认禁用Flash,之前常见的Flash直播方案需要用户同意使用Flash后才可以正常使用直播功能,这样的用户体验很致命。

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

常见直播协议

  • RTMP: 底层基于TCP,在浏览器端依赖Flash。
  • HTTP-FLV: 基于HTTP流式IO传输FLV,依赖浏览器支持播放FLV。
  • WebSocket-FLV: 基于WebSocket传输FLV,依赖浏览器支持播放FLV。WebSocket建立在HTTP之上,建立WebSocket连接前还要先建立HTTP连接。
  • HLS: Http Live Streaming,苹果提出基于HTTP的流媒体传输协议。HTML5可以直接打开播放。
  • 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成为可能。

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再解码转换后再喂给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移动端
  4. 优先使用 HTTP-FLV,因为它延迟小,支持HTTP-FLV的设备性能运行 flv.js 足够了。
  5. 不支持 flv.js 就使用 HLS,但是 HLS延迟非常大。
  6. 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:
  • 也可以使用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, } 这里是优化后的完整代码

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏程序你好

微服务架构与传统SOA几个主要区别

882
来自专栏SDNLAB

基于ONOS的SDN-IP架构概述篇

编者按:SDN-IP是ONOS上的一个应用程序,允许软件定义网络使用标准的边界网关协议(BGP)连接到外部网络。从BGP角度看,SDN网络表现为单一的自治系统(...

3155
来自专栏数据和云

数据库选型:多核还是多线程?

数据库选型,是用多核主机还是多线程主机?我是否可以用比较便宜的单核超线程(Hyper-Threading,HT)的机器,来替代双核非HT的机器? 回答这个问题,...

3177
来自专栏SDNLAB

SDN私享汇(十三):DCFabirc控制器实现高级OpenStack网络功能

DCFabirc的主要特性和基于DCFabric的OpenStack网络的高性能优势。DCFabric的最新版本“秦”在峰会上正式发布,新版本主要在多线程优化、...

2372
来自专栏码匠的流水账

聊聊jdbc的batch操作

statement的batch操作,可以批量进行insert或update操作,提升操作性能,特别是在大数据量的insert或update的时候。

592
来自专栏QQ会员技术团队的专栏

告知你不为人知的 UDP:疑难杂症和使用

本文承接《告知你不为人知的UDP:连接性和负载均衡》文章的下文,本文主要从UDP疑难杂症、UDP协议与TCP协议高效性的对比以及UDPd的使用场合这三个方面描述...

3.9K4
来自专栏散尽浮华

OpenStack构架知识梳理

OpenStack既是一个社区,也是一个项目和一个开源软件,提供开放源码软件,建立公共和私有云,它提供了一个部署云的操作平台或工具集,其宗旨在于:帮助组织运行为...

2269

新手指南OpenStack:Nova的基础知识

[第二部分基础知识] OpenStack 新手指南 #Nova? 它是OpenStack提供云计算服务的IaaS的主要架构控制器。在美国国家航空航天局(NA...

2078
来自专栏Cloud Native - 产品级敏捷

微服务架构 (五): 获取微服务数据, 生成报表

2016.8.17, 深圳, Ken Fang 架构师在设计从多个微服务取数据, 而生成报表的架构设计方案时, 往往面临著需在边界上下文 (Bounded Co...

18710
来自专栏IT技术精选文摘

微服务架构—优雅停机方案

793

扫码关注云+社区