@kongliu/libde265-web
v0.1.4
Published
Browser HEVC player with transparent WebCodecs/libde265 WASM fallback
Maintainers
Readme
libde265-web
English | 简体中文
浏览器端 HEVC/H.265 实时播放器:优先使用 WebCodecs,浏览器或具体 HEVC 配置不支持时透明回退到 libde265 WebAssembly。两种后端共享同一个播放器、输入、 帧和事件接口。
特性
auto、webcodecs、wasm三种解码模式- WebSocket 二进制 Annex-B 字节流,可跨消息任意分片
- 内置 HEVC NAL/Access Unit 拆分和 VPS/SPS/PPS 缓存
- 有界输入队列、WebCodecs 背压、关键帧安全恢复和渲染丢帧
- 统一
UnifiedVideoFrame,可自动渲染到 Canvas - WASM 可自动移入 Dedicated Worker,并把 HTMLCanvasElement 转移为 OffscreenCanvas
- WebGL2 I420/Main10 shader 渲染,失败时自动回退 Canvas2D
- baseline、WASM SIMD、WASM threads+SIMD 三种构建
- TypeScript 源码和自动生成的类型声明,不依赖前端框架
- ES Module 可直接使用,无运行时 npm 依赖
libde265 本身采用 LGPL-3.0-or-later;本项目的 TypeScript/C++ 胶水采用 MIT。 发布产品前请阅读许可说明和第三方声明,并单独评估 HEVC 专利许可义务。
快速开始
安装开发依赖、编译 TypeScript,并生成 WASM:
npm install
npm run build
git submodule update --init --recursive
npm run build:wasm
npm run serve浏览器打开 http://localhost:8080。serve 会发送 COOP/COEP 响应头,因此
threads+SIMD 变体可以运行。
多路不同视频的简单示例见
examples/multi-view.html,本地访问
http://localhost:8080/examples/multi-view.html。
最小调用代码:
<canvas id="video"></canvas>
<script type="module">
import { createHevcPlayer } from "@kongliu/libde265-web";
const player = await createHevcPlayer({
canvas: document.querySelector("#video"),
mode: "auto",
codec: "hev1.1.6.L93.B0",
wasmBaseUrl: "/assets/libde265/",
wasmWorker: "auto",
renderer: "auto"
});
player.on("error", console.error);
await player.connect("wss://example.com/hevc-stream");
console.log(player.backend); // "webcodecs" 或 "wasm"
</script>调用方需要把 dist/wasm/ 下的文件原样部署到 wasmBaseUrl。完整说明见:
手动推流
不使用内置 WebSocket 时,可以接入任意传输层:
const player = await createHevcPlayer({
canvas,
mode: "auto",
wasmBaseUrl: "/wasm/",
lowLatency: {
maxInputFrames: 12,
maxDecodeQueue: 4,
maxQueueAgeMs: 250,
dropPolicy: "until-key"
}
});
transport.onData((bytes) => {
player.push(bytes); // Uint8Array、DataView 或 ArrayBuffer
});
transport.onEnd(async () => {
await player.flush();
});push() 接收原始 Annex-B HEVC,不接收 MP4、MPEG-TS、FLV 等容器。容器数据必须
先 demux。
自定义协议已经解析出完整帧、PTS 和关键帧标志时,直接调用:
player.pushAccessUnit(packet.payload, {
timestamp: packet.ptsUs,
duration: packet.durationUs,
key: packet.key,
sequence: packet.sequence
});包入口会自动加载 dist/esm/,类型声明由 TypeScript 输出到 dist/types/。调用方无需
引用本项目的 src/ 目录。
浏览器策略
auto 不会仅凭 window.VideoDecoder 存在就选择 WebCodecs。它会调用
VideoDecoder.isConfigSupported() 探测指定的完整 codec string。HEVC 支持与
操作系统、浏览器、硬件和媒体扩展有关,因此应始终保留 WASM 文件。
多线程 WASM 需要:
- HTTPS 或
localhost Cross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corp- 浏览器具备
SharedArrayBuffer
wasmVariant: "auto" 会按 SIMD → baseline 自动选择,不会自动启用多线程。
需要 threads+SIMD 时必须显式指定 wasmVariant: "threads-simd"。
WASM 后端默认在浏览器支持时使用 Dedicated Worker。renderer: "auto" 会优先使用
WebGL2,无法创建 WebGL2 context 时回退 Canvas2D;支持
transferControlToOffscreen() 时,解码和渲染都在 Worker 内完成。需要保持所有
frame.planes 时使用默认的 workerFrameOutput: "planes";纯播放且不读取平面时可设为
"metadata",避免把 Y/U/V 平面复制到主线程:
const player = await createHevcPlayer({
canvas,
mode: "auto",
wasmWorker: "auto",
renderer: "auto",
workerFrameOutput: "metadata"
});
console.log(player.wasmExecution); // "worker"、"main" 或 null
console.log(player.rendererKind); // "webgl2"、"canvas2d" 或 null性能预期
auto 优先选择浏览器原生 WebCodecs;在系统提供 HEVC 硬件解码时,这是低延迟和低 CPU
占用的首选。WASM 是兼容性回退:SIMD 和 threads+SIMD 能明显改善纯软件解码,但实际
能否实时取决于分辨率、位深、码率、设备 CPU 和码流特性,不能用一个固定 FPS 概括。
内置 WASM Canvas 渲染目前会在 CPU 上把 I420 转成 RGBA,高分辨率时可能先成为瓶颈。
对延迟敏感的调用方可以设置 render: false,在 onFrame 中读取统一帧的
nativeFrame 或 planes,接入自己的 WebGL/WebGPU 渲染器。建议用目标设备和真实码流
执行 npm run benchmark:wasm -- baseline <stream.h265> 做验收。
组件默认启用有界低延迟模式。轻度渲染积压时,只丢弃尚未交给调用方的旧解码帧;编码
输入严重积压时会重置解码器、丢弃到下一个 IRAP 关键帧,并触发 keyframerequest。
调用方可监听 backpressure 向自定义服务器发送暂停、降码率或请求 IDR 的控制消息:
player.on("backpressure", ({ level, stats }) => {
transport.setPressure(level, stats);
});
player.on("keyframerequest", () => {
transport.requestIdr();
});验证
npm run check
npm test
npm run build
npm run build:wasm
npm run test:wasm正式生成 npm 安装包时只需执行:
npm run packprepack 会自动依次执行类型检查、单元测试、TypeScript 构建和全部 WASM 构建;任何
一步失败都会中止打包,最终的 .tgz 输出到 build/packages/。不要跳过 prepack,
否则可能把旧版本 libde265 的 WASM 产物装入新包。
上游 libde265 v1.1.1 固定在 Git submodule 中,升级时应重新运行测试和实际码流验证。
