一个文件,为每种屏幕形状裁切字幕。

CI npm License: MIT Node.js 22.12 or newer

在线演示·快速开始·CLI·播放器·格式规范·基准测试

The Overtone demo on Tears of Steel: a 16:9 player shows the one-line caption 'The world's changed, Celia.' and a 9:16 player, center-cropped to the same close-up, the two-line cut 'The world's / changed, Celia.'; in both, 'world's changed,' has a yellow highlight as key words
一个.overtone.json文件,在 16:9 和 9:16 播放器中(social样式包),基于
Blender 开源电影 Tears of Steel。影片:(CC) Blender Foundation |mango.blender.org,CC BY 3.0

。

快速开始

重新裁切你已有的字幕。离线运行,无需 API key,无需 ffmpeg(Node.js 22.12 或更新版本):

curl -O https://download.blender.org/demo/movies/ToS/subtitles/TOS-en.srt
npx overtone-captions recut TOS-en.srt

你会得到TOS-en.overtone.json、.horizontal和.vertical .vtt以及.srt文件,还有一份转录文本。词级时间是从字幕提示估算的。

从音频为视频生成字幕。这需要ffmpeg以及服务商的 API key(默认是 OpenAI 和 Azure AI Speech;overtone providers列出了相关环境变量)。--dry-run会显示音频的去向和预估费用,并且不会发送任何内容:

npm install -g overtone-captions
overtone transcribe talk.mp4 --language en --context "关于城市骑行的座谈" --dry-run
overtone transcribe talk.mp4 --language en --context "关于城市骑行的座谈"

--local改为离线运行,使用 whisper.cpp 和 Ollama。

在 video.js 中显示字幕:

import videojs from 'video.js';
import 'video.js/dist/video-js.css';
import 'videojs-overtone';
import 'videojs-overtone/themes/base.css';
import 'videojs-overtone/themes/clean.css';

videojs('my-video')。overtone({ src: 'talk.overtone.json' });

为什么

大多数字幕只裁切一次,针对一块屏幕,做法是把每行填到长度上限。16:9 的裁切对 9:16 的手机视频来说太宽,行尾会落在 "the" 或 "of" 上,而且两位说话人共用一条字幕。

Overtone 在一个文件里为每种屏幕形状保留一份裁切。这些裁切遵循阅读规则:行尾避免落在虚词上,人名和数字保持在一起,每位说话人都有自己的字幕,停顿会变成换行或字幕断点,这样听不到犹豫的观众也能读出来。

同一段来自 NASA 采访的词句和时间,按 9:16 裁切(22 字符 × 2 行):

填到长度上限Overtone
the 2004 class. Jim,
thank you for joining

us. It's great to be here, Allard. Thanks.

Jim, thank you
for joining us.

It's great to be here, Allard. Thanks.

through you? Okay. A
little about me: I

grew up in Eugene, Oregon. I joined the

Okay.
A little about me:

I grew up in Eugene, Oregon.

I joined the Astronaut Corps

为什么要用新格式而不是 WebVTT 或 TTML:它们存储的是成品字幕提示,所以播放器只能重新折行。.overtone.json将每个词存储一次,外加任意数量的指向这些词的切分点。需要标准文件时,可按切分点导出 WebVTT 或 SRT。

为什么不用 WhisperX、stable-ts 或托管语音 API:它们能给出不错的词和时间,通常还更便宜。Overtone 在其上增加了字幕布局。overtone recut重新切分它们输出的 SRT 或 WebVTT,因此你可以保留自己的引擎。

工作原理

  • 听审。多个引擎听取音频。文本听审(gpt-transcribe)给出词;时间听审(Azure AI Speech)给出词时间和说话人。启用ELEVENLABS_API_KEY后,ElevenLabs Scribe 会增加第二次听审。
  • 文本投票。当各听审结果不一致时,文本模型会重新聆听该片段,并由一个 LLM 选择器挑选词。
  • 编辑器。LLM 利用你的上下文、你的术语表和自身的世界知识来纠正听错的词、名称和术语(它无需提示就能把 "Telecom Cell" 修正为 "Telkomsel"),标注说话人并标记关键词。它不确定的修改会进入复核列表,供你靠耳朵检查。
  • 行切分。一套带版本的规则集为每个配置切分行。相同的词和规则集,得到相同的字幕。

LLM 从不设置时间戳:每个词的时间来自各引擎。代码只检查 LLM 修改的结构。流水线如何工作包含每一步。

包

包 它是什么
overtone-captions 该overtoneCLI:transcribe,recut,burn,export,validate,init,languages,providers。
videojs-overtone video.js 8.5+ 插件和五个样式包:clean,social,minimal,high-contrast,lumora。
overtone-format 该.overtone.json格式:类型、JSON Schema、验证器,以及 WebVTT、SRT 和文本导出器。无运行时依赖。

在样式库中查看每个样式包。

基准测试

小而公开。方法、完整表格和注意事项:bench/RESULTS.md和bench/captions/RESULTS.md。

  • 换行(三个英文片段,20.8 分钟,16:9,规则集 1):Overtone 的换行中有 0.3% 结束于 "the"、"of" 或 "and" 这类词且其后无停顿。将行填满到上限的做法,其换行中有 28.8% 如此,ElevenLabs 的 SRT 导出为 16.1%。Overtone 将说话人全部 47 处 0.5–1.5 秒的停顿都显示为换行;另外两者分别显示 28% 和 72%。
  • 文本(四个语言的六个片段,20 分钟,3 次运行,2026-10-23):在所有引擎都返回文本的 5 个片段上,词错误率为 5.3%,而单独使用 gpt-transcribe 为 6.2%,单独使用 Azure Speech 为 7.7%。
  • 静默失败:gpt-transcribe 在一场安静的会议中每次运行都返回空结果。Overtone 用其他引擎听到的语言重试,得分为 32.8%,而单独使用 Azure Speech 为 42.9%。
  • 成本:在这些运行中,每分钟音频 $0.023–0.025,使用 ElevenLabs Scribe 为 $0.029(标价)。

限制

  • 完整的断行和数字规则适用于英语和荷兰语。德语、法语、西班牙语、意大利语和葡萄牙语支持语言检测;其他语言使用中性规则。参见语言。
  • 在没有空格的文字(中文、日文、泰文)中,“词”是一个完整短语:每个短语计一次时间,断行只发生在短语之间。
  • 无翻译,无音效标签,例如[music],无 GUI 编辑器。媒体最长 2 小时。

文档

许可证

MIT,参见LICENSE。作者Lont。