Koe:没做成的浏览器字幕插件

Yuxino,•做东西
中EN

Koe 是我做的浏览器字幕插件,也是 mimi 的副产品。mimi 听电脑正在播放的声音,实时配字幕;Koe 想试另一条路:通用的离线视频字幕,到底能走多远,体验能做到什么水平?

看已经录好的视频,我可以接受先等几秒,让识别和翻译多拿到一点上下文,希望结果好一点。直播不能这么等,录播却有后面的声音可以提前处理。这是我想试的方向,不是说离线就一定更准。

我也试过把 mimi 那种实时字幕做进浏览器,问题很多。具体是哪些旧问题,现在已经记不清了。Koe 最后也没有做成能直接分享给别人用的插件,安装还是很麻烦。

一小时的视频,也要全部先算完吗

先碰到的是长视频。不能每次都把整段音频交给语音识别,再等所有字幕出来才开始看。要等几分钟,用户就不太愿意了;要是一小时的视频呢?后半段也许根本不会看完,有必要先把它全部识别、翻译一遍吗?

所以开始按片段处理。先做播放位置附近的声音,再往后准备,别一上来算完整条视频。本地模式花的是电脑自己的算力和时间;如果改用云端调用,还要算服务费用。

但要提前处理,先得拿到后面的声音。Koe 现在的直读路径只兼容特定的 HLS 点播来源,也就是按播放清单读取一段段媒体文件;还要求来源公开、未加密,分片格式也能处理。并不是所有网站都用这套方式。

普通 MP4、DASH 等来源没有接进这条直读路径。不用 HLS,不等于音频绝对拿不到,只是这次实现没有通用地处理它们。浏览器允许时,Koe 还能采集标签页正在播放的声音,交给本机识别;这又回到了听完才能处理的实时路径,没法靠它预读后面的对白。

能拿到声音的网站,又该怎么切,用户才不会觉得等得太久?五秒一次,还是十秒一次?切得短,字幕可能早点出来,但上下文会不会丢;切得长,又得多等一会儿。当时一直在权衡这些问题。

切片还要处理一句话跨过边界的情况。当前代码让相邻片段重叠一点,保留上下文,再合并结果,避免同一句出现两遍。

数字代表声音里的小段内容,两段都包含 3。这是分段方案的示意,不是实际识别结果。

用户还会跳进度。前面切好的片段用不上了,得从新位置重新安排,不能继续等旧位置的字幕。当前实现会取消旧任务、清掉旧字幕状态,再从新的播放位置开始预读;晚回来的结果也要检查是不是仍属于当前会话。整套处理已经变得很复杂。

时间也要换回整条视频。十分钟处取的一段音频,第三秒的台词要在 10:03 显示。仓库里有旧会话结果隔离 (opens in a new tab)和慢翻译积压处理 (opens in a new tab)的实现记录。

页面里不一定只有一个视频

网页里可能有主视频、广告和预览。要做通用插件,还得判断用户到底在看哪一个,不能看到一个 <video> 就把字幕塞过去。

Koe 已经会根据播放状态、有没有声音和画面大小来选视频,也会降低带广告类名的元素的优先级。这是在猜哪个更像主视频,仍然可能猜错。让用户自己改选是可以继续考虑的办法,目前还没有做好这项选择功能。

显示字幕本身早有浏览器标准。<track> (opens in a new tab) 可以给视频挂上带时间的字幕轨,跟着播放位置显示文字。困难在前面:没有现成字幕时,怎么生成它,怎么拿到对应的声音,以及它到底属于哪个视频。

Chrome 也有 Live Caption 和 Live Translate (opens in a new tab)。前者在本机处理声音和字幕,后者会把字幕发给 Google 翻译,不能把两者一起叫离线翻译。这也和翻译网页上已有的文字是不同的功能。

安装又是另一件麻烦事

Koe 的本地识别由配套的 Helper 在 Mac 上运行 Whisper,首次要下载大约 626 MB 的模型。本地中文翻译还要 macOS 26 及以上,在系统设置里开启 Apple 翻译的 On-Device,并下载支持的语言包。macOS 15–25 的兼容版只能做本地识别。

模型和语言包先下载,视频声音仍从原网站读取。这里说的离线,是识别和翻译留在本机,不是打开所有网络视频都不用联网。Koe 另有 DashScope 云服务模式,会把声音发给服务商处理。

当时我主要拿 ego-lite 测试,写了不少硬编码。比如安装器把 ego-lite 的浏览器身份写死了,自动加载也围着它做;Chrome 还需要手动加载扩展。安装路径还绑着 Apple 芯片 Mac。

下载下来,还被 Apple 的安全检查拒之门外了😭。现成的 Helper 只有 ad-hoc 签名,没有 Developer ID 签名,也没完成 Apple 公证。

Koe 官网 (opens in a new tab)倒是有个可爱的妹子。

Koe 的原角色头像:戴耳机的白发女孩

最后 Koe 啥也没做到,就做了个可爱的妹子……😭 下载下来也是屎一坨。

代码留在 Koe 仓库 (opens in a new tab),感兴趣的话,也可以试着做一个,哈哈。

评论