Show HN:Overtone – 转录、校正并剪切任意屏幕形状的字幕
Show HN: Overtone – Transcribe, correct and cut captions for any screen shape

原始链接: https://github.com/lonthq/overtone-captions

Overtone 将每个口语单词仅存储一次——包含时间戳与说话人——并在单个 `.overtone.json` 文件中为不同屏幕宽高比生成独立的字幕切分。其 CLI 可离线重新切分字幕,或使用语音提供商转录音视频,支持可选的本地处理。video.js 插件会选取与播放器匹配的切分。字幕遵循可读性规则:避免弱行尾、将名称与数字保持在一起、分隔说话人,并在停顿处断句。该格式可导出 WebVTT/SRT。转录结合多个语音引擎,使用 LLM 解决分歧,并应用基于规则的排版,而时间戳来自引擎。基准测试显示,相比单引擎,它产生的不自然断句更少、词错误率更低。软件包包括 CLI、video.js 插件和格式库。完整规则目前覆盖英语和荷兰语;其他语言使用检测或中性规则。它不翻译、不添加声音标签、不提供 GUI 编辑器,并支持最长两小时的媒体。采用 MIT 许可证。

Show HN:Overtone 是一款开源(MIT)工具,用于转录、修正和格式化任意屏幕宽高比的字幕。它结合了多个语音转文本模型(GPT-transcribe、Azure STT、ElevenLabs Scribe);当它们不一致时,会重新发送短片段,并使用 LLM 进行合理性检查,以更高成本降低词错误率。基于规则的切割器将转录稿拆分为大小合适的字幕,尊重停顿、说话人并保持姓名/数字完整,布局针对 16:9 与 9:16 定制。字幕可以烧录进 MP4,或通过 videojs 插件显示;用户可使用 `npx overtone-captions recut` 重新剪辑现有 SRT。API 密钥转录包含 `--dry-run` 成本估算。由 Lont 构建以减少手动字幕修正,它邀请大家为样式、语言和提供商贡献。评论提到 STT 成本和现代字幕质量差;作者澄清 Overtone 不翻译画面上的文字,指出 Netflix/Disney 对此使用强制叙事字幕/IMF 叠层。
相关文章

原文

Captions cut for every screen shape, from one file.

CI npm License: MIT Node.js 22.12 or newer

Live demo · Quick start · CLI · Player · Format spec · Benchmark

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
One .overtone.json file in a 16:9 and a 9:16 player (social style pack), on the Blender open movie Tears of Steel.
Film: (CC) Blender Foundation | mango.blender.org, CC BY 3.0.

Overtone stores each spoken word once, with its time and speaker, and cuts captions separately for each picture shape: 16:9 and 9:16 by default, or any aspect you name. A CLI makes the file from your subtitles, audio or video. A video.js plugin shows the cut that fits the player.

Re-cut subtitles you already have. Offline, no API key, no ffmpeg (Node.js 22.12 or newer):

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

You get TOS-en.overtone.json, .horizontal and .vertical .vtt and .srt files, and a transcript. Word times are estimated from the cues.

Caption a video from its audio. This needs ffmpeg and provider API keys (OpenAI and Azure AI Speech by default; overtone providers lists the variables). --dry-run shows where the audio goes and the estimated cost, and sends nothing:

npm install -g overtone-captions
overtone transcribe talk.mp4 --language en --context "Panel about urban cycling" --dry-run
overtone transcribe talk.mp4 --language en --context "Panel about urban cycling"

--local runs offline instead, with whisper.cpp and Ollama.

Show the captions in 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' });

Most captions are cut once, for one screen, by filling each line to a length limit. The 16:9 cut is too wide for a 9:16 phone video, lines end on "the" or "of", and two speakers share a caption.

Overtone keeps a cut per screen shape in one file. The cuts follow reading rules: lines avoid ending on weak words, names and numbers stay together, each speaker gets their own caption, and pauses become line or caption breaks, so viewers who cannot hear a hesitation can read it.

The same words and times from a NASA interview, cut for 9:16 (22 characters × 2 lines):

Filled to the length limitOvertone
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

Why a new format instead of WebVTT or TTML: those store finished cues, so a player can only rewrap them. .overtone.json stores each word once, plus any number of cuts that point to those words. Export WebVTT or SRT per cut when you need a standard file.

Why not WhisperX, stable-ts or a hosted speech API: they give good words and times, often cheaper. Overtone adds the caption layout on top. overtone recut re-cuts their SRT or WebVTT output, so you can keep your engine.

  • Hearings. Several engines hear the audio. The text hearing (gpt-transcribe) gives the words; the timing hearing (Azure AI Speech) gives word times and speakers. With ELEVENLABS_API_KEY set, ElevenLabs Scribe adds a second hearing.
  • Text vote. Where the hearings disagree, the text model re-listens to the snippet and an LLM chooser picks the words.
  • Editor. An LLM corrects misheard words, names and terms using your context, your glossary and its own world knowledge (it fixes "Telecom Cell" to "Telkomsel" without being told), labels speakers and marks key words. Edits it is unsure about go on a review list for you to check by ear.
  • Line cuts. A versioned rule set cuts the lines for each profile. Same words and rule set, same captions.

The LLM never sets timestamps: each word takes its time from the engines. Code checks only the structure of the LLM's changes. How the pipeline works has every step.

Package What it is
overtone-captions The overtone CLI: transcribe, recut, burn, export, validate, init, languages, providers.
videojs-overtone The video.js 8.5+ plugin and five style packs: clean, social, minimal, high-contrast, lumora.
overtone-format The .overtone.json format: types, JSON Schema, validator, and WebVTT, SRT and text exporters. No runtime dependencies.

See every style pack in the style gallery.

Small and public. Method, full tables and caveats: bench/RESULTS.md and bench/captions/RESULTS.md.

  • Line breaks (three English clips, 20.8 minutes, 16:9, rule set 1): 0.3% of Overtone's breaks end on a word like "the", "of" or "and" with no pause after it. Filling lines to the limit does that at 28.8% of its breaks, ElevenLabs' SRT export at 16.1%. Overtone shows all 47 of the speakers' 0.5–1.5 s pauses as a break; the other two show 28% and 72%.
  • Text (six clips in four languages, 20 minutes, 3 runs, 2026-10-23): on the 5 clips where every engine returned text, word error rate 5.3%, against 6.2% for gpt-transcribe alone and 7.7% for Azure Speech alone.
  • Silent failures: gpt-transcribe returned nothing for a quiet meeting in every run. Overtone retried with the language the other engines heard and scored 32.8%, against 42.9% for Azure Speech alone.
  • Cost: $0.023–0.025 per audio minute in those runs, $0.029 with ElevenLabs Scribe (list prices).
  • Full line-cutting and number rules exist for English and Dutch. German, French, Spanish, Italian and Portuguese have language detection; other languages get neutral rules. See Language.
  • In scripts without spaces (Chinese, Japanese, Thai), a "word" is a whole phrase: one time per phrase, and line breaks only between phrases.
  • No translation, no sound tags such as [music], no GUI editor. Media up to 2 hours.

MIT, see LICENSE. Made by Lont.

联系我们 contact @ memedata.com