Files
hmo 7de5ab3902 subtitle-studio: 字幕生成系统
- 选择文件夹/单文件 → SenseVoice 转录 → LLM 修正 → 多路线翻译 → 双语 SRT
- 路线:直译中文 / 英转中 / 仅转录
- 并发流水线:转录(可调) + LLM 并发(可调),降噪拆锁并发
- 断点续跑:.subtitle-work/ 中间产物,三阶段独立续跑 + 翻译段级续跑
- 去重:history 跟随视频文件夹,防重复任务保护
- 实时进度:SSE 推送 + 耗时显示 + 子任务状态 + 重新生成按钮
- 时间戳调优:VAD silence_schedule + noisereduce 降噪 + 完整性校验
2026-08-16 20:17:14 +08:00

6.2 KiB
Raw Permalink Blame History

字幕生成系统 subtitle-studio — 架构设计

设计日期:2026-08-15 架构:纯 Windows 本地,自包含 | 目标:文件夹/单文件 → 多路线字幕

1. 总体架构

┌─────────────────────────── Windows 本机 ───────────────────────────┐
│                                                                     │
│  [Web 前端] 浏览器页面                                               │
│    - 选择文件夹 / 单个文件                                            │
│    - 选择翻译路线(直译 / 英转中 / 仅转录)                            │
│    - 实时查看任务进度(SSE 推送)                                     │
│    - 已完成视频列表 + 字幕文件下载/打开                                │
│           │ HTTP/SSE                                                  │
│  [FastAPI 后端] :8788                                                │
│    - 任务管理器(队列 + 并发控制,默认 1 任务串行防 GPU 争抢)          │
│    - 进度状态机:pending → transcribing → fixing → translating → srt → done │
│           │                                                          │
│  [管道核心] subsudio.pipeline                                         │
│    - transcribe.py  SenseVoice + fsmn-vadGPU16kHz wav          │
│    - fix.py          LLM 分块并发修正日文/韩文转录                      │
│    - translate.py    LLM 全文翻译(路线1 直译 / 路线2 英转中)          │
│    - srt.py          生成 .ja.zh.srt / .zh.srt / .zh.en.srt          │
│           │                                                          │
│  [运行时] py312_cudaconda + OCG Router (192.168.1.246:19878)      │
└─────────────────────────────────────────────────────────────────────┘

2. 设计决策

D1. 复用 py312_cuda 环境,不新建 venv

  • 转录需要 faster-whisper/funasr/torch-CUDA,已全部就绪于 D:\ProgramData\anaconda3\envs\py312_cuda
  • 后端 FastAPI/uvicorn 也装这个环境(检查缺包再补)
  • 避免重复装 CUDA 依赖(虚拟环境铁律:不污染系统,但可复用专用环境)

D2. LLM 走 OCG Router(本地中转,自动选 key)

  • base_url http://192.168.1.246:19878/v1apiKey ocg-router-local
  • 模型 deepseek-v4-flash1M 上下文,全文一次请求)
  • 关键经验:不指定 max_tokens(推理模型会烧光截断);全文翻译 1746 段 105 秒

D3. 翻译路线(用户可选)

路线 流程 产物
direct (默认) 转录 → LLM修正 → 直译中文 .ja.zh.srt + .zh.srt
via_en 转录 → LLM修正 → 英转中 .r2.zh.en.srt + .r2.zh.srt
transcribe_only 只转录,不翻译 _transcript.json

D4. 任务队列串行执行

  • GPU 转录是重资源操作,一次只跑 1 个任务
  • 翻译阶段可并发分块(fix 用 4 worker
  • 进度通过 SSE 实时推送到前端

D5. 输出目录

  • 默认:字幕文件生成到视频同目录PotPlayer 自动加载)
  • 同时复制一份到 output/<task_id>/ 便于管理/下载

3. 目录布局

subtitle-studio/
├── src/substudio/
│   ├── __init__.py
│   ├── main.py           # FastAPI 入口(uvicorn
│   ├── taskmanager.py    # 任务队列 + 状态机 + SSE 广播
│   ├── pipeline/
│   │   ├── __init__.py
│   │   ├── transcribe.py # SenseVoice 转录(复用技能逻辑)
│   │   ├── fix.py        # LLM 分块并发修正
│   │   ├── translate.py  # LLM 全文翻译(路线选择)
│   │   └── srt.py        # SRT 生成
│   ├── config.py         # 路径/模型/API 配置
│   └── llm.py            # OCG Router 客户端(流式兼容)
├── templates/index.html  # 前端页面
├── static/app.js         # 前端逻辑
├── output/               # 任务输出
├── scripts/start.bat     # 启动脚本
└── README.md

4. 进度状态机

pending → transcribing → fixing → translating → srt → done
                             └────── error(失败即停,可重试)

每阶段有 progress0-100)和 message(如 "转录中 320/1746 段" SSE 事件:task_update 推送 {task_id, status, progress, message}

5. 关键技术点

5.1 转录(复用已验证逻辑)

  • ffmpeg 提取 16kHz 单声道 wav
  • 降噪(默认开启)noisereduce 频谱门控,prop_decrease=0.70.9 过度会字间隙),实测 RMS 降 64%,句子边界更清晰
  • fsmn-vad 切段(时间戳精准关键)
    • max_single_segment_time 参数无效(实测)
    • 必须传自定义 silence_schedule[(8000,500),(12000,300),(20000,200),(inf,100)]
    • 效果:段长从默认 15.67s → 4.64s 上限,平均 1.59s,时间戳严重错位修复
    • 根因:默认 schedule 产生长段 → 只能按字符比例估算句内时间 → 字幕与说话时间对不上
  • SenseVoiceSmall 逐段转录,rich_transcription_postprocess 清理
  • 输出句子级时间戳 JSON

5.2 修正(分块并发)

  • 按字符量分块(块边界=段边界,不切断句子)
  • 每块一个 worker 进程并发(4 worker
  • prompt:结合上下文修正 ASR 错误,保留 [idx]

5.3 翻译(全文一次请求)

  • 不指定 max_tokens1M 上下文)
  • 全文 30K 字符一次请求,1746 段 105 秒
  • 输出 [idx] 行式解析

5.4 OCG Router 兼容

  • 兼容 SSE 流式返回(data: {...} 解析)
  • 有限重试(3 次退避,不疯狂重试)
  • 失败即停 + 进度保存(断点续传)

6. 安全与资源

  • 无 Docker 操作,纯本地文件处理
  • 只读视频,写入同目录 SRT + output/
  • 一次一个任务(GPU 转录),翻译并发仅限 LLM API
  • 不碰系统环境(复用 py312_cuda 专用环境)