Whisper语音转写实战:从环境搭建到批量出稿的完整指南
1. 手动整理一小时的痛,和 Whisper 给我的转机
先说说我为什么会专门写这篇 Whisper 语音转写实战。我手里头有大量音频要处理:每周至少两场客户访谈、一期播客、还有零零散散的会议录音。以前靠的是最原始的办法——听一句暂停一下,把重点敲进文档里。一小时的对谈,我平均要花三到四个小时才能理出一份还算能看的文字稿,遇到口音重、语速快的受访者,那简直是一场灾难。后来我试过各种“智能转写”在线服务,要么按分钟收费贵得肉疼,要么免费额度只够转三五分钟,要么音频传上去之后等半天才出结果,准确率还忽高忽低,关键数据一旦听错,返工比手动整理更崩溃。
直到我发现了 Whisper。如果你也在热搜里看到“whisper是什么”这个词,不用绕弯子,Whisper 就是 OpenAI 开源的自动语音识别(ASR)模型。它的核心本事是干两件事:把语音变成文字,以及把任意语言的语音翻译成英文输出。和那些云端服务最大的区别是,它完全开源,可以免费下载,在本地跑,录音文件不用上传到任何人的服务器,处理多少个小时的音频都不额外花钱,只要你的电脑扛得住。从我的实际体验来说,它的中文识别能力在开源模型里是第一梯队,对大多数普通话、方言口音和背景噪音的容忍度相当高。
这篇文章适合谁看?如果你和我一样,需要定期把访谈、会议、讲座、播客、课堂录音转成文字稿,或者在剪视频时需要给素材生成字幕,那你完全可以照着这篇文章从零开始搭一套自己的转写流水线。我会从环境搭建、模型选型、命令行参数逻辑、批量出稿脚本、坑点排查一直讲到最终的成稿排版。整篇文章不会只丢给你几个命令,而是告诉你每一个环节为什么要这么选、这么配,遇到问题的时候从哪里入手排查,这样你才能有本事把流程真正跑通,而不是下载完就卡在第一个报错上。
2. 装环境的核心决策:算力、依赖和模型怎么选
2.1 先想清楚你的机器能跑到哪一步
很多人一上来就问“用哪个模型最强”,这个问题其实得反过来问——你的电脑扛得住哪个模型。Whisper 的模型有六个档位:tiny、base、small、medium、large-v1、large-v2,后来社区里最常用的多是 large-v3。我的结论很直接:如果你要转中文而且是长期用,直接上 large-v3,哪怕慢一点也值得;如果只是偶尔转个把小时,或者机器实在不行,small 是最低底线。
我第一台用来跑 Whisper 的电脑没有独显,是一颗英特尔 8 核 CPU,16G 内存。当时天真地想直接跑 large,结果一条五十分钟的音频跑了两个多小时,转出来的内容虽然质量高,但这个速度根本没法当日常工具用。后来换了台带 RTX 3060 12G 显存的机器,情况才真正改善。这里先给一份我实测下来大致靠谱的性能参考,不同机器会有差异,但量级不会偏差太大:
| 模型 | 参数规模 | CPU 转写速度(约) | GPU 转写速度(约) | 中文识别效果 | 我的建议 |
|---|---|---|---|---|---|
| tiny | 39M | 约 4-5 倍实时 | 极快 | 很差,仅能听懂大部分单字 | 不建议 |
| base | 74M | 约 2-3 倍实时 | 极快 | 能听出短句,长句易错 | 玩具级别 |
| small | 244M | 约 0.8-1 倍实时 | 极快 | 日常对话能看,但专有名词错得多 | 最低可用档 |
| medium | 769M | 约 0.3-0.5 倍实时 | 约 2-3 倍实时 | 明显提升,口语能听懂八成 | 面向中文的低显存友好档 |
| large-v3 | 1550M | 非常慢 | 约 1 倍实时 | 个人认为开源里中文最好的一档 | 长期使用推荐 |
这里的“倍实时”是指处理时长和音频时长的比值。比如 1 倍实时,就是一条 60 分钟的音频大约需要 60 分钟处理;2 倍实时,就是 60 分钟音频大约 30 分钟处理完。CPU 跑 large 你可以直接劝退自己。GPU 显存方面,我的经验是:medium 需要大概 5G 显存,large 系列建议至少 10G 显存,8G 显存转 long 音频会偶尔爆显存,但配合后面讲的分段参数也能跑。如果你的机器只有 4G 显存,就老老实实在 small 和 medium 之间做选择。
2.2 依赖安装顺序和最容易翻车的点
安装 Whisper 本身非常简单,三样东西:Python、ffmpeg、whisper 包。但很多人卡住不在 whisper 本身,而在 ffmpeg。Python 请用 3.9 到 3.11 版本,3.12 及以上目前有些依赖兼容性问题,我踩过一次,不建议在环境上冒险。
ffmpeg 是处理音频和视频的瑞士军刀,Whisper 依赖它将各种格式的音频解码成模型能处理的格式。Windows 用户最容易在这里翻车:直接去 ffmpeg 官网下载编译好的 Windows 压缩包,解压后把 bin 目录路径加到系统环境变量 Path 里,然后重新打开命令行验证。macOS 用户用brew install ffmpeg,Ubuntu/Debian 用户用apt install ffmpeg。装完一定要在终端跑一下:
ffmpeg -version如果输出版本信息,说明解码工具就位了。我见过太多人跳过这步直接装 Whisper,最后执行转写时报FileNotFoundError: [WinError 2] 系统找不到指定的文件,其实就是 ffmpeg 不在 PATH 里。
接下来是主体安装:
pip install -U openai-whisper装完试着查一下版本:
whisper --help能正常打印帮助信息,环境就算齐了。第一次真正转写的时候,Whisper 会从网上下载模型文件,常用的 large-v3 模型文件将近 3G,第一次运行会卡在“下载中”很久。如果你在这一步经常失败而不是速度慢,先找找是不是网络环境问题。我的做法是先把模型文件下载到本地缓存目录,再让 Whisper 离线加载。
2.3 第一次跑通 demo,别上来就处理大文件
环境装好之后,强烈建议先拿一小段音频做测试。录音文件可以是 mp3、m4a、wav,OpenAI 官方支持的格式还挺多。最基础的调用方式:
whisper 测试音频.mp3 --model small --language Chinese --output_format txt这条命令的意思是用 small 模型处理这个文件,明确告诉模型内容是中文,结果输出成 txt 格式。等它跑完,同目录下会生成一个“测试音频.txt”文件,里面就是转写出来的文字。第一次跑的时候,重点不是看准确率,而是确认整个链路是通的:音频解码成功、模型成功加载、结果正常落盘。
很多人问为什么不直接上 medium 或者 large 测试。原因很简单:第一次跑的时候,你还不确定自己的机器性能怎么样,也不知道显存够不够,先用 small 把流程摸顺,再换大模型,成本最低。我记得我第一次直接用 large 测试,结果中途显存爆掉程序崩溃,还以为是软件装错了,回头排查半天才发现是显存不足,这个冤枉时间花得太不值了。
3. 命令行参数背后的逻辑:先弄懂再跑大批量
Whisper 的命令行参数非常多,但日常高频使用的其实就十来个。为什么我要单独拿出一章讲参数?因为批量转写的时候,参数配错一个地方,几十个文件全部白跑,那个时间成本真的是血泪教训。下面把每个关键参数的意义和最佳实践拆开说清楚。
3.1 语言参数千万别省
直接用whisper audio.mp3不加任何参数也能跑,模型会自动判断音频里是什么语言。但自动检测有一个概率问题,尤其是音频开头有音乐、静音、咳嗽声的时候,模型有可能猜错语言。一旦猜成别的语言,输出的中文内容就会夹杂大量英文音译词,比如“环境”变成“environment”。所以我的习惯是,明确知道音频语言是中文的时候,一定要加--language Chinese,这能让模型在解码时把搜索空间限定在中文里,错误率明显下降。
如果你实在不知道音频是什么语言,可以先不加语言参数跑一小段片段,看到开头输出的 language 标签再手动指定。Whisper 支持的语言代码列表很长,中文就是Chinese,英文是English。
3.2 输出格式决定了你的后续处理方式
--output_format支持这么几个值:txt、srt、vtt、tsv、json。很多人只选一个,但我的建议是直接全要:
whisper audio.mp3 --output_format allall会同时生成全部五种格式。我问过自己为什么要这么干,其实后面的处理场景不一样:txt 用来做文字稿初稿,srt 直接能当视频字幕用,json 里面有每个词的时间戳和置信度,可以做二次加工和说话人分段分析,tsv 是表格形式方便导入 spreadsheet。所以别省这个参数,反正生成五种文件的计算成本是一次性的。
3.3 时间戳细粒度:词级还是行级
默认情况下,Whisper 输出的 srt 是按句子级别切分时间戳的,一行字可能跨越好几秒。如果你只需要看懂内容,足够用了。但如果要拿字幕去剪映、PR 里对齐视频,你可能希望时间戳更准确一些。这里有一个参数叫--word_timestamps True,开启后会把时间戳精细到每个词。代价是处理时间会增加一些,而且对中文这种没有天然空格分隔的语言,词级切分逻辑会有点奇怪,输出的词可能不是一个完整词语。我实际用下来的结论是:做字幕用句子级就够,做音频剪辑对齐轨道才需要词级。大多数情况下默认的句子级即可,别盲目追求精细。
3.4 分段长度和上下文的关系
Whisper 内部会把长音频切成一段一段处理,默认段长 30 秒。--condition_on_previous_text这个参数默认是开启的,意思是处理后面段落的时候,会把前面段落的文字也作为上下文参考,这样长文档的转写连贯性会好很多。但这也带来一个问题:如果前面段落识别错了,后面可能会受错误内容的“诱导”跟着错。我实测下来,保持默认开启是利大于弊的,因为连贯性收益远大于个别错误传递。真正需要关掉它的场景是音频内容主题跳变非常剧烈的,比如开会时突然有人插进来讲了个完全无关的话题,这时上下文不仅没有帮助,反而成了干扰。不过这种场景属于少数,不用一上来就动它。
3.5 半精度和初始提示词
--fp16 True是指在支持 fp16 的 GPU 上启用半精度计算,能显著提升速度且几乎不损失准确率。CPU 上跑就不要开这个参数,反而更慢。还有一个非常实用但很多人忽略的参数:--initial_prompt。你可以用一段文字告诉模型“这个音频是讲计算机技术的,会出现 CUDA、Python 这类词”,模型在转写时会把注意力偏向这些领域。我之前处理一批人工智能相关的访谈,在 initial_prompt 里塞了一段包含大量专业术语的描述,专有名词的识别明显好了不少。这个问题后面在坑点章节里会详细说。
我把这些高频参数整理成一个速查表,方便你直接抄:
| 参数 | 作用 | 我的建议值 |
|---|---|---|
--model | 指定模型大小 | 中文首选large-v3 |
--language | 指定音频语言 | 明确语言必填 |
--output_format | 输出格式 | 用all |
--fp16 | 半精度加速 | GPU 用True,CPU 用False |
--word_timestamps | 词级时间戳 | 默认关闭 |
--initial_prompt | 初始上下文提示 | 按领域填写 |
--verbose | 打印过程信息 | 批量时用False |
--task | 转写或翻译 | 一般用transcribe |
4. 批量出稿流水线:一个循环搞定几十个音频
命令行一条条跑,偶尔处理一两个文件没问题,但真正要批量出稿时,你会发现用脚本来做才是正解。我有一个文件夹每周都会新增四五条访谈录音,命名规则是“客户名_日期.m4a”,我需要把这些全部转成文字稿和字幕。手工一条条复制命令效率太低,所以我写了一个 Python 脚本,把批量处理流程固化下来。
4.1 第一步:录音文件先统一成 16kHz 单声道 wav
这一步很多教程不会重点讲,但我的经验是它非常值得做。Whisper 虽然能直接读 m4a、mp3,但不同格式的采样率和声道数会影响处理效率。尤其是手机录音,有的是 48kHz 立体声,有的还有奇怪的编码后缀。先用 ffmpeg 统一转成 16kHz 单声道 wav,处理速度会快不少,而且能规避一些 ffmpeg 解码特定 mp3 编码时的兼容问题。
import subprocess import os input_path = "a.m4a" output_path = "a_16k.wav" cmd = [ "ffmpeg", "-i", input_path, "-ar", "16000", "-ac", "1", "-y", output_path ] subprocess.run(cmd, check=True)-ar 16000是采样率降到 16000Hz,-ac 1是转成单声道,-y表示覆盖已有文件。为什么是 16kHz?因为 Whisper 训练时使用的就是 16kHz 采样率,这是它最熟悉的输入格式,相当于把食材切成它最习惯的大小再下锅,当然更顺滑。
如果你不想在脚本里再调 subprocess,也可以直接在 Whisper 转写前用 Python 库实现同样的转换,但 ffmpeg 是最稳的,建议保留。
4.2 第二步:批量遍历目录并调用 Whisper
这一步是脚本的核心。我用pathlib遍历指定目录下的所有音频文件,过滤出扩展名是.m4a、.mp3、.wav的文件,然后逐个调用whisper.transcribe()。为什么不直接调命令行而是用 Python API?因为命令行每次调用都要重新加载模型,处理几十个文件,模型反复加载的开销非常可观。用 Python API 可以把模型常驻内存里,处理完一个接着处理下一个,速度成倍提升。
import whisper from pathlib import Path import json model = whisper.load_model("large-v3") audio_dir = Path("./audio_files") output_dir = Path("./output_files") output_dir.mkdir(exist_ok=True) audio_extensions = {".m4a", ".mp3", ".wav", ".flac", ".m4b"} audio_files = [f for f in audio_dir.iterdir() if f.suffix.lower() in audio_extensions] failed_files = [] for audio_file in audio_files: print(f"正在处理: {audio_file.name}") try: # 直接传原文件,Whisper 内部会自动加载 ffmpeg 解码 result = model.transcribe( str(audio_file), language="Chinese", fp16=True, verbose=False ) # 生成纯文本 txt_path = output_dir / f"{audio_file.stem}.txt" with open(txt_path, "w", encoding="utf-8") as f: f.write(result["text"]) # 生成带时间戳的 srt 字幕 srt_path = output_dir / f"{audio_file.stem}.srt" write_srt(result["segments"], srt_path) print(f"完成: {audio_file.name} -> {txt_path.name}") except Exception as e: print(f"失败: {audio_file.name} - {e}") failed_files.append(str(audio_file)) with open(output_dir / "failed_list.txt", "w", encoding="utf-8") as f: for item in failed_files: f.write(item + "\n")注意model.transcribe()里我显式传了language="Chinese",这是为了避免批量处理时每一条音频都让模型重新做语言检测。还有一个细节是fp16=True,前提是你的 GPU 支持,如果你用的是 CPU,这里一定要改成False,否则会报错或者更慢。
4.3 第三步:从 segments 生成可读的 SRT 字幕
上面的脚本里我调用了一个write_srt()函数,这个函数需要自己实现。SRT 文件的格式是“序号 + 时间轴 + 文本”,时间轴的格式是小时:分钟:秒,毫秒。从 Whisper 返回的segments列表里可以拿到每一句的start和end字段,单位是秒,需要转成 SRT 格式:
def format_timestamp(seconds): millis = round(seconds * 1000) hours = millis // 3600000 minutes = (millis % 3600000) // 60000 secs = (millis % 60000) // 1000 ms = millis % 1000 return f"{hours:02}:{minutes:02}:{secs:02},{ms:03}" def write_srt(segments, output_path): with open(output_path, "w", encoding="utf-8") as f: for i, seg in enumerate(segments, start=1): f.write(f"{i}\n") f.write(f"{format_timestamp(seg['start'])} --> {format_timestamp(seg['end'])}\n") f.write(f"{seg['text'].strip()}\n\n")这个函数生成的 srt 文件可以直接拖进剪映或 PR。我刚开始做字幕时踩过一个坑:直接拿 Whisper 的 txt 输出当字幕,发现时间轴完全对不上,因为句子被自动合并了。后来才意识到必须用 segments 而不是 text 字段。这就是理解和会调用的区别。
4.4 第四步:给交付方看的文稿怎么生成
客户的访谈成稿和字幕的需求不太一样。字幕要求句子短、口语化保留;成稿要求尽量通顺、去掉口癖、分段清晰。所以我一般会从result["segments"]里把每句话抽出,再按说话场景拼成段落,而不是直接使用 Whisper 输出的整段文字。比如把每次较长的停顿视为一个新段落开始:
def write_markdown(segments, output_path): with open(output_path, "w", encoding="utf-8") as f: current_paragraph = [] last_end = 0 for seg in segments: # 如果句间间隔超过 2 秒,则另起一段 if current_paragraph and seg["start"] - last_end > 2.0: f.write("".join(current_paragraph) + "\n\n") current_paragraph = [] current_paragraph.append(seg["text"].strip()) last_end = seg["end"] if current_paragraph: f.write("".join(current_paragraph) + "\n\n")这个逻辑的目的是:Whisper 本身不做段落划分,但通过安静间隙判断,能很自然地划分出说话人和话题切换,比单纯输出一大坨文字要友好得多。你如果后面还要人工润色,这种段落结构也省时间。
4.5 批量跑的时候要不要并行
脚本写好后,很多人会问能不能多线程并行处理多个文件。我的建议是:GPU 用户不要并行,CPU 用户也不要并行。GPU 上并行处理多个文件并不会让模型吃掉更多显存去同时跑多个任务,反而会因为任务切换造成资源浪费。CPU 上并行确实能快一些,但 Whisper 的解码过程线程安全方面有坑,多线程容易出诡异问题,不值得。稳妥的办法是串行处理队列。我实测处理十条 40-60 分钟的音频,large-v3 + RTX 3060,串行跑完大约耗 7-8 个小时,晚上挂机跑,早上起来收稿,完全能接受。
5. 实测三个月踩过的坑:环境、中文口语和长音频
5.1 安装期的三大坑,每条都是真实翻车记录
先说安装期。第一大坑是 Python 版本兼容性,我用 Python 3.12 装了最新版 Whisper,跑import whisper没问题,但实际调用时报了TypeError,一看是torch的兼容性问题,当时最新的 PyTorch 还不支持 3.12,只能退到 3.10 才消停。这个坑后来随着 PyTorch 更新逐渐少了,但如果你遇到诡异的 error,先怀疑 Python 版本。
第二大坑是 ffmpeg 路径。我一度以为 Windows 上装了 ffmpeg 就行,结果在 IDE 里跑脚本时一直报找不到 ffmpeg,因为 IDE 自带的环境变量和命令行不共享。最后我在脚本里显式指定了 ffmpeg 路径才彻底解决:
import whisper whisper.load_model("base") # 如果 ffmpeg 不在 PATH 里,可以用这个方式指定但 OpenAI 的 Whisper 包没有直接暴露设置 ffmpeg 路径的参数,我的排查思路是确保 ffmpeg 全局可用,同时在环境变量里单独加一份路径,另外再检查一次 Python 进程加载的 PATH。这个方法比较绕,但确实能解决 IDE 和命令行不一致的问题。
第三大坑是第一次下载模型卡住。也就是前文说的,模型文件太大,默认从 OpenAI 的服务器下载,网络条件不好的时候经常中断。后来我用国内镜像源或者手动把模型文件放到缓存目录才解决。我这里不展开讲具体的镜像地址,因为镜像库变动频繁,你只要明白原理:先下载好模型文件,然后在运行时设置环境变量指向本地缓存目录,可以彻底避免下载失败的问题。
5.2 中文口语的翻车现场:不是 Whisper 不够强,是你没喂对它
我对中文识别的观察非常细。Whisper 对普通话的识别整体已经相当好,但口语场景里还是有几个典型的毛病。
第一个是专有名词和生僻词。人名、地名、公司名、产品名,尤其是不常见的那种,经常会被听成发音相近的常见词。比如“飞书”变成“非书”,“飞猪”变成“飞猪”这种稍微好点,但“还是那个 Keystone 项目”会变成“还是那个K型项目”。解决这个问题的办法就是前面说的--initial_prompt。我的做法是在处理每一批音频前,根据当前项目的主题整理 50 到 100 字的关键词描述,塞进 initial_prompt 里。实测下来,对于包含领域专有名词的音频,这种做法的准确率提升非常明显。
第二个是语气词和口癖。Whisper 会把“嗯”“啊”“那个那个”这些词原原本本地转写出来。对字幕来说这是好事,能保留说话人停顿的感觉;但对交付给客户的成稿,这就是噪音。我的处理方法是在成稿脚本里加一个语气词过滤:
import re noise_words = ["嗯", "啊", "那个", "就是说", "然后呢", "对吗"] def clean_text(text): # 去掉开头和结尾的语气词 text = text.strip() for w in ["嗯", "啊"]: text = re.sub(rf"^{w}[,.,。]?", "", text) return text别指望代码能完全清理干净,但能把 70% 的明显口癖去掉,剩下的交给人工润色。
第三个是数字和英文混排。中文访谈里经常出现“我们 2019 年的时候”“Python 那个库”这种中英数字混排。Whisper 对这些内容的处理基本靠谱,但偶尔会把英文单词转成中文音译,比如“API”变成“A P I”或者“接口”,“CPU”变成“中央处理器”,这取决于上下文。如果你需要保留原始英文,可以在 initial_prompt 里写上“请保留英文原文和技术缩写”,会有一定缓解。
5.3 长音频处理:两小时会议录音的分配策略
一条两小时的音频如果直接整个丢给 Whisper,即使显存够,也容易出现一个问题:中途如果发生程序崩溃,前面的转写结果全部丢失。我的处理方式非常明确:大文件先按 30 分钟一段切分,再逐段处理。虽然 Whisper 内部本来就有分段机制,但从外部切分有额外的好处——每段独立处理,避免了一段错误文本通过上下文条件传递给下一段,而且万一某一段失败,只需要重新转那一段就行,不用整条重跑。
切分也可以交给 ffmpeg:
ffmpeg -i 长音频.mp3 -f segment -segment_time 1800 -c copy 分段_%03d.mp3-segment_time 1800是每 1800 秒切一段。切分后按前面的批量脚本处理每段,最后再用脚本把所有 txt 合并。这个方案的缺点是有可能在切分点处把一个句子拦腰截断,Whisper 按整段理解的时候连贯性稍差。不过在实际处理中,我很少遇到切分点正好落在语义关键位置的情况,整体收益远大于损失。
另外一个容易忽略的问题:会话中不同说话人。Whisper 不区分说话人,它只会一股脑把所有声音转成文字。如果你需要知道某句话是谁说的,就得借助说话人分离工具,比如 pyannote。但这属于进阶玩法,两头同时跑会非常吃资源且配置复杂。我的做法是:先用 Whisper 转出完整文字稿,再在人工校对时根据音色和上下文手动标注说话人。对大多数场景来说,这个成本已经可以接受。
5.4 背景音乐、掌声和多人同时说话的干扰
访谈里经常有背景音乐,尤其播客的开头和结尾。Whisper 在音乐段落的表现是:要么生成长长的空白片段,要么输出乱写的“歌词”。解决方案不是调参数,而是预处理:用 ffmpeg 把音频里的音乐片段剪掉,或者至少把音乐声压低。最省事的办法是在脚本里自动检测静音段,静音段超过一定长度就从有效音频里剔除,这样背景音乐处的无效转写会少很多。
还有多人同时说话的情况,这个目前所有自动转写工具都很难处理,Whisper 也不例外。它会把两个人重叠的声音合并成一句,输出结果是不可用的。我在处理这种素材时,一般会在访谈开始前就和参与者约定“尽量别抢话”,这是最有效也最便宜的解决办法。技术上我还没有找到特别好的办法,也欢迎有经验的朋友留言交流。
6. 从转录到可交付成稿的最终一步:降噪、排版和字幕
6.1 音频预处理:转写之前先好好洗一遍
声音质量直接决定了转写效果。同样一段语音,用 iPhone 在安静房间录的,和用会议室麦克风录的,Whisper 的识别准确率可以差出十几个百分点。如果你能做一点预处理,后续校对时间能省非常多。
最常用的预处理是高通滤波。录音里常见的人声低频噪音、空调嗡嗡声、空调风声,可以通过高通滤波把 80Hz 以下的声音切掉,人声几乎不受影响。
ffmpeg -i 原音频.wav -af "highpass=f=80,lowpass=f=8000" 处理后的音频.wav高通 80Hz 以下,低通 8000Hz 以上,这样能有效过滤掉大部分环境噪音,同时保留人声主要频段。这个处理对转写效果的影响是正向的。
如果录音里有明显的背景人声或电视声,可以试用降噪工具。开源圈比较火的有 NVIDIA 的 Riva 和 RNNoise,但需要单独安装。早期我用过一个简单的 DSD(Deep Speech Denoiser)方案,效果不稳定,后来放弃了。我的经验是:先去物理环境里减少噪音源,比任何软件降噪都管用。如果录音质量实在太差,别指望 Whisper 能创造奇迹,人工重录往往是最省时间的。
6.2 文稿的排版:让客户一眼看懂的逻辑
转写完成后,直接拿 Whisper 的 txt 去交付,很多客户会不满意,因为满屏语气词、半截句子、缺少分段会让阅读体验非常差。我给自己定了一个交付标准:每一段文字至少经过一次润色,去掉明显口癖,按话题重新换行,重要结论和行动项加粗标记。润色不是改写,不要改变说话人原意,只是把口语变成书面语。
具体到排版,我习惯把一段话控制在 3 到 5 行内,每句话之间空行。如果是访谈稿件,还会在每段前加“问/答”标记。对于有明确结构的会议录音,我会加“议题 1”“议题 2”这样的标题,方便领导快速定位。这些小改动看着不起眼,但能显著提高稿件被阅读的可能性。
6.3 字幕处理:从 srt 到剪映的实用流程
如果你做视频,Whisper 的 srt 输出可以直接导入剪映。剪映支持直接导入 srt,导入后字幕会自动落在时间轴上。导入前最好检查一下 srt 的编码,建议 UTF-8 无 BOM,有 BOM 的中文 srt 在某些版本的剪映里第一行字幕会变成乱码。万一遇到这种情况,用文本编辑器另存为 UTF-8 无 BOM 即可。
剪映导入 srt 后,我还习惯统一字幕样式:字体、描边、字号、位置。Whisper 输出的每条字幕可能长短不一,短的只有一两个字,长的可能是一整句话。剪映里有“批量修改样式”的功能,可以一次性统一风格,不用一条条改。
6.4 一段完整流程的时间成本,算给你看
最后给你算一笔账。一条 60 分钟的访谈录音,我的完整流程是:预处理转 16kHz wav 大约 1 分钟,Whisper large-v3 在 RTX 3060 上转写大约 60-70 分钟,清洗语气词和排版大约 15 分钟,人工校对关键内容大约 30 分钟,总计约 2 小时左右。相比之下,我手动整理时一条 60 分钟的访谈至少需要 4 到 5 小时。省下的时间不是一点点,而且我不需要再付给在线转写服务按分钟计算的费用。这套流水线我已经稳定用了大半年,期间也踩过不少坑,但把坑都填平之后的收益非常可观。
我个人的建议是,不要一味追求模型最大、参数最全,而是根据你自己的素材特点、机器性能、交付要求去组合一套最顺手的流程。先跑通一条最基本的链路,再慢慢往里面加预处理、加排版、加说话人标注,每加一个环节都要问自己“这个环节真的帮我省时间了吗”,而不是“这个功能看起来很炫”。工具是拿来用的,用起来顺、交付得起,才是最重要的。