H5直播调研

lxf2023-12-31 03:30:02

一、H5直播基础

1.典型的直播流程:

录制->编码->网络传输(推流->服务器处理->CDN分发)->解码->播放

2.MSE 意义

初识 HTML5 video 标签和MSE媒体源扩展
以往用户在浏览网页内容尤其是视频内容时,需要使用像Adobe Flash或是微软的Silverlight这样的插件,播放视音频内容即使是电脑小白也知道,需要媒体播放器的支持,前面提到的插件就是起到媒体播放器的作用。但是使用插件这样的方式是很不便捷且很不安全的,一些不法分子会在这些插件上动手脚。因此W3C的最新的HTML5标准中,定义了一系列新的元素来避免使用插件,其中就包含了标签这一大名鼎鼎的元素。

正是使用了标签,支持HTML5的浏览器得以实现无插件就原生支持播放媒体内容,但是对媒体内容的格式有所限制。说到媒体内容,就自然地需要谈到媒体的封装格式和编码格式,这里总结一下,原视频文件通过编码来压缩文件大小,再通过封装将压缩视音频、字幕组合到一个容器内,具体内容请大家自行查阅。

我们可以把标签看做拥有解封装和解码功能的浏览器自带播放器。随着视频点播、直播等视频业务的发展,视频通过流媒体传输协议(目前常用的有两种,MPEG-DASH和Apple的HLS)从服务器端分发给客户端,媒体内容进一步包含在一层传输协议中,这样就无法识别了。以HLS为例,将源文件内容分散地封装到了一个个TS文件中。

仅靠标签无法识别这样的TS文件,那么就引入了MSE拓展来帮助浏览器识别并处理TS文件,将其变回原来可识别的媒体容器格式,这样就可以识别并播放原来的文件了。那么支持HTML5的浏览器就相当于内置了一个能够解析流协议的播放器。

比如在hls.js 源码解读【1】中,介绍的hls.js
hls实际会先通过 ajax(loader 是可以完成自定义的) 请求 m3u8文件,然后会读取到文件的分片列表,以及视频的编码格式,时长等。随后会按照顺序(非 seek )去对分片进行请求,这些也是通过 ajax 请求二进制的文件,然后借助 Media Source Extensions 将 buffer 内容进行合流,然后组成一个可播的媒体资源文件。

3.video/audio支持的视频格式

video: mp4、webm、ogv
audio: mp3 wav ogg
1.一般承载视频的格式,比如flv、avi、mpg、vob、mov、mp4等。而视频是用什么方式进行编解码的,则与Codec相关。举个栗子,MP4格式根据编解码的不同,又分为nMP4、fMP4。nMP4是由嵌套的Boxes 组成,fMP4格式则是由一系列的片段组成,因此只有后者不需要加载整个文件进行播放。
值得注意的是: mp4规范第10章就是 h264, mp4和h264可以等同

2.Codec:多媒体数字信号编码解码器,能够对音视频进行压缩(CO)与解压缩( DEC ) 。CODEC技术能有效减少数字存储占用的空间,在计算机系统中,使用硬件完成CODEC可以节省CPU的资源,提高系统的运行效率。 H5直播调研

4.常用视频编解码格式:

AVI、MOV、MPEG/MPG/DAT、Real Media、QuickTime、ASF、H264/X264/AVC、H.263、MPEG-1、MPEG-2、MPEG-4、Sorensen Spark、VC-1、JPEG、RV、DivX、On2 TrueMotion VP6

5.常用音频编解码格式:

PCM、WAV、OGG、APE、AAC、MP3、Vorbis、Opus...

二.常用直播协议: RTMP、HLS、HTTP-FLV、WebSocket-FLV

1.RTMP协议

  1. 基于TCP
  2. adobe垄断,国内支持度高
  3. 浏览器端依赖Flash进行播放
  4. 2~5秒的延迟 RTMP,全称 Real Time Messaging Protocol,即实时消息传送协议。Adobe 公司为 Flash 播放器和服务器之间音视频数据传输开发的私有协议。工作在 TCP 之上的明文协议,默认使用端口 1935。协议中的基本数据单元成为消息(Message),传输的过程中消息会被拆分为更小的消息块(Chunk)单元。最后将分割后的消息块通过 TCP 协议传输,接收端再反解接收的消息块恢复成流媒体数据。

RTMP 主要有以下几个优点:RTMP 是专为流媒体开发的协议,对底层的优化比其它协议更加优秀,同时它 Adobe Flash 支持好,基本上所有的编码器(摄像头之类)都支持 RTMP 输出。现在 PC 市场巨大,PC 主要是 Windows,Windows 的浏览器基本上都支持 Flash。另外RTMP适合长时间播放,曾经有过测试,联系 100 万秒,即 10 天多连续播放没有出现问题。最后 RTMP 的延迟相对较低,一般延时在 1-3s 之间,一般的视频会议,互动式直播,完全是够用的。

当然 RTMP 并没有尽善尽美,它也有不足的地方。一方面是它是基于 TCP 传输,非公共端口,可能会被防火墙阻拦;另一方面,也是比较坑的一方面是 RTMP 为 Adobe 私有协议,很多设备无法播放,特别是在 iOS 端,需要使用第三方解码器才能播放。

2.HLS 协议

  1. Http Live Streaming,苹果提出的基于HTTP的流媒体传输协议
  2. HTML5直接支持(video),适合APP直播,PC断只有Safari、Edge支持
  3. 必须是H264+AAC编码
  4. 因为传输的是切割后的音视频片段,导致内容延时较大 HLS (HTTP Live Streaming) 是苹果公司基于 HTTP 的流媒体传输协议。 主要应用于 iOS 设备,包含(iPhone, iPad, iPod touch) 以及 Mac OSX 提供音视频直播服务和录制内容(点播)等服务。

相对于常见的流媒体协议,HLS 最大的不同在于它并不是一下请求完整的数据流。它会在服务器端将流媒体数据切割成连续的时长较短的 ts 小文件,并通过 M3U8 索引文件按序访问 ts 文件。客户端只要不停的按序播放从服务器获取到的文件,从而实现播放音视频。

相较 RTMP 而言,使用 HLS 在 HTML5 页面上实现播放非常简单:
直接:

H5直播调研 或者:

H5直播调研 HLS 的优势:

  • Apple 的全系列产品支持:由于 HLS 是苹果提出的,所以在 Apple 的全系列产品包括 iPhone、 iPad、safari 都不需要安装任何插件就可以原生支持播放 HLS, 现在 Android 也加入了对 HLS 的支持。

  • 穿透防火墙。基于 HTTP/80 传输,有效避免防火墙拦截

  • 性能高。通过 HTTP 传输, 支持网络分发,CDN 支持良好,且自带多码率自适应,Apple 在提出 HLS 时,就已经考虑了码流自适应的问题。 HLS 的劣势:

  • 实时性差,延迟高。HLS 的延迟基本在 10s+ 以上

  • 文件碎片。特性的双刃剑,ts 切片较小,会造成海量小文件,对存储和缓存都有一定的挑战

3.flv.js

  1. Bilibli开源,解析flv数据,通过MSE封装成fMP4喂给video标签
  2. 编码为H264+AAC
  3. 使用HTTP的流式IO(fetch或stream)或WebSocket协议流式的传输媒体内容
  4. 2~5秒的延迟,首帧比RTMP更快 FLV (Flash Video) 是 Adobe 公司推出的另一种视频格式,是一种在网络上传输的流媒体数据存储容器格式。 其格式相对简单轻量,不需要很大的媒体头部信息。整个 FLV 由 The FLV Header, The FLV Body 以及其它 Tag 组成。因此加载速度极快。采用 FLV 格式封装的文件后缀为 .flv。

H5直播调研
HTTP-FLV 基于HTTP流式IO传输FLV,依赖浏览器支持播放FLV。即将流媒体数据封装成 FLV 格式,然后通过 HTTP 协议传输给客户端。
HTTP-FLV 依靠 MIME 的特性,根据协议中的 Content-Type 来选择相应的程序去处理相应的内容,使得流媒体可以通过 HTTP 传输。相较于 RTMP 协议,HTTP-FLV 能够好的穿透防火墙,它是基于 HTTP/80 传输,有效避免被防火墙拦截。除此之外,它可以通过 HTTP 302 跳转灵活调度/负载均衡,支持使用 HTTPS 加密传输,也能够兼容支持 Android,iOS 的移动端。\

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

4.流媒体协议 RTMP, HTTP-FLV, HLS 简单对比

H5直播调研
在支持浏览器的协议里,延迟排序是:
RTMP = HTTP-FLV = WebSocket-FLV < HLS
而性能排序恰好相反:
RTMP > HTTP-FLV = WebSocket-FLV > HLS
也就是说延迟小的性能不好。

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

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

  • HTML5 Video
  • Media Source Extensions
  • WebSocket
  • HTTP FLV: fetch 或 stream

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,因为它可以运行在任何操作系统上,对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
      />
    )
  }
}

让以上代码在浏览器里运行。这是你还看不到直播,是因为还没有主播推流。

  • 你可以使用OBS来推流,注意要配置好OBS:

H5直播调研

  • 也可以使用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,// 减少首桢显示等待时长
}

这里是优化后的完整代码

6.总结H5直播实际使用方案测试中:

B站的flv.js在web端和安卓浏览器表现良好,但值得注意的是在ios浏览器上无法播放flv,原因:

flvjs.isSupported()在ios上是值是undefined, 也就是mseFlvPlayback 和 mseLiveFlvPlayback属性没有,
也就是flv对应的 Media Source Extensions 在ios上没有
浏览器/小程序FLVM3U8RTMP
PC端Chrome34及以上版本34及以上版本❎ ( 需flash )
Firefox49及以上版本49及以上版本❎ ( 需flash )
IE*IE11及以上版本
*Windows8.1及以上版本
*IE11及以上版本
*Windows8.1及以上版本
❎ ( 需flash )
Edge❎ ( 需flash )
Opera❎ ( 需flash )
Safari8及以上版本8及以上版本❎ ( 需flash )
移动端Android
Ios
小程序Android/Ios*video可播
*live-player可播
*video可播
*live-player无法播
*video无法播
*live-player可播
Web-AppAndroid H5/Ios H5APLCloud支持APLCloud支持APLCloud支持
值得注意的是 live-player拉流专用组件标签: 官网仅支持flv和rtmp

综上目前关于H5,在直播方面, 移动端ios上用hls, 其余都可用flv, 在不涉及直播点播方面用hls即可 浏览器用mse硬解只能做到这样, 加上wasm解码器来软解可以实现在ios也用flv, 并且因WebRTC能正在做到低延时, 高并发可用WebRTC + (flv+hls / wasm软解flv,hls)兼容方案, 做到向下兼容降级.

备注: 更新中,本调研摘录多个作者, 个人使用记录下

本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!