简介: 2020年,直播带货火爆全网。想一探淘宝直播背后的前端技术?本文将带你进入淘宝直播前端技术的世界。 对于大多数前端工程师来说,音视频技术是一个比较少涉足的领域,本文涵盖了流媒体技术中的文本、图形、图像、音频和视频多种理论知识,涉及到播放器、web媒体技术、主流框架等介绍,只需要花上一点点时间,你将进入前端多媒体的领域。
2020年,直播带货火爆全网。想一探淘宝直播背后的前端技术?本文将带你进入淘宝直播前端技术的世界。
对于大多数前端工程师来说,音视频技术是一个比较少涉足的领域,本文涵盖了流媒体技术中的文本、图形、图像、音频和视频多种理论知识,涉及到播放器、web媒体技术、主流框架等介绍,只需要花上一点点时间,你将进入前端多媒体的领域。
音视频基础
▐ 视频
✎ 基础概念
✎ 视频容器格式
容器格式相信大家经常见到:
MP4、AVI、FLV、TS/M3U8、WebM、OGV、MOV...
▐ 音频
✎ 基础概念
✎ 音频容器格式
音频格式也比较常见:WAV、AIFF、AMR、MP3、Ogg...
✎ 音频编码格式
直播技术
▐ 流媒体协议
每一个你在网络上观看的视频或音频媒体都是依靠特定的网络协议进行数据传输,基本分布在会话层(Session Layer)、表示层(Presentation Layer)、应用层(Application Layer)。
常用协议:RTMP、RTP/RTCP/RTSP、HTTP-FLV、HLS、DASH。各个协议都有自己优势与劣势。
▐ 推拉流过程
主播在设备上开启直播,采集设备将主播声音及画面采集后通过对应协议推流到「流媒体服务器」上。此时观看端(即拉流端)通过拉流协议即可从「流媒体服务器」上拉取到流数据进行播放。
播放器
本节主要讲述播放器相关技术,在本节中会简要讲述播放器在拿到相关流之后如何运作。
▐ 拉流
第一步是拉流,在播放之前率先需要拿到视频流才可能执行播放。
举个例子,flv格式的视频流数据,我们可以通过浏览器提供的:Fetch API、Stream API 进行拉流。
▐ 解封装
拿到流数据之后,紧接着需要执行解封装操作。在开始播放的之前,需要把图像、声音、字幕(可能不存在)等从拉取的流数据中分离出来,这个分离的行为和过程就是解封装(demux)。
在解封装之后获得图像、声音、字幕等基本流,而后基本流可以通过解码器进行解码。
▐ demux(解码)
从上层解封装中,我们了解到,在解封装之后,需要对分离出来的原始码流进行解码,生成音、视频播放器可播放的数据。
在解码过程中,我们会得到各式各样的数据,我们挑选几个重要的来讲:
✎ SPS 和 PPS
这俩哥们儿决定了最大视频分辨率、帧率等以及还有一系列视频播放当中的参数。PPS通常与SPS一起,保存在码流的起始位置。
SPS、PPS中保存了一组编码视频序列的全局参数,如果丢掉,解码过程很可能GG。
✎ IBP帧
- I帧,关键帧。I帧进行帧内预测,可以单独解码本帧的数据,I帧通常是每个GOP(MPEG所使用的一种视频压缩技术)的第一帧,经过适度地压缩,作为随机访问的参考点可以当成静态图像。
- B帧,向前预编码帧。它要使用一个前面的I帧或P帧和一个后面的I帧或P帧进行预测。不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。
- P帧,前向预测编码在帧(predictive-frame),通过将图像序列中前面已编码帧的时间冗余信息去充分去除压缩传输数据量的编码图像,也成为预测帧。
✎ SEI(补充增强信息)
- 视频编码器在输出视频码流的时候,可以没有SEI。举个简单例子,之前特别火的直播答题,通过SEI传递较多和答题业务相关的信息,并通过SEI承载的信息,优化题目显示和观众音视频观看的同步性。
✎ PTS和DTS
- DTS(Decoding Time Stamp):即解码时间戳,这个时间戳的意义在于告诉播放器该在什么时候解码这一帧的数据。
- PTS(Presentation Time Stamp):即显示时间戳,这个时间戳用来告诉播放器该在什么时候显示这一帧的数据。
简而言之,这俩哥们儿很可能直接决定了你音视频播放是不是同步的。
解码还会生成各式各样的产物,这里就不展开介绍了,有兴趣的同学可以在本篇最后查看。
▐ remux(复用)
有demux,自然就有remux。把基本的音频ES、视频ES、字幕ES等组合成一个完整的多媒体就是Remux(复用)。
对一个视频来说,改变封装格式,改变视频编码,需要remux和demux的配合。这里不展开叙述。
▐ 渲染
渲染,指的是将解码后的数据,在 pc 硬件上(显示器、扬声器)进行播放。负责渲染的模块我们称之为渲染器(Render),视频渲染器主流有EVR(Enhanced Video Render)以及 madVR (madshi Video Render),Web 播放器一般使用 video 标签来嵌入。
自定义渲染:以我们的H.265播放器为例,利用浏览器提供的接口来实现一个模拟的 video 标签,通过 canvas 和 audio 来实现渲染。
web媒体技术
▐ webRTC
网页即时通信(英语:Web Real-Time Communication),它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-Peer)的连接,实现视频流和(或)音频流或者其他任意数据的快速传输。
组成形式:视频引擎(VideoEngine)、音效引擎(VoiceEngine)、会议管理(Session Management)、iSAC(音效压缩)、VP8(Google自家的WebM项目的视频编解码器)、APIs(Native C++ API, Web API)
▐ MSE
用过播放器的同学对于MSE肯定不会陌生。媒体源扩展 API(MSE) 提供了实现无插件且基于 Web 的流媒体的功能。使用 MSE,媒体串流能够通过 JavaScript 创建,并且能通过使用 audio 和 video 元素进行播放。
MSE 大大地扩展了浏览器的媒体播放功能,提供允许 JavaScript 生成媒体流。这可以用于自适应流(adaptive streaming)及随时间变化的视频直播流(live streaming)等应用场景。
这里不展开叙述MSE的使用,感兴趣的同学可以去搜索一下MSE,相信能帮助到你们。
▐ WebXR
XR 是 Extended Reality (扩展现实) 的简写,包括了 VR (虚拟现实),AR (增强现实),MR (Mixed reality,混合现实),WebXR 支持各种 XX 现实的设备。WebXR 允许开发人员创建在所有VR/AR设备都可运行的沉浸式内容,以实现基于 Web 的 VR/AR 体验。
▐ WebGL
WebGL(全写 Web Graphics Library)是一种 3D 绘图标准,并允许用户与之交互。这种绘图技术标准允许把 JavaScript 和 OpenGL ES 2.0 结合在一起,通过增加 OpenGL ES 2.0 的一个 JavaScript 绑定,WebGL 可以为 HTML5 Canvas 提供硬件 3D 加速渲染,这样 Web 开发人员就可以借助系统显卡来在浏览器里更流畅地展示 3D 场景和模型了,还能创建复杂的导航和数据视觉化。
WebGL 基于 canvas 画布来进行渲染。在「播放器」章节,我们了解到播放器可以通过canvas实现播放器图像渲染,通过WebGL,播放器播放流畅性能等能力得到增强。
▐ WebAssembly
WebAssembly 或者 wasm 是一个可移植、体积小、加载快并且兼容 Web 的全新格式,是由主流浏览器厂商组成的 W3C 社区团体制定的一个新的规范。
感兴趣的同学可以去https://webassembly.org/ 了解学习。
基于wasm,播放器可以与FFmpeg结合,对目前浏览器器不能够识别的H.265视频进行解码。
使用的开源产品和框架
市面上目前流行着许多开源产品和框架,我们为各位同学收集了一些优秀的主流框架。
▐ flv.js
flv.js 是 Bilibili 网站开源的 HTML5 flv 播放器,基于 HTTP-FLV 流媒体协议,通过纯 js 实现 FLV 转封装,使 flv 格式文件能在 web 上进行播放。
官方Github:https://github.com/bilibili/flv.js
▐ hls.js
hls.js是基于Http Live Stream协议开发,利用Media Source Extension,用于实现HLS在web上播放的一款js播放库。
值得一提的是由于HLS协议由苹果提出,并且在移动端设备上广泛支持,因此可以被广泛应用与直播场景。
官方GitHub:https://github.com/video-dev/hls.js/
▐ video.js
video.js是一款基于html5的播放器,同时支持h5和flash播放,并且拥有超过100个插件可进行使用,可满足hls、dash格式播放,支持定制主题,字幕扩展等不同层次的诉求,在世界范围拥有大量的应用场景。
官方GitHub:https://github.com/videojs/video.js
官方文档:https://videojs.com/
▐ FFmpeg
FFmpeg 是一套领先的多媒体框架,是一套开源且跨平台的多媒体解决方案,提供了音视频的编码、解码、转码、封装、解封装、流媒体、滤镜、播放等功能,官网地址
对于前端来说FFmpeg可以用来:
- JS播放器:可以基于FFmpeg和WebAssembly实现浏览器端的JS播放器,或扩展浏览器端其他的音视频能力。
- Node模块 fluent-ffmpeg:node.js中非常实用的模块,该模块简化了ffmpeg复杂的命令操作,且配合文件上传以及视频流的处理等非常实用,更多详情可参考 fluent-ffmpeg
▐ OBS
OBS(Open Broadcaster Software)是一个用于录制和进行网络直播的自由开源软件包。OBS使用C和C++语音编写,提供实时源和设备捕获、场景组成、编码、录制和广播。数据传输主要通过实时消息协议(RTMP)完成,可以发送到任何支持RTMP的目的地,包括YouTube、Twitch.tv、Instagram和Facebook等流媒体网站。
在视频编码方面,OBS可以使用X264自由软件程序库、Intel Quick Sync Video、Nvidia NVENC和AMD视频编码引擎将视频流编码为H.264/MPEG-4 AVC和H.265/HEVC格式。音频可以使用MP3或AAC编解码器进行编码。进阶用户可以选择使用Libavcodec/libavformat中的任何编解码器和容器,也可以将流输出到自定义FFmpeg URL。
▐ MLT
MLT是一个够用于多种类型app非线性视频编辑器引擎,且不局限于桌面领域(同样适用于Android、iOS等平台,功能十分强大。
官网地址:https://www.mltframework.org/
Github:https://github.com/mltframework/mlt/
由于篇幅问题,本文仅介绍目前淘宝直播背后的技术,更多技术细节可参考:淘宝直播知识文档