尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Jessibuca WASM解码原理:Emscripten如何把ffmpeg变成浏览器里的代码

Jessibuca WASM解码原理:Emscripten如何把ffmpeg变成浏览器里的代码 Jessibuca WASM解码原理Emscripten如何把ffmpeg变成浏览器里的代码【免费下载链接】jessibucaJessibuca 是一款开源的纯H5直播流播放器通过Emscripten将音视频解码库编译成Jswasm)运行于浏览器之中。兼容几乎所有浏览器可以运行在PC、手机、微信中无需额外安装插件。项目地址: https://gitcode.com/langhuihui/jessibucaJessibuca 是一款开源的纯 H5 直播流播放器它的核心解码能力来自 ffmpeg——但不是直接运行 ffmpeg而是通过 Emscripten 工具链把 ffmpeg 音视频解码库编译成 WASM 代码让浏览器原生执行。这就意味着PC、手机、微信里都能播放 H264/H265 直播流无需安装任何插件。本文将带你从零看懂这条WASM 解码流水线以及它在浏览器里的运行原理。上图就是 Jessibuca 的整体架构decoderWASM负责解码renderer.js把解码出的 YUV 数据画到 canvasWebGLPCM 数据交给 AudioContext 播放整个解码过程运行在独立的 Web Worker 线程里不阻塞页面。为什么要把 ffmpeg 搬进浏览器浏览器自带的video标签能播放什么完全取决于操作系统和厂商支持的编码格式H265HEVC在大多数 Chrome/Edge 上无法直接播放FLV、HLS-TS 这类直播封装格式原生支持非常有限想播放就得自己控制解码过程。而 ffmpeg 恰恰是 C 语言写成的解码万能库但它不能直接跑在浏览器里。Emscripten 的作用就是充当翻译官把 C/C 源码编译成 WebAssembly 字节码让浏览器像执行原生代码一样执行它。编译三步曲从 C 源码到 decoder.wasm整个构建过程只需一条命令npm run build:wasm它实际完成了下面三步对应的源码都在仓库中可以逐一查看。第1步交叉编译 ffmpeg 为 WASM 静态库构建脚本 ffmpeg.py 用emconfigure ./configure启动 ffmpeg 的官方配置流程但把编译器全部替换成了 Emscripten 工具链ccemcc、cxxem、aremar。更巧妙的是它开启了极简模式disable-everything关掉所有模块只重新开启avcodec解码核心 少量解析器与解码器h264、hevc、aac、pcm_alaw、pcm_mulaw。这样编译出来的静态库只有几 MB而不是完整 ffmpeg 的几十 MB——体积就是性能首次加载越快开播越快。第2步写一个 C 适配层连接 JSffmpeg 的 API 是给 C 程序用的浏览器需要的是 JS 对象。这个桥接层就是 wasm/decoder.cpp它做了三件事封装 ffmpeg 解码流程FFmpeg基类内部调用avcodec_find_decoder→avcodec_open2→avcodec_send_packet→avcodec_receive_frame也就是找到解码器 → 初始化 → 送入压缩数据 → 取出解码帧的标准流程按类型分家FFmpegVideoDecoder处理 H264/H265 视频帧把 YUV 平面数据整理成紧凑缓冲区FFmpegAudioDecoder处理 AAC 音频并用swr_convert完成采样率/声道转换双向通信解码器内部持有 JS 对象引用jsObject解出一帧就回调draw(timestamp, y, u, v)通知浏览器侧渲染反过来 JS 也能通过setVideoCodec等消息把编码信息传进去。文件末尾的EMSCRIPTEN_BINDINGS(...)宏embind就是报关单——它声明AudioDecoder和VideoDecoder这两个类及其decode、clear方法对 JS 可见。第3步emcc 一键打包wasm/make.py 负责最后的装订emcc ./decoder.cpp obj/lib/libavcodec.a obj/lib/libavutil.a obj/lib/libswresample.a \ -Oz --bind --pre-js ./pre.js --post-js ./post.js \ -s WASM1 -s ALLOW_MEMORY_GROWTH1 -o ../src/decoder/decoder.js几个关键参数的含义参数作用-Oz极致体积优化--bind启用 embind 生成 C/JS 胶水代码--pre-js / --post-js注入 pre.js 和 post.js自定义日志输出与模块导出-s ALLOW_MEMORY_GROWTH1允许 WASM 内存按需增长支持更高分辨率-s TOTAL_MEMORY64MB初始内存 64MB覆盖 1080P 解码缓冲最终产物有两个文件src/decoder/decoder.wasm —— ffmpeg 的 WASM 字节码本体src/decoder/decoder.js —— Emscripten 自动生成的运行时负责下载 wasm、初始化内存、暴露VideoDecoder类给 JS 调用。浏览器里是如何跑起来的运行时大致经历 4 个阶段Worker 中启动Jessibuca 在 Web Worker 里加载decoder.js解码不吃主线程页面滚动、按钮点击都不会卡实例化 WASM运行时内部调用WebAssembly.instantiate(binary, info)把decoder.wasm编译进浏览器并把 JS 环境内存、回调函数注入给它喂数据直播流解复用后得到的 H264/H265 裸数据通过decoder.decode(data, timestamp)进入 WASM 内存中的 ffmpeg 解码管线回调渲染ffmpeg 每解出一帧C 侧调用 JS 的draw()把 YUV 指针传回renderer用 WebGL 把这一帧绘制到 canvas。音频同理解出的 PCM 通过playAudioPlanar()回调交给 AudioContext 播放。你的浏览器支持 WASM 吗WebAssembly 目前全球用户支持率约 96%是 Baseline 特性Chrome、Edge、Safari、Firefox 全覆盖。Jessibuca 仓库提供了检测页面check-support.html —— 一键检测浏览器支持情况wasm-support.html 对应的说明截图见下图浏览器开发者工具里看到content-type: application/wasm响应头就说明 WASM 文件加载正常在 Network 面板中decoder.js和decoder.wasm两个文件都会被请求加载注意 wasm 文件需要正确的 MIME 类型application/wasm否则浏览器会拒绝编译为什么 WASM 解码这么快关键在 CPU 指令集的超频——SIMD单指令多数据。ffmpeg 的大量像素处理循环天然适合 SIMD一条指令同时算 4 个像素速度成倍提升。WebAssembly SIMD 已成为 Baseline 特性全球用户覆盖率约 91.87%这也是 Jessibuca 能单核解码 1080P H265 直播流、同时支持多路并发播放的底层原因。总结一张图记住整条链路阶段工具/文件产物交叉编译 ffmpegffmpeg.pylibavcodec.a等静态库编写 C 适配层wasm/decoder.cpp可被 emcc 编译的源码emcc 打包wasm/make.pydecoder.jsdecoder.wasm浏览器运行src/decoder/decoder.jsWorker 中解码 → canvas 渲染一句话概括Emscripten 把 ffmpeg 的 C 代码翻译成浏览器能直接执行的 WASM 字节码Jessibuca 再在 Web Worker 里调度它解码结果经 WebGL 上屏——插件、Flash、Native 插件统统不需要这就是纯 H5 也能流畅播 H265 直播的底层原理。【免费下载链接】jessibucaJessibuca 是一款开源的纯H5直播流播放器通过Emscripten将音视频解码库编译成Jswasm)运行于浏览器之中。兼容几乎所有浏览器可以运行在PC、手机、微信中无需额外安装插件。项目地址: https://gitcode.com/langhuihui/jessibuca创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表