浏览器上音视频的播放和传输

概述

音视频成为传输信息的重要媒介,而浏览器作为各平台最为泛用的软件,本文对音视频的在浏览器上的播放和传输进行简单说明。

PC 上因为客户端播放音视频过于沉重,需要单独下载播放器,而B/S 结构更加灵活,轻巧,便于新功能的集成,只需浏览器即可, 并且依托Web 具备跨平台的属性,并且方便接入其它的功能接口,且无需更新客户端。

音视频在浏览器中的播放

首先需要对多媒体有一些基本的概念,将目的作为理解的关键:

  1. 容器格式
    包括MP4,FLV,MKV等,其作用是将编码后的多媒体 “包装” 成一个文件,目的是方便播放。比如将不同的字幕和配音封装到一个MKV容器中,那么不同观众在观看时可以选择自己想要的字幕和配音种类,获得更好的体验。
  2. 编码格式
    包括H.264, VP8,AAC等, 其作用是将原始的多媒体数据按照一定的算法进行编码,目的是压缩数据。比如一个影片中连续的两帧,都是满月当空,后一帧只是多了一个狼人,那么后一帧的信息只需要增加狼人部分的RGB点阵信息(并非实际算法)
  3. 传输协议
    包括RTSP,RTMP,HLS等 ,是客户端和服务端传输媒体流的网络应用协议, 目的是传输。比如直播的过程主播通过采集媒体信息,通过推流传输到直播平台,直播平台处理流,观众进入直播间向服务器拉流,推拉流过程中都依赖传输协议。

在浏览器中有以下三种方法来播放音视频

ActiveX控件

来自微软的Basic,需要单独安装控件,浏览器只是提供窗口的功能;不过现在Chrome 和FireFox 都已经不再支持,只有IE 还提供支持。这种方案应用当前已经比较少了,在监控安防领域还有着部分的应用,因为使用的多为rtsp 协议的原因,这一协议在浏览器上基本没有合适的解决方案,要么使用单独的客户端如:VLC 播放器,要么采用IE+ActiveX 控件的形式来完成播放。

Flash播放器

来自Adobe 的flash,曾经使用最多最广泛,现在提及更多的是来自安全漏洞的源头,恨不得赶紧扫进历史的垃圾堆。Chrome 在Chrome 76 开始已经默认禁止,并且宣布2020 年12 月之后已经不再支持Flash 播放器。连Adobe 本身也宣布在2021 年起停止支持Flash。浏览器播放RTMP 流需要依赖Flash。

标签<video>

Chrome 的媒体播放与架构中的Media 模块密切相关,支持的格式avc/aac,avc也就是h264, google 自家的vp8,vp9, 具体情况可以看具体说明 Chromium Project。但是标准的HTML 中的<video>标签只支持MP4,而且还是fMP4(Fragment MP4),总之<video> 对格式支持非常有限。而且<video>标签的src还不支持切换片段,而媒体流传输通常都会进行分片。如何解决这个问题?

解决的核心就是MSE(Media Source Extensions), 它的功能可以抽象成Media Source的两个方向:

  1. 入口: 是Video 和Audio 的两个Buffer,传过来的媒体文件解析分离(demux)出视频流和音频流,然后放入两个Buffer中。
  2. 出口: Media Source 将音视频的两个Buffer重新封装(remux)fMP4格式的文件,通过Blob对象和URL,传出到<video>进行播放

核心的两点:

  • Media Source Extensions
  • Source Buffer

这也是当前主流的播放方式,非常知名的开源项目flv.js来自谦谦大佬就是通过JS软解flv,得到音视频流喂给MSE 的两个Buffer,最后生成fMP4文件交给<video>播放。

还有HLS(后文会有介绍)的在浏览器中的播放部分,只不过格式换成了ts的容器格式,而且增加m3u8格式作为一段媒体流的基本信息和索引列表。

小结

  1. ActiveX几乎已经历史遗留产物了,也只有IE这样的兼容支持才能保持存在。
  2. Flash即将在2020年12月不再支持,是Adobe公司本身宣布,浏览器将来也将停止支持;非常奇葩的是在中国,某司宣布会继续提供Flash支持。
  3. 浏览器上的音视频播放以后会全部通过 <video> 标签本身来实现。

音视频在浏览器中的传输

http

HTTP传输通用性最强,不受到端口和防火墙的限制,最为典型的就是HLS(HTTP Live Streaming) 就是基于HTTP来实现的,相当于将需要传输的媒体文件,切分成带编号的媒体文件,然后通过HTTP协议来获取媒体文件,并且提供了一个媒体文件信息的列表,只需要按照列表顺序逐个拉取播放。

websocket

相较http而言,当前使用得比较少,但是也有ws-flv等方案,基本原理就是传输协议的变化,变成了对浏览器友好的websocket,对前端而言只是数据的获取从XHR 传输换成了websocket 而已。

webrtc

Chrome推出的新协议,在浏览器中有着原生的支持,主要用于P2P连接,主要的API

  1. getUserMedia: 从源(如网络摄像头)中获取音频和视频(注:在非HTTPS环境中会被禁止)
  2. RTCPeerConnection: 音视频流的连接
  3. RTCDataChannel: 音视频流的数据通道
  4. MediaRecorder: 保存媒体流接口

它是直接在传输层采用了RTP/RTCP。RTP 本身就定义了要传输串流媒体的参数标准(封包标准),或者说本质上就是一种流容器,所以不需要做太多处理即可播放,从这点而言更像是应用层。另外它虽然是传输层协议,但是又能基于TCP,UDP实现不同的传输。RTCP 则是为RTP 提供统计功能,描述传输状态。

另外P2P音视频的传输不能没有连接目标凭空传输,而P2P的坑点就在于如何在重重NAT+防火墙下建立双方的连接 ,webRTC在建立P2P连接的过程中会需要借助一个Signal Server(信令服务器搭建简单,并且有不少免费公开信令服务器可供选择),专门用于双方的交换信息,建立连接。

小结

  1. HTTP无需多言
  2. websocket 与传统意义上的socket编程原理相似,借助HTTP来完成初次握手,在Header中会有upgrade的标记
  3. WebRTC是一个很复杂的协议,底层是C/C++实现的,在浏览器中提供JS的接口;浏览器只能使用设计好的接口,而在客户端中由于能直接修改C/C++来适应业务需要,所以反而比浏览器应用灵活

END