libmedia
libmedia copied to clipboard
一个 TypeScript 实现的高性能媒体库,支持 WebCodecs 和 Wasm。 A high-performance media library implemented in TypeScript, support WebCodecs and Wasm.
libmedia
中文 | English
介绍
libmedia 是一个用于在 Web 平台上处理多媒体内容(如音频、视频、字幕)的工具库。
背景
目前想在 Web 平台上处理音视频使用 ffmpeg.wasm 项目是一个不错的选择;但其还是有很多缺陷:
-
首当其冲的是内存占用问题,ffmpeg.wasm 会将需要处理的文件数据先整个写入内存,处理一个大一点的文件通常会 OOM。这完全无法基于其做出一个体验很好的项目;
-
ffmpeg.wasm 提供的 API 基于 native ffmpeg 命令行,没有 ffmpeg API 级别的接口,大大限制了灵活性;
-
编译输出文件太大,影响加载速度并且你很难去优化它;
-
只能在开启 SharedArrayBuffer 的页面上使用,目前绝大多数网站都是没有支持 SharedArrayBuffer 环境的;提供的单线程版性能又降低一大截;
-
无法和 Web 生态进行有效的结合,比如无法使用 WebCodecs,无法处理流式来源的数据;Web 上基本都是异步 IO;
libmedia 就是为了尝试解决上面的问题而设计的。
libmedia 有 TypeScript 模块和 WebAssembly 模块,并且设计理念上以 TypeScript 模块为主导;我们将音视频的封装解封装层放在 TypeScript 模块实现,这样就能使用异步 IO 来处理各种来源的流,规避 ffmpeg 中的同步 IO 所带来的问题。这样可以让整个系统在非 SharedArrayBuffer 环境上运行;
解码编码模块放入 WebAssembly 模块中,这些模块可以从 ffmpeg 的 libavcodec 模块中编译而来,并且将每种解码器和编码器编译成单独的 wasm 模块,解决编译产物太大的问题,使用的时候只需要去加载要使用的模块。同时编解码模块可以使用 WebCodecs。
libmedia 的 API 设计上参照 ffmpeg 设计,很多数据结构概念都是一致的,所以你能看见诸如 AVStream
、AVCodecParameters
、AVFormatContext
、AVPacket
、AVFrame
等数据结构。ffmpeg 作为音视频行业事实上的标准,其设计是非常优秀的;照着设计直接得到优秀的设计模式,还减少开发者学习理解的难度,毕竟做音视频开发的多少都对 ffmpeg 学习过;当然最主要的原因是我们需要让这些数据可以在 TypeScript 模块和 WebAssembly 模块中都可以进行读写操作,其在内存上的布局和 ffmpeg 保持一致是前提。
libmedia 是设计在多线程上的,只是可以回退到单线程上运行;所以对多线程开发比较亲和;开发者可以很优雅的基于此做多线程的开发,毕竟在音视频领域使用多线程带来的体验绝对要高出很多。
库
-
avformat
音视频封装解封装库(flv、mp4、mpegts、matroska、mp3) -
avcodec
音视频编解码库,主要是 C/C++(FFmpeg 和其他编解码项目) 编译的 Wasm 和 Web 平台标准 WebCodecs -
audioresample
音频重采样(FFmpeg 音频重采样模块编译) -
audiostretchpitch
音频变速、变调处理(soundtouch 编译) -
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
-
AVTranscode 是 libmedia 的转码工具实现,目前还未实现
API
avformat
-
AVStream
-
AVFormatContext
-
demux
-
mux
-
IFormat
- IFlvFormat
- IIvfFormat
- IMatroskaFormat
- IMovFormat
- IMp3Format
- IMpegtsFormat
- IOggsFormat
-
OFormat
- OFlvFormat
- OIvfFormat
- OMatroskaFormat
- OMovFormat
- OMp3Format
- OMpegtsFormat
- OOggsFormat
avcodec
- WasmAudioDecoder
- WasmVideoDecoder
- WebVideoDecoder
avpipeline
- IOPipeline
- DemuxPipeline
- AudioDecodePipeline
- AudioRenderPipeline
- VideoDecodePipeline
- VideoRenderPipeline
avnetwork
- FetchIOLoader
- FileIOLoader
- DashIOLoader
- HlsIOLoader
avplayer
- AVPlayer
avutil
-
struct
- AVBuffer
- AVCodecParameters
- AVFrame
- AVPacket
- AVPCMBuffer
-
util
- avbuffer
- avframe
- avpacket
- avcodecparameters
io 组件
- BitReader
- BitWriter
- BufferReader
- BufferWriter
- IOReader
- IOReaderSync
- IOWriter
- IOWriterSync
- SafeFileIO
开发
若你想集成此项目来开发,建议将本仓库作为子模块,项目使用了 cheap 库,需要你对 cheap 的使用有所了解。凡是使用了 libmedia API 的地方都需要使用 cheap 插件来编译。
当前本项目只支持使用 webpack 进行编译打包
下面介绍如何编译 AVPlayer 工具
# 克隆项目以及所有子模块
git clone https://github.com/zhaohappy/libmedia.git --recursive
# 进入 libmedia 目录
cd libmedia
# 安装依赖
npm install
# 编译 AVPlayer 开发版
npm run build-avplayer-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
并重新编译 AVPlayer
{
"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/avtranscode.html
是一个转码示例,涉及到解封装和封装的用法
相关文章
下一代 Web 音视频技术会是什么样的
开源协议
libmedia 使用 LGPL 开源协议,你需要遵守协议要求,详情查看 LGPL
版权所有 (C) 2024-现在 赵高兴
Copyright (C) 2024-present, Gaoxing Zhao