当前位置: 首页 > news >正文

WasmVideoPlayer:浏览器里直接播放H265视频

文章目录

  • WasmVideoPlayer:浏览器里直接播放H265视频
    • 技术实现
    • 线程模型
    • 缓冲控制
    • 音视频同步
    • 编译和使用
    • 已知问题

WasmVideoPlayer:浏览器里直接播放H265视频

这个项目在 GitHub 上拿到了 1390 Star。

sonysuqin 开源了 WasmVideoPlayer,做的事情很明确:用 WebAssembly 在浏览器里播放 H265 编码的视频。

目前原生支持 H265 播放的浏览器基本没有。H265 解码对性能要求高,硬解兼容性差,再加上专利费的问题,各大浏览器厂商都在转向支持更开放的 AV1 编码。但 AV1 的商用普及还需要时间。

现实情况是,H265 相比 H264,在相同分辨率下码率几乎降了一半。对带宽压力大的网站来说,用 H265 能省不少带宽成本。只是浏览器不支持,目前 H265 播放主要靠 APP 端的硬件解码。

这个项目用 WASM、FFmpeg、WebGL、Web Audio 组合出了一套浏览器端的 H265 播放方案。

技术实现

整个播放器的核心组件:

  • FFmpeg 3.3 负责解封装和解码,理论上支持 FFmpeg 的各种内置 codec,包括 H264、H265,默认支持 MP4、FLV 文件播放和 HTTP-FLV 流播放
  • WebGL 做 YUV 到 RGB 的颜色空间转换和渲染,硬件加速,性能比 CPU 转换好
  • Web Audio 处理 PCM 音频数据的播放
  • WASM 让 C/C++ 代码能在浏览器里跑

线程模型

WASM 对多线程的支持还不够成熟,浏览器端的 pthread 还在试验阶段。所以这个项目用了 Web Worker 来实现线程分离。

三个线程各管各的:

主线程负责界面控制、播放控制、下载控制、音视频渲染和同步。解码线程跑在 Decoder Worker 里,处理解封装和解码。下载线程单独一个 Downloader Worker,按 chunk 下载文件。

线程之间用 postMessage 异步通信,传视频帧这种大数据时用 Transferable 接口,避免拷贝损耗性能。

缓冲控制

播放器的缓冲控制比较关键。FFmpeg 的同步读数据接口必须保证能返回数据,但 WASM 现在没法用多线程同步机制。

项目做了两层缓存:获取文件元信息之前的数据缓存,和解码帧缓存。数据不足时停止解码进入 Buffer 状态,数据够了继续播放。这样 FFmpeg 就不会因为读不到数据而报错退出。

下载也有速率控制,拿到文件码率后以码率的一定倍数下载,不会无限制占用带宽和 CPU。

音视频同步

音频数据直接交给 Web Audio,通过 API 获取当前播放的音频时间戳,以此为基准同步视频帧。视频帧时间落后就立刻渲染,时间早就 delay。

delay 用 setTimeout 实现,缓冲控制同时也在控制渲染频率,避免 setTimeout 调用太多导致内存暴涨。

编译和使用

环境需要安装 Emscripten 工具链,下载 FFmpeg 3.3 分支,再 clone 项目代码,保证 FFmpeg 和代码目录平级。进入代码目录执行./build_decoder.sh编译。

测试用任意 HTTP Server 都行,比如http-server -p 8080 .,浏览器打开 localhost:8080 就能跑。

Chrome、Firefox、Edge 的较新版本都支持,360 浏览器、搜狗浏览器等 webkit 内核的也能用。

已知问题

H265 解码播放的 CPU 占用比较高。如果不及时传递音频数据,AudioContext 的 currentTime 不做控制可能导致音视频不同步。

这个项目定位是探索验证性质,功能实现上还有很多细节可以优化。但它确实验证了一件事:通过 WASM + FFmpeg 的组合,浏览器端播放 H265 是可行的。

现上还有很多细节可以优化。但它确实验证了一件事:通过 WASM + FFmpeg 的组合,浏览器端播放 H265 是可行的。

http://www.cnnetsun.cn/news/3150305.html

相关文章:

  • GitHub功能全览:含AI代码创作、多解决方案及汽车故障诊断音频ML项目
  • 性价比高的区域教育一体化管理平台哪个更完善
  • 云原生技术28-K8s排障实战:20个常见问题的快速定位与解决,从CrashLoopBackOff到Running的完整指南
  • SSTImap实战指南:自动化检测与利用服务器端模板注入漏洞
  • 2025年AI Agent爆发:程序员转型“智能体指挥官“的5个实战路径
  • cubesendbox安装过程踩坑笔记➕解决方案
  • 2026,需要处理音视频字幕的开发者该怎么选靠谱好用的字幕提取器
  • AI技能管理新范式:告别手动复制,实现提示词工程化与资产化
  • 终极GitHub下载加速指南:3分钟解决国内访问缓慢问题
  • 通过代理路由实现Codex无缝切换国产大模型:CC Switch配置指南
  • 从零理解 RBAC:元点Admin 如何实现按钮级权限控制
  • 2026实测解析:软件测试培训为什么首推橙好测试开发?零基础/转行必看
  • Skills Manager:开源AI技能管家,实现提示词工程化与团队协作
  • GPT-5.5 Instant:从拼智商到拼情商,AI助手如何变得更懂你
  • 基于大数据爬虫+Hadoop用户偏好迁移的电影推荐系统
  • Dify 实战指南:从零构建 AI 应用,掌握 Agent 工作流与 RAG 核心
  • 当我们在浏览器里点开一把小锁:SSL/TLS是怎么保护我们的
  • python字符串的四种定义方式
  • 基于SpringBoot的合同管理系统与实现
  • 红日靶场(ATTCK实战)1通关方法
  • 少儿C++分级课程体系搭建:从L1到L4的教学设计经验分享
  • MAF预定义ChatClient中间件-07]PerServiceCallChatHistoryPersistingChatClient——基于ReAct循环的一步一存档
  • OpenClaw 的 sessions_spawn 隔离机制
  • 若依系统登录密码RSA加密实战:jsencrypt前端加密与Spring Boot后端解密
  • Go 数据结构 string 深度剖析
  • Docker--Docker Swarm集群
  • Deepin Boot Maker实战指南:跨平台启动盘制作高效方案深度解析
  • 苏州本地AI流量破局!一网推GEO苏州本地服务中心年度收录破8万
  • QA Use:推荐一款AI 原生 E2E 测试平台,自然语言一键跑通用例!
  • 冰河木马 v8.4 手动清除实战:3步删除注册表项与恢复文件关联