中文 | English
libmedia 是一个用于在 Web 平台上处理多媒体内容(如音频、视频、字幕)的工具库。
libmedia 有 TypeScript 模块和 WebAssembly 模块,并且设计理念上以 TypeScript 模块为主导;我们将音视频的封装解封装层放在 TypeScript 模块实现,这样就能使用异步 IO 来处理各种来源的流,可以让整个系统在非 SharedArrayBuffer 和非 Worker 环境上运行。
解码编码模块放入 WebAssembly 模块中,这些模块可以从 FFmpeg 的 libavcodec 模块中编译而来,并且将每种解码器和编码器编译成单独的 wasm 模块,解决编译产物太大的问题,使用的时候只需要去加载要使用的模块。同时编解码模块可以使用 WebCodecs。
libmedia 的 API 设计上参照 FFmpeg 设计,很多数据结构概念都是一致的,所以你能看见诸如 AVStream
、AVCodecParameters
、AVFormatContext
、AVPacket
、AVFrame
等数据结构。FFmpeg 作为音视频行业事实上的标准,其设计是非常优秀的;照着设计直接得到优秀的设计模式,还减少开发者学习理解的难度,毕竟做音视频开发的多少都对 FFmpeg 学习过;当然最主要的原因是我们需要让这些数据可以在 TypeScript 模块和 WebAssembly 模块中都可以进行读写操作,其在内存上的布局和 FFmpeg 保持一致是前提。
libmedia 是设计在多线程上的,只是可以回退到单线程上运行;所以对多线程开发比较亲和;开发者可以很优雅的基于此做多线程的开发,毕竟在音视频领域使用多线程带来的体验绝对要高出很多。
avformat
音视频封装解封装库(flv、mp4、mpegts、matroska、ogg、mp3)avcodec
音视频编解码库,主要是 C/C++(FFmpeg 和其他编解码项目) 编译的 Wasm 和 Web 平台标准 WebCodecsaudioresample
音频重采样(FFmpeg 音频重采样模块编译)audiostretchpitch
音频变速、变调处理(soundtouch 编译)videoscale
视频缩放,格式转换(FFmpeg libswscale 模块编译)avnetwork
Web 平台网络文件 IO 相关(Fetch、WebSocket、WebTransport、File)avprotocol
音视频协议(dash、m3u8)avrender
音视频渲染(8bit、10bit、HDR、audioWorklet、WebGL、WebGPU)avpipeline
媒体任务处理管线,用于多线程并行化处理任务
libmedia 支持多线程,但需要页面可以使用 SharedArrayBuffer,你可以通过在顶层文档的响应头上添加以下两个响应头:
- Cross-Origin-Opener-Policy: same-origin
- Cross-Origin-Embedder-Policy: require-corp
来开启使用 SharedArrayBuffer,若不支持多线程将回退到主线程上运行。
-
AVPlayer 是 libmedia 的音视频播放器实现,支持软解、硬解、MSE;支持多种封装协议、多种编码格式。 在线 demo 在线本地播放器
-
AVTranscoder 是 libmedia 的转码工具实现 在线 demo
Format | Input | Output |
---|---|---|
flv | ✅ | ✅ |
mov | ✅ | ✅ |
mp4 | ✅ | ✅ |
mpegts | ✅ | ✅ |
mpegps | ✅ | ❌ |
matroska | ✅ | ✅ |
webm | ✅ | ✅ |
h264 裸流 | ✅ | ❌ |
hevc 裸流 | ✅ | ❌ |
vvc 裸流 | ✅ | ❌ |
mp3 | ✅ | ✅ |
ogg | ✅ | ✅ |
ivf | ✅ | ✅ |
aac | ✅ | ❌ |
flac | ✅ | ❌ |
wav | ✅ | ❌ |
webvtt | ✅ | ❌ |
srt | ✅ | ❌ |
ass | ✅ | ❌ |
ssa | ✅ | ❌ |
ttml | ✅ | ❌ |
Protocol | Input | Output |
---|---|---|
hls | ✅ | ❌ |
dash | ✅ | ❌ |
rtmp | ✅ | ❌ |
rtsp | ✅ | ❌ |
rtmp 和 rtsp 需要使用 WebSocket 或 WebTransport 代理 tcp 连接,avplayer 使用如下:
const player = new AVPlayer()
// 第一个参数是 Websocket 代理的 rtmp 地址
player.load('rtmp://xxx.xxx.xxx.xxx/xxx/xxx', {
// uri 是源 rtmp 地址
uri: 'rtmp://xxx.xxx.xxx.xxx/xxx/xxx'
})
player.play()
player.load('rtsp://xxx.xxx.xxx.xxx/xxx')
player.play()
// 使用 wss 连接
player.load('rtsp://xxx.xxx.xxx.xxx/xxx')
// 使用 ws 连接
player.load('rtsp+ws://xxx.xxx.xxx.xxx/xxx')
// 使用 webtransport 连接
player.load('rtsp+webtransport://xxx.xxx.xxx.xxx/xxx')
编解码器被编译成了单独的 wasm 模块,解码器在 dist/decode
目录下,编码器在 dist/encode
目录下。编解码器的 wasm 模块有三个版本分别为 baseline、atomic、simd。baseline 版本是基准版本,指令集对应到 WebAssembly 的 MVP 版本,但需要支持 Mutable Globals,兼容性最高,性能最低;atomic 增加了 atomic 原子操作指令集和 Bulk Memory 指令集;simd 增加了 simd 向量加速指令集,性能最高。目前的 simd 版本是靠编译器自动优化的,不同的编解码器实现效果不同(目前没有看见过有针对 wasm 指令集做加速优化的开源项目,如果想要更高的加速效果需要自己优化,当前只有 h264 的 simd 解码器是手动优化的,也是性能最好的一个 wasm 模块)。
如果你发现某些 wasm(比如 aac.wasm) 文件太大了,这是因为其对应的代码实现里面声明了大块的全局数组导致 Data 段存在大块的全是 0 的数据;只要你的 web 服务器对静态资源开启 gzip 之类的压缩算法就能让其变得很小。
环境 | baseline | atomic | simd | webcodecs |
---|---|---|---|---|
Chrome | 74+ | 75+ | 91+ | 94+ |
Firefox | 61+ | 79+ | 89+ | N/A(linux video only) |
Safari | 13.4+ | 15+ | 16.4+ | 16.4+(video only) |
Wasmtime | 0.20+ | 15+ | 15+ | N/A |
Wasmer | 0.7+ | N/A | N/A | N/A |
Node.js | 12.0+ | 16.4+ | 16.4+ | N/A |
Deno | 0.1+ | 1.9+ | 1.9+ | N/A |
wasm2c | 1.0.1+ | N/A | N/A | N/A |
codec | baseline | atomic | simd | webcodecs(Chrome) |
---|---|---|---|---|
h264 | ✅ | ✅ | ✅ | ✅ |
hevc | ✅ | ✅ | ✅ | ✅ (只支持硬解) |
vvc | ✅ | ✅ | ✅ | ❌ |
av1 | ✅ | ✅ | ✅ | ✅ |
vp8 | ✅ | ✅ | ✅ | ✅ |
vp9 | ✅ | ✅ | ✅ | ✅ |
mpeg1 | ✅ | ✅ | ✅ | ❌ |
mpeg2 | ✅ | ✅ | ✅ | ❌ |
mpeg4 | ✅ | ✅ | ✅ | ❌ |
theora | ✅ | ✅ | ✅ | ❌ |
aac | ✅ | ✅ | ✅ | ✅ |
mp3 | ✅ | ✅ | ✅ | ✅ |
opus | ✅ | ✅ | ✅ | ✅ |
flac | ✅ | ✅ | ✅ | ❌ |
speex | ✅ | ✅ | ✅ | ❌ |
vorbis | ✅ | ✅ | ✅ | ❌ |
ac3 | ✅ | ✅ | ✅ | ❌ |
eac3 | ✅ | ✅ | ✅ | ❌ |
dts | ✅ | ✅ | ✅ | ❌ |
G.711 A-law | ✅ | ✅ | ✅ | ❌ |
G.711 μ-law | ✅ | ✅ | ✅ | ❌ |
codec | baseline | atomic | simd | webcodecs(Chrome) |
---|---|---|---|---|
h264 | ✅ | ✅ | ✅ | ✅ |
hevc | ❌ | ✅ | ✅ | ❌ |
vvc | ❌ | ❌ | ❌ | ❌ |
av1 | ❌ | ✅ | ✅ | ✅ |
vp8 | ✅ | ✅ | ✅ | ✅ |
vp9 | ✅ | ✅ | ✅ | ✅ |
mpeg4 | ✅ | ✅ | ✅ | ❌ |
theora | ✅ | ✅ | ✅ | ❌ |
aac | ✅ | ✅ | ✅ | ✅ |
mp3 | ✅ | ✅ | ✅ | ❌ |
opus | ✅ | ✅ | ✅ | ✅ |
flac | ✅ | ✅ | ✅ | ❌ |
speex | ✅ | ✅ | ✅ | ❌ |
vorbis | ✅ | ✅ | ✅ | ❌ |
ac3 | ✅ | ✅ | ✅ | ❌ |
eac3 | ✅ | ✅ | ✅ | ❌ |
dts | ✅ | ✅ | ✅ | ❌ |
G.711 A-law | ✅ | ✅ | ✅ | ❌ |
G.711 μ-law | ✅ | ✅ | ✅ | ❌ |
-
IFormat
-
OFormat
- WasmAudioDecoder
- WasmVideoDecoder
- WebAudioDecoder
- WebVideoDecoder
- WasmAudioEncoder
- WasmVideoEncoder
- WebAudioEncoder
- WebVideoEncoder
- IOPipeline
- DemuxPipeline
- MuxPipeline
- AudioDecodePipeline
- AudioEncodePipeline
- AudioRenderPipeline
- VideoDecodePipeline
- VideoEncodePipeline
- VideoRenderPipeline
-
struct
-
util
- BitReader
- BitWriter
- BufferReader
- BufferWriter
- IOReader
- IOReaderSync
- IOWriter
- IOWriterSync
- SafeFileIO
若你想集成此项目来开发,建议将本仓库作为子模块,项目使用了 cheap 库,需要你对 cheap 的使用有所了解。凡是使用了 libmedia API 的地方都需要使用 cheap 插件来编译。
当前本项目只支持使用 webpack 进行编译打包
下面介绍如何编译 AVPlayer 和 AVTranscoder 工具
# 克隆项目以及所有子模块
git clone https://github.com/zhaohappy/libmedia.git --recursive
# 进入 libmedia 目录
cd libmedia
# 安装依赖
npm install
# 编译 AVPlayer 开发版
npm run build-avplayer-dev
# 编译 AVTranscoder 开发版
npm run build-avtranscoder-dev
# 启动本地 http 服务
# 任何一个 http 服务都行,若报 edp 找不到,可以全局安装: npm install edp -g
edp webserver start --port=9000
# 浏览器访问 http://localhost:9000/test/avplayer.html
若要源码调试多线程 Worker 中的代码,设置 tsconfig.json
中ENABLE_THREADS_SPLIT
宏为 true
并重新编译
{
"cheap": {
"defined": {
"ENABLE_THREADS_SPLIT": true
}
}
}
tsconfig.json
还可设置其他宏来裁剪编译,你可以根据自己的需要更改相关设置,详情看 tsconfig.json
-> cheap
-> defined
中的配置
examples/demux.ts
是解封装的使用示例
examples/mux.ts
是封装的使用示例
examples/decode.ts
是解码的使用示例
test/avplayer.html
是 AVPlayer 的使用示例,也是在线 demo 的实现
test/avtranscoder.html
是一个 AVTranscoder 的使用示例,也是在线 demo 的实现
libmedia 使用 LGPL 开源协议,你需要遵守协议要求,详情查看 LGPL
但某些依赖库是 GPL 协议,如果你使用了这些依赖库则 libmedia 将被传染为 GPL 协议。这些依赖库使用在下面的组件:
- dist/encoder/x264.wasm
- dist/encoder/x264-atomic.wasm
- dist/encoder/x264-simd.wasm
- dist/encoder/x265-atomic.wasm
- dist/encoder/x265-simd.wasm
- ffmpeg: LGPL v2.1+
- soundtouch: LGPL v2.1
- openh264: BSD-2-Clause
- x264: GPL
- x265: GPL
- theora: BSD-3-Clause
- vorbis: based BSD
- speex: revised BSD
- opus: BSD-3-Clause
- libvpx: BSD-3-Clause
- libogg: BSD-3-Clause
- lame: LGPL
- kvazaar: BSD-3-Clause
- flac: BSD-3-Clause
- fdkaac: based BSD
- dav1d: BSD-2-Clause
- aom: BSD-2-Clause
- hls-parser: MIT
- sdp-transform: MIT
- ass.js: MIT
- ass-compiler: MIT
- yox: MIT
版权所有 (C) 2024-现在 赵高兴
Copyright (C) 2024-present, Gaoxing Zhao