本地转码的单线程与多线程
“浏览器里能转视频”这件事本身已经不新鲜,但同一网站在不同浏览器里速度差数倍、有的环境还会自动切换“兼容模式”——背后的原因是一条线程的故事。
浏览器里的 ffmpeg 是怎么跑起来的
桌面软件里的 ffmpeg 是本地程序,直接调用操作系统的全部能力。浏览器里做不到——网页代码被关在沙箱里,没有文件系统访问权、不能随意开线程。解决方案是 WebAssembly:把 ffmpeg 编译成 wasm 字节码,在浏览器提供的虚拟机里运行,性能达到原生的七八成。
关键约束在线程上:普通网页环境只给一个主线程,wasm 里的 ffmpeg 也就只能单线程干活——一个核在烧,其他核围观。
多线程的条件与代价
要开多线程,浏览器必须提供 SharedArrayBuffer(共享内存)与真正的 Worker 线程,而启用 SharedArrayBuffer 要求网页以“跨域隔离”(COOP/COEP 头)方式交付——这是 2018 年 Spectre 漏洞后的安全要求。满足条件时,ffmpeg 的多线程版本能把编码任务拆到多个核并行,速度提升数倍。
代价是兼容面收窄:部分浏览器(尤其移动端与内嵌 webview)对隔离头的支持残缺,会出现“半支持”状态——线程能开但静默挂起,任务永远不返回。这是社区已知的坑,不是个别网站的 bug。
自动降级:多线程失败怎么办
工程上的解法是双内核加自动降级:检测到环境满足隔离条件就用多线程内核;多线程加载或运行失败(超时、挂起、报错)自动切换单线程内核重试,用户侧表现为“切换兼容模式”的提示。单线程慢一些,但在任何能跑现代浏览器的设备上都不会挂起。
对使用者的含义:如果某次任务触发了兼容模式,本次会话内后续任务都会直接走单线程——与其反复重试多线程,不如让它跑完。同一文件在 Chrome(多线程)与 Safari(常降级)上的耗时差数倍,是正常现象而非网站偷懒。
什么任务值得等,什么任务别硬扛
浏览器本地处理的 sweet spot 是日常体量:几分钟到几十分钟的视频、单次或小批量任务——零上传、零排队,总耗时通常可接受。三重叠加的场景(超长视频、大批量、极限画质参数)会明显放大单线程与多线程的差距,也更容易触发内存上限,此时桌面工具或分段处理更合理。
还有一条实践建议:多任务排队时让处理标签页保持前台,浏览器对后台标签页的节流会把速度拖到几分之一——线程再多,被冻结了也白搭。