7.1 Whisper 转写


7.1 Whisper 转写

本节摘要:剧本里明明有全部台词,为什么还要跑一遍语音识别?因为转写的目标不是"拿到文字",而是拿到"实际发出的声音的时间戳",并验证 TTS 真正读了什么。本节先给出这三个理由,然后落地本地 Whisper:一张模型规格选择表(从 tiny 到 large-v3 的显存与速度口径),一个带台本注入的转写脚本写法示意;接着集中处理中文转写质量——同音错字、专名漂移、数字口径三大错型,用 initial_prompt 喂台本风格、用术语表做后校正;最后辨析 segment 与 word 两档时间戳粒度的取舍与长音频的漂移对策。模型行为随时演进,一切以官方仓库文档为准。

学习目标

  • 说清"已有台本仍要转写"的三个理由与各自产物。
  • 按显存、速度与中文质量口径选定 Whisper 模型规格。
  • 用台本注入与术语表后校正两道防线压低错字率。
  • 区分 segment 与 word 时间戳粒度并知道何时需要哪档。
  • 理解长音频时间戳漂移的原因与分段转写对策。

一、已有台本,为什么还要转写

第一个理由:字幕需要时间戳。台本知道每句话的内容,不知道每句话实际在第几秒——TTS 的实际时长、句间停顿、镜头间静音都会让它偏离估算。第二个理由:验证 TTS 实读内容。第 6.1 节的听检靠人,转写提供机器侧的对照:把成片音轨转回文字,与台本做差异比对,漏读、跳句、错读会直接暴露。第三个理由:适配临场改动。剪辑中删了一个镜头、补了一句气口台词,台本与成片脱节时,以转写结果为准重建字幕,比手工同步台本可靠。

转写的双重角色 台本(应然)──┐ ├──▶ 文本对账 ──▶ 差异清单 ──▶ 人工裁决:改台本还是重配 成片音轨 ──▶ ASR ──▶ asr_result.json(实然:文字+时间戳) │ └──▶ 7.2 字幕分段的时间轴来源 ​

二、本地跑法与模型规格

转写放在本地跑,理由与第 6.1 节本地 TTS 相同:音频不出网、边际成本为零、可重复。Whisper 家族的常用规格与经验口径如下(显存与速度为社区口径,以官方仓库为准):

规格 显存口径 速度口径 中文质量印象 适用
tiny / base 约 1 GB 极快 错字多 调试流水线
small 约 2 GB 快 勉强可用 快速预检
medium 约 5 GB 中 错字明显减少 短剧主力选择
large-v3 约 10 GB 慢 更稳 机器富余时的终稿

工程建议:开发期用 small 以下规格快速迭代,出片用 medium 或 large-v3 重跑一遍。转写脚本的关键技巧是把台本节选作为 initial_prompt 注入——它不改变音频,只引导模型用词与标点风格向台本靠拢,对专名与标点的稳定性格外有效。

# transcribe.py —— 本地 Whisper 转写(写法示意,参数以官方仓库为准) import json, whisper MODEL = "medium" PROMPT = "以下是本集台本节选,供统一用词与标点风格:雨夜便当店,陈师傅,林小满,订单备注。" def transcribe(audio="audio/final_audio.wav", out="build/asr_result.json"): model = whisper.load_model(MODEL) result = model.transcribe(audio, language="zh", initial_prompt=PROMPT, word_timestamps=True, condition_on_previous_text=False) segs = [{"start": round(s["start"], 3), "end": round(s["end"], 3), "text": s["text"].strip()} for s in result["segments"]] with open(out, "w", encoding="utf-8") as f: json.dump({"audio": audio, "model": MODEL, "segments": segs}, f, ensure_ascii=False, indent=2) print(f"转写完成:{len(segs)} 段 → {out}") if __name__ == "__main__": transcribe() ​

两个参数值得解释:word_timestamps 打开词级时间戳(第四节详述);condition_on_previous_text 关闭后每段独立解码,避免前面段的错认滚雪球式污染后续段。若追求更低显存与更快速度,faster-whisper 等推理加速实现可作替代,接口思路一致,以各自文档为准。

三、中文转写质量战:错型与两道防线

中文 ASR 的错误高度模式化,认得出错型才治得了:

错型 表现 例(示意)
同音错字 拼音相同或相近的字互换 台本"便当"转成"便裆"
专名漂移 剧中自造名词被换成常见词 "雨夜便当"转成"雨夜变蛋"
数字口径 汉字数字与阿拉伯数字不稳 "七幺幺"与"711"混用
标点缺失 长句无停顿标点 整段一逗到底
繁简混杂 个别字输出繁体 "后臺""纪录"混入

第一道防线是上文的 initial_prompt,把台本里的专名、数字写法喂进去,防患于然。第二道防线是后校正:转写结果出来后过一遍术语表,整词替换。两道防线一前一后,覆盖绝大多数错型。

# apply_glossary.py —— 术语表后校正:中文整词替换,英文加词边界 import json, re def load(path="build/glossary.json"): return json.load(open(path, encoding="utf-8")) def fix(text, glossary): for wrong, right in glossary.items(): if re.fullmatch(r"[A-Za-z0-9 .-]+", wrong): text = re.sub(rf"\b{re.escape(wrong)}\b", right, text) else: text = text.replace(wrong, right) return text def main(src="build/asr_result.json", dst="build/asr_fixed.json"): glossary = load() doc = json.load(open(src, encoding="utf-8")) changed = 0 for seg in doc["segments"]: fixed = fix(seg["text"], glossary) changed += fixed != seg["text"] seg["text"] = fixed with open(dst, "w", encoding="utf-8") as f: json.dump(doc, f, ensure_ascii=False, indent=2) print(f"后校正完成:改动 {changed} 段 → {dst}") if __name__ == "__main__": main() ​
# glossary.json —— 术语表:错写在前、正写在后(随听检与对账滚动补充) { "雨夜变蛋": "雨夜便当", "便裆": "便当", "后臺": "后台", "七幺幺": "711" } ​

注意:后校正只改文字,不动时间戳;替换词与原词长度悬殊时(如"七幺幺"换"711"),阅读节奏几乎不受影响,因为字幕是按时间轴显示的。

四、时间戳粒度:segment 还是 word

Whisper 默认输出 segment 级:每个自然段一条起止时间,粒度一到数秒,对"一句一条字幕"的短剧场景刚好够用。word 级则给出每个词的时刻,代价是转写更慢、输出更大。选型标准:若字幕分段的切分点都落在句读处,segment 级足够;若要做卡拉OK式逐字、或需要把一条长 segment 精确切给多个 cue,才需要 word 级。

另一个现实问题是长音频的累计漂移:半小时以上的连续转写,时间戳可能整体偏移零点几秒。对策是分段转写——按第 6.3 节锚点表把音轨切成镜头级片段分别转写,时间戳加上片段起点再拼回全局,漂移被限制在单镜头内。静音较多的素材可配合 VAD(语音活动检测)先剔除长静音,转写又快又稳。

五、产物与对账

asr_fixed.json 是本节的最终产物:segments 数组,每段有 start、end、text。它向两个方向输出:向下交给第 7.2 节做字幕分段;向旁用于与台本对账——把 segments 顺序拼接成一整段文字,与台本全文做序列对比,差异清单里每一处都要人工裁决:多数是 ASR 错字(补术语表),少数是 TTS 漏读(回第 6.1 节重跑该句),个别是剪辑期改动(更新台本归档)。对账把第 06 章与本章焊成一个闭环:声音、文字、时间三者互相印证。

本节要点回顾

  • 转写的三个理由:拿时间戳、验证实读内容、适配临场改动。
  • 模型规格按显存与质量口径选:开发用小规格,出片用 medium 起。
  • initial_prompt 喂台本风格在前,术语表后校正在后,两道防线治中文错型。
  • segment 级时间戳够用于句级字幕;长音频按镜头分段转写防漂移。
  • asr_fixed.json 双向输出:向下做字幕,向旁对账台本。

文字与时间戳都拿到了,下一节把它们加工成观众真正看到的字幕:按字数与停留规则切成 cue,套进样式模板,再决定烧进画面还是外挂交付。

作者与出处
原作者:灏天文库
整理人: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天文库 转发
评论区 (0)
U