Suba 是一个面向本地媒体库的字幕生成与翻译 CLI 工具。
它用于把电影、剧集、动画、课程等本地视频/音频文件自动处理成可用字幕: 先从媒体中提取音频,再通过 VAD/说话重叠检测/可选人声分离进行预处理,随后使用 Whisper 系列模型转写原文字幕,最后通过 OpenAI 或本地 Ollama 模型翻译并输出目标语言字幕文件。
简单来说,Suba 解决的是这个问题:
我有一批没有字幕、字幕质量很差、或只有外语音轨的视频,想批量生成可用的中文字幕,而不是一个文件一个文件手动处理。
- 扫描本地媒体目录,自动生成待处理任务。
- 支持视频、音频输入,自动提取或复用 16kHz ASR 音频。
- 使用 Silero VAD 切分语音片段,减少无声区干扰。
- 支持 pyannote OSD 检测重叠说话,并可按规则启用 Sepformer 人声分离。
- 使用 faster-whisper / Kotoba Whisper 进行语音转写。
- 支持 OpenAI 标准请求、OpenAI Batch、Ollama 本地模型翻译。
- 支持批量任务、缓存复用、失败重试、运行日志与终端进度面板。
- 输出常见字幕格式,适合配合 Jellyfin、播放器或本地媒体库使用。
本地视频/音频
↓
扫描目录生成 tasks.toml
↓
提取/复用 16kHz 音频
↓
VAD 切分语音
↓
OSD 重叠说话检测
↓
可选 Sepformer 人声分离
↓
Whisper 转写原文字幕
↓
OpenAI / Ollama 翻译
↓
写出目标字幕文件
Suba 更适合以下场景:
- 本地媒体库中有大量外语视频,需要批量生成中文字幕。
- 希望字幕处理过程可配置、可恢复、可重复执行。
- 希望本地完成转写,再用 OpenAI Batch 降低大批量翻译成本。
- 希望用本地 Ollama 模型进行离线或半离线翻译实验。
- 不满足于简单“音频转文字”,而是希望处理 VAD、重叠说话、缓存、批量任务、字幕格式输出等完整流程。
- 想要一个开箱即用的图形界面软件。
- 只想临时转写一个短音频,不需要批量任务和配置文件。
- 完全不想配置 Python、CUDA、ffmpeg、模型路径或翻译服务。
- 需要商业级字幕质量保证而不做人工校对。
推荐先生成本地配置模板和任务模板:
suba init config --output config.local.toml
suba init tasks --output tasks.local.toml扫描媒体目录并生成任务:
suba scan --config config.local.toml --tasks-file tasks.local.toml --input-dir /path/to/media先做配置校验和输入探测:
suba run --config config.local.toml --tasks-file tasks.local.toml --validate-only正式执行:
suba run --config config.local.toml --tasks-file tasks.local.toml如果使用 OpenAI Batch,可按三步执行:
suba batch-submit --config config.local.toml --tasks-file tasks.local.toml
suba batch-poll --config config.local.toml --tasks-file tasks.local.toml
suba batch-apply --config config.local.toml --tasks-file tasks.local.toml先创建并激活虚拟环境,然后安装依赖。
要求:Python 3.12.x(版本已锁定,不支持 3.13+)。
推荐(Windows 一键):
.\scripts\bootstrap.ps1或:
.\scripts\bootstrap.bat可选参数示例:
.\scripts\bootstrap.ps1 -Profile cu129 -ProxyUrl "http://127.0.0.1:10809"
.\scripts\bootstrap.ps1 -Profile cpu -ProxyUrl ""本地配置建议:
- 使用
suba init config --output config.local.toml生成本地主配置模板。 - 使用
suba init tasks --output tasks.local.toml生成本地任务模板。 - 这些文件已被
.gitignore忽略,可安全填写本地提示词与测试任务。
Windows + CUDA:
pip install -U pip
pip install -r requirements/base.txt -r requirements/windows-cu129.txt
pip install -e .Linux + CUDA:
pip install -r requirements/base.txt -r requirements/linux-cu129.txt
pip install -e .CPU:
pip install -r requirements/base.txt -r requirements/cpu.txt
pip install -e .suba init config --output config.toml
suba init tasks --output tasks.toml
suba scan --config config.toml --tasks-file tasks.toml --input-dir /path/to/media
suba run --config config.toml --tasks-file tasks.toml --validate-only
suba run --config config.toml --tasks-file tasks.toml
suba batch-submit --config config.toml --tasks-file tasks.toml
suba batch-poll --config config.toml --tasks-file tasks.toml
suba batch-apply --config config.toml --tasks-file tasks.toml
suba batch-clean --config config.toml --tasks-file tasks.tomlstages.*.typed:强校验区,未知 key 会报错。stages.*.extra:扩展区,允许任意 key。prompts.prompt/prompts.refinement_prompt:模板默认留空,不在仓库内置提示词;请本地填写(兼容旧字段fix_prompt)。stages.transcribe.typed.save_source_subtitle:是否保存原文字幕,默认false。stages.transcribe.typed.model_profile:kotoba-whisper-v2.2(默认)或kotoba-whisper-v2.0。stages.transcribe.typed.without_timestamps:默认false(建议保持,避免时间戳缺失)。stages.translate.typed.api_mode:batch|standard,默认batch。stages.translate.provider_options.proxy_url:OpenAI 请求代理(可选,如http://127.0.0.1:10809)。context.title/context.description/context.genres:可选元数据,仅用于翻译消歧,不会改变时间戳流程。process.paths.batch_work_dir:Batch 工件目录(可选)。为空时优先当前目录suba/batch,失败回退cache_dir/batch。process.batch_artifacts_policy:keep|completed,默认keep。completed表示成功回写后清理 Batch 中间工件。process.batch_split_max_requests:Batch JSONL 拆分的最大请求数(默认30000)。process.batch_split_max_bytes_mb:Batch JSONL 拆分的最大大小 MB(默认150)。- runtime 根目录规则:优先
process.paths.batch_work_dir的上级目录;否则优先当前目录suba,失败回退cache_dir/suba。 - 模型目录优先级:
--models-root>SUBA_MODELS_ROOT>process.paths.models_root。
- 先收集视频,再按规则过滤并生成任务(视频是任务锚点)。
- 同目录同 base 若存在
*.{任意lang}.asr.16khz.wav,优先使用该 ASR 音频作为任务输入;lang仅用于命名,不作为可信语言来源。 - 当
process.overwrite_policy = "skip"时:若同目录已存在{base}.{target_primary}*.{format}(如目标zh-CN时匹配zh*),扫描直接跳过,不写入任务。 - 目标语言主语言为
zh时,视频文件命中以下规则会跳过:- 文件名主干尾部
-C/-C1/-UC/-UC1... - 文件名主干包含
.zh或.zh-*
- 文件名主干尾部
scan默认仅扫描主视频(--scan-main-only),会过滤文件名包含.sample./.trailer.的条目;可通过--no-scan-main-only关闭。scan仅更新任务文件(--tasks-file),不会改写主配置文件。
- 本地实时(
ollama或openai+standard): 提取 -> VAD -> OSD 门控 -> 可选 Sepformer 分离 -> 转写 -> 文件级翻译 -> 字幕写出。openai+standard默认按“整份字幕文件一次请求”翻译(不是逐句请求)。ollama支持stages.translate.extra.mode = sentence|file:默认sentence,可切到file。ollama的sentence模式支持stages.translate.extra.context_window(默认5,即前 5 句上下文)。openai+standard会自动强制使用staged分阶段执行(忽略process.execution_mode=per_task)。ollama优先使用 JSON Schema 约束返回结构;若服务版本不支持会自动降级为format=json并继续校验重试。
- OpenAI Batch(
openai+batch): 本地转写并落地meta-> 生成 JSONL -> 提交 Batch -> 轮询 -> 回写目标字幕。 - 视频输入:始终提取 16kHz wav 到
cache_dir。 - 音频输入:
.wav只读取文件头判断采样率。- 其他音频通过
ffprobe仅读元数据判断采样率。
- 16kHz 音频直接跳过提取,否则提取到
cache_dir。 - 字幕直接写入
tasks.output_dir,不执行跨盘移动。 - 提取并
read_audio之后,后续 VAD/OSD/分离/转写都基于内存音频张量处理,不重复触发媒体文件 IO。
- 路径指纹:仅使用输入路径生成指纹(不使用 size/mtime)。
- 每个任务 meta:
<cache_dir>/jobs/<fingerprint>/<media_name>.meta.json - Batch 状态:
<batch_work_dir>/batches.json meta中会保存 cueid/t与可选o=1(重叠说话弱提示),用于 Batch 映射与回写。- standard/batch 共用 transcribe meta 复用逻辑:若指纹与转写参数签名匹配,会复用已转写结果并跳过重复转写。
- 命令日志:
<runtime_root>/logs/<timestamp>-<command>.log(控制台输出会同步写入日志文件)。 - 日志内容包含异常堆栈(traceback)与任务耗时统计。
- 每个任务在汇总里会输出一行阶段耗时(各阶段 + total)。
- 终端呈现层(TTY 自动启用):顶部总览 + 中部两列(左任务列表固定宽度、右日志自适应)+ 底部按键提示。
- UI 刷新频率固定为
250ms(4Hz),通过事件队列异步消费,不阻塞主流程执行。
[stages.vad.extra]
overlap_gate_enabled = true
enable_sepformer = true
overlap_min_count = 3
overlap_min_total_ms = 3000
overlap_min_ratio = 0.03
osd_onset = 0.8104268538848918
osd_offset = 0.4806866463041527
osd_min_duration_on = 0.05537587440407595
osd_min_duration_off = 0.09791355693027545- 任务级并发由
process.max_workers控制。 process.execution_mode:per_task:按任务完整执行(默认)。staged:按preprocess -> transcribe -> translate/export分阶段队列执行。
- 失败重试与超时策略:
process.retry_count:任务失败后重试次数(默认 0)。process.retry_backoff_seconds:重试退避基数秒数(默认 1.0)。process.task_timeout_seconds:任务软超时阈值(默认 0 表示关闭)。
- GPU 阶段采用互斥保护:
- 转写阶段默认串行(避免显存竞争)。
- 本地 Ollama 翻译默认与转写互斥(共享 GPU 门)。
- Sepformer 分离可配置
stages.vad.extra.separation_device=cpu|gpu|auto。
- OpenAI 翻译默认不占本机 GPU,可与其他任务并发。
- 可选设备参数(均在
extra):stages.transcribe.extra.device = "auto|cpu|gpu"stages.translate.extra.device = "auto|cpu|gpu"stages.vad.extra.separation_device = "auto|cpu|gpu"
- 转写透传参数(在
stages.transcribe.extra):model_options:透传给WhisperModel(...)transcribe_options:透传给model.transcribe(...)
- 润色触发参数(在
stages.translate.extra):request_timeout_seconds:翻译请求超时秒数(默认3600)enable_refinement:是否启用润色逻辑(默认true)refinement_max_len:超过该长度触发润色(默认60)refinement_length_ratio:翻译长度超过原文长度倍数触发(默认2.2)refinement_trigger_patterns:命中任一正则触发润色json_retry_count:文件级 JSON 解析失败时的额外重试次数(默认2)
staged模式可选并发参数(均在extra):stages.vad.extra.preprocess_parallelismstages.transcribe.extra.parallelismstages.translate.extra.parallelism