edit | blame | history | raw

本地视频语音转写 4 小时长视频优化编码方案 V001

创建人员:dev.developer.project
文件职责:冻结长视频有界分块、时间轴合并、资源验收和失败清理的最小实现方案。
管理规范/模板:../../../dev-doc/编码规范.md../../../dev-doc/开发审计规范.md../../../../common/dev-doc/编码规范.md
引用文件:../../../ai-media-processor/draft/本地视频语音转写_4小时长视频性能与资源优化需求_v0.1.md../../../dev/project-dev/transcribe_media.py../../../dev/project-dev/test/test_transcribe_media.py../本地视频语音转写工具.md
记录方式:重型性能优化编码方案;方案审核通过后按本版本实现,变化另建后继版本。

1. 事项与边界

  • 事项:DEV-PROJECT-INFO-LOCAL-MEDIA-TRANSCRIBE-LONG-VIDEO-OPT-20260801-001
  • 目标:保持命令、模型和四文件合同不变,使约 4 小时视频不再把完整波形、VAD 拼接结果和频谱一次装入 Python 内存。
  • 只修改 dev/project-dev/transcribe_media.py、对应测试和使用说明;不新增模型、CPU 降级、批处理、断点续跑、服务或数据库。
  • 原视频只读;完整 FLAC 仍为正式候选输出;失败统一删除暂存目录,四个正式文件只在全部成功后提交。

2. 模块和接口

现有公开 CLI 与 transcribe_video(video_path, output_dir, language, ...) 不变,只增加内部函数:

  1. _probe_audio_duration:对已生成的完整 FLAC 获取有限、正数时长。
  2. _plan_audio_chunks:当时长大于 1200 s 时生成顺序核心区间;核心长度 1200 s,两侧重叠 5 s,首尾裁到 [0,duration]
  3. _extract_audio_chunk:从完整 FLAC 生成唯一临时块;固定 16 kHz、单声道 FLAC、-n,失败显式停止。
  4. _collect_chunked_transcript:复用同一模型逐块转写;每块结束后在 finally 删除临时块。
  5. _project_chunk_segments:块内时间加音频块全局起点;按分段中点落入对应核心 [core_start, core_end),仅末块允许中点等于总时长;排序后输出全局分段。

短视频 duration <= 1200 s 继续调用现有 _collect_transcript(model, full_flac, language),不创建音频块。

3. 语言与模型合同

  • large-v3device=cudacompute_type=float16vad_filter=True 不变。
  • 模型在完整 FLAC 生成后只加载一次。
  • 显式语言传给所有块;未指定语言时首块不传语言,保存其检测语言和概率,后续块固定复用检测语言。
  • 任一块失败不走 CPU、其他模型或参数降级。

4. 时间轴与去重

对第 i 块:

  • core_start = i * 1200
  • core_end = min(duration, core_start + 1200)
  • audio_start = max(0, core_start - 5)
  • audio_end = min(duration, core_end + 5)
  • global_start/end = audio_start + local_start/end
  • midpoint = (global_start + global_end) / 2

只保留中点属于本块核心区间的分段;这是一条唯一归属规则,不增加模糊文本去重或重写识别结果。最终分段按 (start,end,text) 升序,TXT/SRT/JSON 继续由同一个结果对象生成。

5. 资源与失败安全

  • 暂存目录同时包含完整 FLAC 和最多一个固定名临时块;临时块写完、转写后立即删除。
  • 进度输出 正在转写分块 i/n 并立即刷新,便于资源采样关联块号。
  • 中断、FFmpeg 或 GPU 失败由现有外层 finally 清理整个暂存目录;块函数另有局部 finally,确保当前块先删除。
  • 不在 Python 中读取完整 FLAC 字节,不保存完整波形或频谱。
  • 正式输出冲突检查、相邻暂存、四文件提交和回滚逻辑不变。

6. 测试与验收

6.1 离线测试

  • 20 分钟阈值两侧;4 小时生成 12 个核心块。
  • 首块、内部块、末块的 5 秒重叠和裁边。
  • 边界中点唯一归属、全局偏移、排序和无重复序号。
  • 模型只加载一次;未指定语言时首块检测、后续复用。
  • 任意块失败时临时块和暂存目录清理。
  • 现有无音轨、FFmpeg 失败、输出冲突和禁止 CPU 降级回归。

6.2 真实回归

  1. 使用原 1193.64 s 视频走未分块路径,核对 705 段、四文件对应、源哈希不变。
  2. 在专属临时目录用只读源循环复用生成约 14400 s 测试副本。
  3. 完整运行采样 Python 与 FFmpeg 合计工作集、RTX 3090 显存、当前块号和临时块大小。
  4. 验证 exit 0、耗时 <=100 min、RAM <=12 GB、GPU <10 GB、临时块 <500 MB、前后三块峰值差、FLAC 时长、文本非空、SRT/JSON 可解析和全部 20 分钟边界。
  5. 保留 4 小时媒体与输出供 case_analysis.media_processor 只读复核。

7. 重跑与恢复

  • 不实现断点续跑;失败后换新输出目录整任务重跑。
  • 已存在任一正式输出即拒绝,不复用半成品。
  • 4 小时验收副本和结果只位于 dev/project-dev/tmp/DEV-PROJECT-INFO-LOCAL-MEDIA-TRANSCRIBE-LONG-VIDEO-OPT-20260801-001/

8. 高风险点与门禁

  • 边界中点比较错误会导致重复或漏段,必须由合成分段单元测试冻结。
  • 若未在每块 finally 删除临时块,会违反 500 MB 和单块上限。
  • 若后续块仍传 language=None,会造成语言漂移;测试必须检查调用参数。
  • 若短视频错误进入分块,19:54 基线会漂移;真实回归必须证明仍走单次路径。
  • 方案审核未通过前不修改代码;实现后按需求执行完整资源验收,再提交实现审核或请求方验收。

9. 当前状态

PENDING_INDEPENDENT_DESIGN_REVIEW