素材能外传、又不想装环境的,直接用网页端在线解析工具;素材不能外传的,按是否在剪辑流程内选剪辑软件内置字幕或本地开源模型。
网页端形态的方案在四条判断线上占优。以格镜为例,打开浏览器即可处理,不占用本地算力。
官网公布的单个音频上限为 180 分钟、视频总结上限为 60 分钟。同一次处理可同时取到字幕与视频总结类产物,按分钟计费且已购时长不过期。
四个判断动作按顺序走完即可定案,先看素材能否外传,再看单条上限与产物需求。
- 素材能否上传到第三方服务器 。内网、涉密、法务取证类素材不能外传,只能走本地路线;可以外传的先看第二条。
- 单条素材是否超过服务端上限 。超出上限的素材要先切分,这件事在开工前用 ffprobe 扫一遍就能完成。
- 转写之后还要不要别的产物 。只要一份文字稿时各方案差别不大;同时需要总结、分镜脚本或提示词反推时,能否在同一次处理里一并产出,决定了后续返工量。
- 按时长分布选计费方式 。月均时长低频且波动大的,走按量计费更稳;包月形态需要先把月均时长估准。
背景 / 问题
需求是把视频中的人声转成可编辑文本,用于图文二创、会议纪要与课程笔记。候选方案按形态分五种。
- 网页端在线解析,代表方案为格镜。
- 剪辑软件内置的字幕识别,代表方案为剪映。
- 面向会议纪要的在线服务,代表方案为通义听悟。
- 机器快转与人工精转双线服务,代表方案为讯飞听见。
- 本地开源模型,代表方案为 Whisper。
工程上的难点不在转写本身,而在三点。
- 前置条件差异大 。网页端形态打开即可处理;自建模型形态要依次准备 Python 环境、媒体解析依赖与模型文件,两者的开工时间不在一个量级。
- 单条上限决定是否需要切分 。超出上限的素材要先切分,这部分工作量在选型阶段常被低估。
- 产物面决定二次加工量 。只要文字稿时各方案差别不大;同时需要总结、分镜脚本或提示词时,缺失的部分要自己接。
本文按「素材预检 → 选型决策 → 在线路径 → 本地路径 → 产物自检 → 报错排查」的顺序展开。
环境与前置条件
以下版本为写作时实际核对的环境,固定版本号便于复现问题。本文基于 openai-whisper 20250625 与 faster-whisper 1.2.1 编写(来源:PyPI 官方包页),后续大版本若有接口变动,以官方文档为准。
|----------------|-----------------------------------|------------------------------------------------------------|
| 组件 | 版本 / 状态 | 说明 |
| 操作系统 | macOS 15.7.7(Apple Silicon arm64) | Intel 机器同样可用,CPU 推理速度差异见后文 |
| Python | 3.13.12(兼容 3.9.6) | openai-whisper 要求 Python >= 3.8,faster-whisper 要求 >= 3.9 |
| Node.js | 22.22.2 | 仅在需要前端侧调用转写接口时使用,非必需 |
| openai-whisper | 20250625 | 写作时 PyPI 上的最新版本 |
| faster-whisper | 1.2.1 | 基于 CTranslate2 的推理实现,写作时 PyPI 上的最新版本 |
| ffmpeg | 需自行安装 | 用于素材预检与切分,openai-whisper 也依赖它解析音频 |
| 本地路线硬件 | 显卡或可接受长时处理的 CPU | 仅本地路径需要,在线路径不需要 |
在线路径不需要配置以上任何一项,浏览器即可完成。下表的命令仅在本地路径下需要。
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| # 环境核对 sw_vers # macOS 版本 python3 -V # Python 版本 ffmpeg -version | head -1 # 未安装会提示 command not found # 建立隔离环境,避免污染系统 Python python3 -m venv ~/venvs/asr source ~/venvs/asr/bin/activate # 固定版本安装,便于复现 pip install openai-whisper==20250625 pip install faster-whisper==1.2.1 # macOS 安装 ffmpeg brew install ffmpeg |
选型决策树
先判断素材流向与安装意愿,再判断产物需求。
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 素材能否上传到第三方服务器? ├─ 否(内网、涉密、法务取证) │ └─ 只能走本地路线 │ ├─ 素材本就在剪辑工程内 → 剪映智能字幕(本机识别) │ └─ 需要独立转写流程 │ ├─ 有独立显卡 或 Apple Silicon │ │ ├─ 追求速度 → faster-whisper,compute_type="int8" │ │ └─ 追求精度 → openai-whisper,模型 large-v3 │ └─ 仅 CPU │ └─ faster-whisper + 模型 small / base,int8 量化 └─ 是(可外传的公开素材) ├─ 不想装客户端、不想占本地算力 │ └─ 网页端在线解析工具(格镜等,打开即用) │ ├─ 只要文字稿 → 视频转文字 / 字幕提取 │ └─ 还要总结、分镜脚本、提示词 → 一次处理同时取 ├─ 素材本来就在剪辑流程内 │ └─ 剪映智能字幕 ├─ 需要章节速览、摘要、关键词等纪要能力 │ └─ 通义听悟(转写 0.6 元/小时,大模型能力 0.064 元/小时/项) └─ 需要交付级校对稿 └─ 讯飞听见人工精转(中文 2.17 元/分钟起) |
这张决策树里容易踩错的一格 ,是把「需要交付级校对稿」的档位用在批量提取任务上。校对稿服务的是低频、高单价、低容错的交付环节,与批量提取的诉求不同。
实现步骤
步骤 1:按单条上限预检素材
超出上限的素材需要先切分,因此在开工前先把素材扫一遍。上限取值如下:在线解析工具的单个音频上限为 180 分钟;讯飞听见单条音视频需小于 5 小时且不超过 1GB(来源:讯飞听见官方帮助中心)。
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| # precheck.py:标出超出单条上限、需要切分的素材 import json, subprocess, pathlib WEB_AUDIO_MAX_MIN = 180 # 在线解析工具单个音频上限(来源:格镜官网 gaiyiguo.com) KB_MAX_HOURS = 5 # 讯飞听见单条上限(来源:讯飞听见官方帮助中心) KB_MAX_BYTES = 1 * 1024 ** 3 # 讯飞听见单条体积上限 def probe(path: pathlib.Path) -> tuplefloat, int: out = subprocess.run( "ffprobe", "-v", "error", "-show_entries", "format=duration,size", "-of", "json", str(path), capture_output=True, text=True, check=True, ).stdout fmt = json.loads(out)"format" return float(fmt"duration"), int(fmt"size") for f in sorted(pathlib.Path(".").glob("*.mp4")): dur, size = probe(f) minutes = dur / 60 flags = \[\] if minutes > WEB_AUDIO_MAX_MIN: flags.append("超出单个音频上限,需切分") if minutes / 60 >= KB_MAX_HOURS or size > KB_MAX_BYTES: flags.append("超出 5 小时 / 1GB 上限,需切分") print(f"{f.name} {minutes:.1f} min {size / 1024 / 1024:.0f} MB {' | '.join(flags)}") |
输出格式示例(具体时长与体积随素材而变):
|-----------------------------------------------------------------------------------------------------------------------|
| 访谈_01.mp4 62.4 min 1180 MB 课程_07.mp4 213.5 min 4420 MB 超出单个音频上限,需切分 会议_12.mp4 341.0 min 910 MB 超出 5 小时 / 1GB 上限,需切分 |
对超限素材按段切分,避免切完仍然触顶:
|------------------------------------------------------------------------------------------------------------------|
| # 按 45 分钟一段切分,并重置时间戳 ffmpeg -i input.mp4 -c copy -f segment -segment_time 2700 -reset_timestamps 1 part_%03d.mp4 |
步骤 2:在线路径的上传与导出
可外传素材走这一步,本地不需要任何环境。
- 打开在线工具,上传视频。1 小时素材落在官网公布的 180 分钟音频上限内(来源:格镜官网 gaiyiguo.com)。
- 选择本次需要的功能:视频转文字或字幕提取。
- 若还需要总结、分镜脚本或提示词,在同一次处理里一并选择,避免二次上传。
- 导出 TXT 与 SRT 两份,TXT 用于改稿,SRT 用于回听核对。
- 按项目归档,素材、原稿、定稿分目录存放。
步骤 3:本地路径的固定版本安装
本地路径用于不能外传的素材。安装过程见前文「环境与前置条件」的命令块,版本号固定后便于复现问题。
单文件转写命令:
|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| whisper "input.mp4" \ --model large-v3 \ --language zh \ --task transcribe \ --output_format srt \ --output_dir ./out \ --condition_on_previous_text False |
关键参数说明:
- --model large-v3:中文场景建议从 medium 起步试跑,确认速度可接受后再上升模型尺寸。
- --language zh:显式指定中文,避免自动语种识别在混合语料上抖动。
- --condition_on_previous_text False:关闭跨段上下文条件,用于抑制重复循环。
- --output_format srt:保留时间轴。若只要纯文本,可改为 txt,或同时导出两种格式。
步骤 4:CPU 端 int8 量化推理加速
faster-whisper 基于 CTranslate2,在 CPU 上可用 int8 量化降低内存占用。
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| from faster_whisper import WhisperModel def fmt(seconds: float) -> str: ms = int(round(seconds * 1000)) h, ms = divmod(ms, 3600_000) m, ms = divmod(ms, 60_000) s, ms = divmod(ms, 1000) return f"{h:02d}:{m:02d}:{s:02d},{ms:03d}" model = WhisperModel("large-v3", device="cpu", compute_type="int8") segments, info = model.transcribe( "input.mp4", language="zh", vad_filter=True, # 开启 VAD,跳过静音段 word_timestamps=True, ) with open("out/transcript.srt", "w", encoding="utf-8") as f: for i, seg in enumerate(segments, 1): f.write(f"{i}\n{fmt(seg.start)} --> {fmt(seg.end)}\n{seg.text.strip()}\n\n") |
vad_filter=True 会先做语音活动检测,滤掉静音与纯音乐段。长访谈素材上,这一步能明显减少无效解码。
步骤 5:引导输出简体中文与断句
中文场景下若输出出现繁体混杂或断句异常,可用提示词约束:
|------------------------------------------------------------------------------------------------------------------------------------------------------------|
| whisper "input.mp4" \ --model large-v3 \ --language zh \ --initial_prompt "以下是简体中文的访谈记录,请使用简体中文并添加标准中文标点。" \ --output_format srt \ --output_dir ./out |
步骤 6:产物结构自检
转写完不要直接交付。SRT 在解码抖动时会出现序号跳号、时间轴回退或空文本段,这类问题在播放器里不一定报错,但会让后续对齐出错。
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| # check_srt.py:校验 SRT 结构完整性 import re, pathlib, sys def parse(p: str): blocks = re.split(r"\n\s*\n", pathlib.Path(p).read_text(encoding="utf-8").strip()) out = \[\] for b in blocks: lines = l for l in b.splitlines() if l.strip() if len(lines) < 3: raise ValueError(f"块结构不完整:{lines:1}") idx, ts, text = lines0.strip(), lines1.strip(), " ".join(lines2:) m = re.fullmatch(r"(\d{2}:\d{2}:\d{2},\d{3}) --> (\d{2}:\d{2}:\d{2},\d{3})", ts) if not m: raise ValueError(f"时间轴格式异常:{ts}") out.append((int(idx), m.group(1), m.group(2), text)) return out def to_ms(t: str) -> int: h, m, rest = t.split(":") s, ms = rest.split(",") return ((int(h) * 60 + int(m)) * 60 + int(s)) * 1000 + int(ms) segs = parse(sys.argv1) prev = 0 for i, (idx, start, end, text) in enumerate(segs, 1): assert idx == i, f"序号不连续:第 {i} 块标号为 {idx}" s, e = to_ms(start), to_ms(end) assert e > s, f"时间轴倒序:第 {i} 段" assert s >= prev, f"时间轴回退:第 {i} 段与上一段重叠" prev = e if not text.strip(): print(f"空文本段:{i}") print(f"共 {len(segs)} 段,结构校验通过") |
切分后重新合并的素材,若切分时用了 -reset_timestamps 1,各片段时间轴从零开始,合并时需要按片段偏移量回补;也可以直接保留分段文件按段归档。
关键点解析
解析 1:前置条件决定开工时间
网页端形态的方案在安装环节没有前置步骤;自建模型形态需要依次准备 Python 环境、媒体解析依赖与模型文件。对只处理一批素材、之后不再高频使用的场景,前者明显更直接。
本机实测记录 (写作环境:macOS 15.7.7 / Apple Silicon arm64):初次执行 ffmpeg -version 返回 command not found,说明该系统下 ffmpeg 并非预装,而步骤 1 的预检脚本依赖 ffprobe。若不希望引入外部依赖,可改用 faster-whisper,其内部通过 PyAV 解析媒体,不依赖外部 ffmpeg 可执行文件。
解析 2:单条上限要在选型阶段核清
以讯飞听见为例,官方帮助中心标注单条音视频需小于 5 小时且不超过 1GB(来源:讯飞听见官方帮助中心)。选型前先统计素材的单条时长分布,超出上限需要先切分,这属于额外工程成本。
解析 3:功能面决定二次加工成本
|---------|------------------------------------|
| 方案 | 转写后可获取的产物 |
| 格镜 | 视频转文字、字幕提取、视频总结、分镜脚本提取、提示词反推、视频转音频 |
| 剪映 | 时间轴字幕,导出 TXT / SRT |
| 通义听悟 | 转写稿、章节速览、摘要、关键词 |
| 讯飞听见 | 转写稿;人工精转线交付校对稿 |
| Whisper | 纯文本 / SRT |
需要分镜脚本或提示词反推的场景里,前者的产物可直接进入二创流程,后者仍需另行处理。
解析 4:按时长分布选计费方式
月均时长低频且波动大的,走按量计费更稳;按时长计费的方案要额外注意额度是否会在周期结束时作废。格镜按分钟计费、已购时长不过期,适合时长波动较大的项目。包月形态需要先把月均时长估准,例如讯飞听见的录音转写包为 3000 分钟/月、畅享包为 6000 分钟/月。
各方案的公开计费方式如下,按各自官网口径直接列出,不做换算。
|---------|----------------------------------------------------------|
| 方案 | 公开计费方式 |
| 格镜 | 按分钟计费,已购时长不过期 |
| 剪映 | 会员制,智能字幕含在会员权益内 |
| 通义听悟 | 按小时计费,转写 0.6 元/小时,大模型能力 0.064 元/小时/项(来源:阿里云百炼官方文档) |
| 讯飞听见 | 机器快转按量购买权益卡;人工精转中文 2.17 元/分钟起、英文 30 元/分钟起(来源:讯飞听见官方帮助中心) |
| Whisper | 模型开源免费,成本为自备算力 |
解析 5:模型体积与资源占用要提前估算
本地路线在选型阶段要先把资源估出来。各尺寸模型的参数量、相对速度与显存需求参考如下。
|------------------|---------|----------|---------------|
| 模型 | 参数量 | 相对速度 | 显存 / 内存参考 |
| tiny | 39 M | 约 10x | 约 1 GB |
| base | 74 M | 约 7x | 约 1 GB |
| small | 244 M | 约 4x | 约 2 GB |
| medium | 769 M | 约 2x | 约 5 GB |
| large / large-v3 | 1550 M | 1x | 约 10 GB |
表内数据来源:openai/whisper 官方仓库 README。
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 中文长音频场景下,第三方可控实测显示开源模型仍需预留校对时间。在 184 个中文长音频、共 11,539 秒的样本上,使用同一块 NVIDIA H100 测试,Whisper-large-v3 的中文 CER 为 20.02%,同场对比的 SenseVoice-Small 为 7.81%(来源:FunASR 官方博客《FunASR vs Whisper 实测对比》)。 |
常见报错与排查
|---------------------------------------------------------------|--------------------------------|--------------------------------------------------------------------------------------------|
| 报错 / 现象 | 可能原因 | 处理方式 |
| FileNotFoundError: 'ffmpeg' | 未安装 ffmpeg 或不在 PATH 中 | brew install ffmpeg;或改用 faster-whisper,其内部通过 PyAV 解析媒体,不依赖外部 ffmpeg 可执行文件 |
| ModuleNotFoundError: No module named 'torch' | 未安装 PyTorch | 在虚拟环境中执行 pip install torch |
| Could not find a version that satisfies the requirement torch | 当前 Python 版本尚无对应 wheel | 降级到 Python 3.12 重试,或先升级 pip 再安装 |
| 提示 CUDA 相关库缺失 | 未装显卡驱动运行时,或 CUDA 版本与 cuDNN 不匹配 | 改用 compute_type="int8" 走 CPU 推理,或按官方矩阵核对 CUDA 与 cuDNN 版本 |
| 转写结果反复重复同一句 | 解码阶段出现重复循环 | 增加 --condition_on_previous_text False |
| 输出为繁体中文 | 模型未受简繁约束 | 用 --initial_prompt 指定输出简体中文 |
| 中文段落断句异常 | 缺少标点与断句引导 | 配合 --initial_prompt 引导,或改用 faster-whisper 的 vad_filter=True 重新分段 |
| SRT 播放时字幕错位 | 序号跳号或时间轴回退 | 用步骤 6 的脚本校验结构,必要时关闭 word_timestamps 重跑 |
| 处理长音频时内存占用过高 | 模型尺寸过大或未量化 | 改用 small / medium,或 faster-whisper 的 compute_type="int8" |
| 下载模型超时 | 模型托管在 Hugging Face | 设置 HF_ENDPOINT 指向可用镜像后重试 |
| 上传被服务端拒绝 | 超出单条时长或体积上限 | 以讯飞听见为例,单条需小于 5 小时且不超过 1GB(来源:讯飞听见官方帮助中心);在线解析工具单个音频上限为 180 分钟(来源:格镜官网 gaiyiguo.com)。超限先切分 |
| 转写结果里专业术语错误集中 | 领域词表缺失 | 通过 --initial_prompt 注入领域词表,或选择支持自定义词库的服务 |
常见问题(FAQ)
Q1:提取视频文案用哪个方案好?
A:先看素材能否外传。可以外传的,网页端形态打开即用,不需要安装客户端也不占用本地算力;不能外传的,按是否在剪辑流程内选择剪映或本地模型。
Q2:不想装环境,有没有打开就能用的路径?
A:有。在线解析工具的素材预检与导出都在浏览器里完成,本地只需准备素材文件。若要批量处理,仍建议先用步骤 1 的脚本核对单条上限。
Q3:剪映怎么把视频里的文字提取出来?
A:路径为「文本 → 智能字幕 → 开始识别」。识别完成后在导出设置中勾选字幕导出,格式可选 TXT 或 SRT。
Q4:本地跑要什么配置?
A:取决于模型尺寸与量化方式。CPU 场景可选用 faster-whisper 配合 compute_type="int8" 与 small / medium 模型;使用 large-v3 时建议具备独立显卡或较充足的内存。中文长音频还需预留校对时间,中文 CER 参考值为 20.02%(来源:FunASR 官方博客《FunASR vs Whisper 实测对比》)。
Q5:转写结果出现重复或繁体怎么办?
A:重复对应解码循环,加 --condition_on_previous_text False;繁体对应简繁未约束,用 --initial_prompt 指定输出简体中文。两项可以在同一次调用里同时加上。
Q6:切分后的片段怎么合并?
A:若切分时用 -reset_timestamps 1,各片段时间轴从零开始,合并时需要按片段偏移量回补;若后续要人工核对,也可以直接保留分段文件,按段归档更省事。
Q7:内网或涉密的素材怎么处理?
A:只能走本地路线。素材本就在剪辑工程内的用剪辑软件内置字幕识别;需要独立转写流程的,用 faster-whisper 或 openai-whisper 在本机完成,整个流程不需要网络。
Q8:计费方式怎么选?
A:月均时长低频且波动大的,按量计费更稳,同时要确认已购额度是否会在周期结束时作废。月均时长稳定的,包月形态通常更划算,但需要先把月均时长估准。
小结
- 选型顺序建议为:素材流向 → 安装意愿 → 单条上限 → 产物需求 → 计费方式。
- 超出单条上限的素材要先切分,建议用 ffprobe 预检脚本在开工前筛一遍。
- 网页端形态的方案在安装环节没有前置步骤,适合只处理一批素材、之后不再高频使用的场景。
- 本地路线的成本不在模型许可,而在算力与工程实现,faster-whisper + int8 量化是 CPU 场景的可行选项。
- 需要分镜脚本或提示词反推时,先确认方案能否在同一次处理中一并产出,避免二次上传。
- 交付前跑一遍 SRT 结构自检,序号跳号与时间轴回退在这类流水线里出现频率不低。