我家里那台跑媒体服务的机器,片子攒了不少,问题一直是字幕。外挂字幕站时好时坏,冷门片、家庭录像、老纪录片干脆就没有;在线字幕插件又要把文件哈希传出去比对,总觉得别扭。前阵子翻 Jellyfin 插件列表,看到一个叫 WhisperSubs 的东西——用本地 Whisper 给整个媒体库自动生成字幕,转写全程在自己机器上跑,不上云。这正好戳中我,折腾了一晚上,记一下。

它到底干什么
一句话:把 OpenAI 的 Whisper 语音识别模型接进 Jellyfin,扫描你的媒体库,给没有字幕的片子自动转写出 .srt。底层用的是 whisper.cpp——就是那个把 Whisper 用 C/C++ 重写、能在纯 CPU 上跑的项目,所以哪怕你没有独显也能用,只是慢一点。
关键卖点是本地处理。它自己也说得挺实在:默认情况下音频抽取和转写都在这台 Jellyfin 服务器上完成,媒体不会离开你的内网,除非你主动去配一个云端 worker。对我这种东西尽量留在本地的人来说,这个默认行为就是我要的。
许可证是 GPL-3.0,要求 Jellyfin 10.11 以上,目前更新到 4.3 这一代,作者七月中旬还在提交,活跃度没问题。
它是怎么工作的
流程其实不复杂,拆开就四步:FFprobe 先读音轨的语言标签,FFmpeg 把音频抽成 16kHz 单声道的 WAV,丢给 whisper.cpp 转写,最后生成的字幕文件按 片名.语言.generated.srt 的命名摆到媒体旁边,刷新一下元数据 Jellyfin 就认了。
WhisperSubs 字幕生成流程(全程在本地)
媒体文件
影视 / 音乐
FFmpeg
抽出 16kHz
单声道音轨
whisper.cpp
本地推理
CPU / GPU
生成字幕
.srt / .lrc
与媒体同目录
Jellyfin
自动加载
音频与转写全部在自己的机器上完成,媒体不出内网
可选:把转写分发给内网里带 GPU 的机器组成 worker 池并行加速
底层这个 whisper.cpp,就是下面这张官方演示图里跑的东西——纯本地把语音实时转成带时间轴的文本:

怎么装
装法比我想的省事。在 Jellyfin 里进 控制台 → 插件 → 存储库,加一个仓库地址:
https://geiserx.github.io/whisper-subs/manifest.json
然后去目录里找 WhisperSubs 装上,重启 Jellyfin 就行。
装完最关键的一步是准备 whisper 引擎。这插件做了个很贴心的设计:在 Linux 上,插件设置页里的「Whisper Engine」区块可以一键下载 whisper-cli 二进制和模型,不用自己手动编译。它还会检测你的 CPU 支不支持 AVX 指令、有没有对应 GPU 库,选不对就自动降级到兼容版本,省了不少踩坑功夫。
模型我建议直接用它默认推荐的 ggml-large-v3-turbo-q5_0,574MB 大小,质量接近满血版但体积只有三分之一。想更省资源可以退到 base(148MB),代价是准确度明显下降。
几个真正要注意的坑
1. Docker 里跑 Jellyfin 的,二进制得进得了容器。 官方镜像默认不带 whisper-cli 需要的运行库(比如 libgomp1)。推荐做法是把宿主机上放二进制和模型的目录只读挂进容器:
volumes:
- /opt/whisper:/opt/whisper:ro
然后在插件里把二进制路径指到 /opt/whisper/whisper-cli。注意二进制的架构要和容器一致,别拿 arm64 的塞进 x86 容器。
2. CPU 转写是真的慢,别用错模式。 普通的「Full」全量转写还好,一个片子跑一遍 whisper 就完事。但「Forced Only」(只转外语对白那种强制字幕)是多步流水线:先做 VAD 切分,再对每个约 30 秒的片段单独做语言检测——一部两小时的电影光检测就要跑约 240 次 whisper 调用,在 CPU 上这一步就能耗掉十几二十分钟。大多数人根本不需要 forced 字幕,老老实实用 Full 模式就好。
3. 页内那个「生成字幕」按钮,只读 web 根会失效。 插件想往 Jellyfin 的 index.html 里注入一段脚本来加这个按钮,但容器化部署里 web 根经常是只读的。解决办法是装一个叫 File Transformation 的第三方插件,让它在响应时动态注入,不改磁盘上的文件,也不用去折腾 chown。
4. 老 CPU / 低功耗 NAS 当心非法指令。 默认的 cpu 构建带 AVX/AVX2 指令,那些没有 AVX 的低端 U(一些入门 NAS、Atom/Celeron、部分虚拟机)直接会崩在「illegal instruction」。好在插件会检测并自动换成 noavx 兼容版,实在不行也能在设置页手动选「CPU (Compatibility)」。
值得一提的两个功能
一个是定时扫描。开了自动生成之后,它默认每天凌晨两点和启动时各扫一遍,给新入库的片子补字幕。而且做了 skip 缓存,已经有字幕的不会反复重扫,大库跑起来第二遍很快。
另一个是分布式 worker 池,我觉得是这插件最聪明的地方。默认所有活儿都在 Jellyfin 这台机器上串行跑,但你要是内网里还有别的机器——比如一台带独显的主机——可以把它们组成一个池子并行转写。它永远优先用你「免费的本地 worker」,只有本地都忙不过来才会溢出到成本权重更高的节点。对我这种主力机性能一般、但内网里零零散散还有几台机器的情况,等于把闲置算力利用起来给字幕库提速。配置也简单,填个 endpoint URL、设并发数和成本权重,点 Test 测通就能存。
小结
折腾下来的体感:这东西解决的是一个很具体、很烦人的真实痛点——媒体库里那些永远配不齐字幕的片子。它没搞花活,就是把成熟的本地语音识别老老实实接进 Jellyfin,默认不上云、模型一键下、还给低端机做了自动降级兜底,工程上很克制。
唯一要提前想清楚的是算力。纯 CPU 能用但要有耐心,尤其别碰 forced 模式;有块显卡或者内网有富余机器组池子,体验会好非常多。如果你也有一堆没字幕的片子躺在自建媒体库里,又不想把文件信息传给在线字幕服务,这个值得装来试试。