2 小时录像 → 可检索图文纪要:一条不重编码的本地流水线

视频ffmpeg语音转写视频章节2026-10-05

2 小时录像 → 可检索图文纪要:一条不重编码的本地流水线

0. 先定产物,再动手

很多人拿到录像的第一反应是「打开剪辑软件」。停下。会议、课程、访谈这类长视频,你要的通常不是一段剪好的片子,而是三样东西:

  • notes.md —— 带 [00:42:10] 时间戳的图文纪要,可以全文搜索
  • chapters.txt —— 章节元数据,写回 MP4,播放器进度条上能直接跳
  • audio.srt —— 逐句字幕,备用
这三样全部从原片派生,视频流一次都不重编码。全程 -c:v copy。

1. 目录与工具

work/
├── raw/      # 原始录像,只读,永不修改
├── audio/    # 抽出的音轨
├── asr/      # 转写结果
└── out/      # 最终产物

工具只需要两个:ffmpeg(6.0+,含 ffprobe)和 whisper.cpp(本地转写,音频不出机器)。

2. 体检:先 ffprobe,别急着转码

ffprobe -v error \
  -show_entries stream=index,codec_type,codec_name,channels,sample_rate,channel_layout,duration \
  -of default=noprint_wrappers=1 raw/meeting.mp4

重点看三件事:

  • 音轨数量。 线上会议录制常见双音轨(本地麦克风 + 系统声)。只抽第一条,对方说的话全丢。
  • 声道布局。 标着 stereo,但左右声道其实是两个不同的人——这不是立体声,是「双单声道」。直接 downmix 会把两个人叠在一起,转写质量断崖下跌。
  • 时长是否一致。 容器时长和音轨时长差几秒很常见,后面所有时间戳要以音轨为基准。
判断「双单声道」的土办法:抽前 30 秒,单独听左、单独听右。

ffmpeg -i raw/meeting.mp4 -t 30 -af "pan=mono|c0=c0" -y /tmp/L.wav
ffmpeg -i raw/meeting.mp4 -t 30 -af "pan=mono|c0=c1" -y /tmp/R.wav

如果两边是不同的人,走分轨路线,别 downmix:

ffmpeg -i raw/meeting.mp4 -map 0:a:0 -af "pan=mono|c0=c0" \
  -ar 16000 -c:a pcm_s16le -y audio/ch0.wav

分别转写、分别标记说话人,最后按时间戳合并。这一步做对,后面省两小时。

3. 抽音频:16k 单声道 PCM

ffmpeg -i raw/meeting.mp4 -vn -ac 1 -ar 16000 -c:a pcm_s16le -y audio/full.wav

要点:

  • 16000 Hz 是 ASR 的标准输入,再高没有收益,只会拖慢转写。
  • 用 pcm_s16le,别用 mp3/aac,有损编码引入的伪影会变成转写错误。
  • 这一步不要做响度归一化。 先看电平:
ffmpeg -i audio/full.wav -af volumedetect -f null - 2>&1 | grep mean_volume

mean_volume 低于 -30 dB 才考虑统一加增益,用 -af volume=12dB。不要上 loudnorm,它会改变时间轴上的动态,对识别没有帮助,还可能让 whisper 的时间戳变差。

4. 转写:先跑 5 分钟试片

whisper-cli -m models/ggml-large-v3-turbo-q5_0.bin \
  -f audio/full.wav \
  -l zh \
  --output-srt --output-json \
  -of asr/full \
  -t 8

正式跑之前必须试片:

ffmpeg -i audio/full.wav -t 300 -c copy -y audio/probe.wav

试片要确认的只有一件事:专有名词。产品名、人名、缩写被听错是最常见的问题。把试片里错的词整理成一份替换表,正式转写后用 sed 批量改——比用 prompt 提示更快、更可控、更可复现。

时间预算:2 小时音频,large-v3-turbo 量化版在 8 核 CPU 上约 20–35 分钟,M 系芯片约 8–15 分钟。

5. 章节切分:两个信号叠加

不要凭感觉切。只用两个客观信号。

信号 A:静音间隔。

ffmpeg -i audio/full.wav -af silencedetect=noise=-32dB:d=1.2 -f null - 2>&1 | grep silence_end

输出形如 silence_end: 1843.21 | silence_duration: 2.14。

信号 B:转写文本里的转折词。 从 SRT 里抓这些词最近一次出现的时间戳:接下来、第二个问题、我们看下一、好,那、总结一下、最后。

切分规则,写成脚本跑:

  • 候选边界 = 静音结束点 ∩ 转折词时间戳 ±15 秒
  • 章节最短 3 分钟。短于 3 分钟的候选点直接丢掉,否则会切出 40 个碎章,比不切还难用
  • 首章从 0 开始,末章到音轨末尾
跑完应该得到 8–15 个章节。这个粒度在播放器进度条上刚好一眼看清。

6. 写 chapters.txt 并烧回 MP4

;FFMETADATA1
title=产品评审会 2026-10-05

[CHAPTER] TIMEBASE=1/1000 START=0 END=372000 title=00:00 开场与议程确认

[CHAPTER] TIMEBASE=1/1000 START=372000 END=1154000 title=06:12 上季度数据复盘

[CHAPTER] TIMEBASE=1/1000 START=1154000 END=2100000 title=19:14 定价方案分歧

时间单位是毫秒,START/END 来自上一步的秒数 ×1000。

写回原片,不重编码:

ffmpeg -i raw/meeting.mp4 -i out/chapters.txt \
  -map_metadata 1 -map 0 -c copy -y out/meeting_chaptered.mp4

两个参数缺一不可:-map_metadata 1 用第二个输入(章节文件)的元数据覆盖;-map 0 保证原片所有流都被拷过去(多音轨、字幕轨一个都不能少)。

校验:

ffprobe -v error -show_chapters -of default=noprint_wrappers=1 out/meeting_chaptered.mp4

7. 生成可检索纪要

从 SRT 出发,按章节边界聚合,每章保留 3–5 条要点句。挑句规则不用 AI 也够用:

  • 单句长度 > 12 字
  • 不以「嗯 / 那个 / 就是说」开头
  • 含数字、日期、人名,或决策动词(决定 / 确认 / 延期 / 由谁负责)
  • 同一章内按时间排序,最多 5 条
输出格式:

## 06:12 上季度数据复盘
[▶ 06:12](meeting_chaptered.mp4#t=372)
  • 09:40 上季度转化率 3.2%,环比下降 0.4 个点
  • 12:05 决定把投放预算从 A 渠道切 30% 到 B 渠道
  • 15:30 数据口径有争议:是否含退款单,待财务确认
`#t=372` 是秒数,VLC、IINA、浏览器原生 `<video>` 都认这个锚点,点一下直接跳。整份 Markdown 丢进笔记软件就能全文搜索。

8. 三条避坑

  • 不要在 -c copy 之外对原片做任何处理再写章节。 一旦重编码,时间戳基准可能变,章节会整体偏移。
  • 不要把 SRT 时间戳直接当章节边界。 一句话一行的粒度太碎,章节必须是「话题级」的。
  • 不要删原始音轨。 转写必然有错,唯一的真相来源是音频;纪要和字幕都只是索引,不是存档。
整条流水线跑顺之后,2 小时录像大约 40–60 分钟出全部产物,其中九成时间机器在跑。你只需要在两处各花 5 分钟:确认专有名词替换表,审一遍章节标题。
PREMIUM

需要完整版教程?

包含详细步骤、视频演示、提示词模板和可下载资料包。微信支付即时获取。

购买完整版 ¥29.90