whisper.cpp 本地部署指南:从零实现中文视频字幕批量生成

whisper.cpp 本地部署指南:从零实现中文视频字幕批量生成 用了大半年 whisper.cpp我把之前那套在线语音转文字方案彻底换了。原因很直接一条十几分钟的视频传上去要等半天高峰期排队更让人崩溃而且音频文件交到别人服务器上隐私上始终过不去。换成 whisper.cpp 之后本地 CPU 直接跑中英文都能识别标准 SRT 字幕拖进剪辑软件就能用免费、离线、没有时长限制批量处理视频字幕非常顺手。这篇文章把我从零开始部署 whisper.cpp 的过程完整记录下来覆盖 Windows、macOS、Linux 三套环境然后拆解中文识别、模型选型、视频提音频出字幕的完整流程最后把我在实际使用中踩过的坑整理成排查清单。如果你是视频创作者、播客剪辑、会议纪要整理或者纯粹想给本地工具链加一个离线语音转文字能力这篇文章可以直接照着做。1. 先说结论为什么是 whisper.cpp 而不是在线接口或原版 Whisper1.1 它到底解决什么问题whisper.cpp 是 OpenAI 开源 Whisper 语音识别模型的一个 C/C 移植实现。原版 Whisper 用 Python 和 PyTorch 写官方推荐跑在 GPU 上安装依赖多、环境容易冲突在普通办公电脑上跑一条长音频经常要等到怀疑人生。whisper.cpp 把模型推理逻辑用纯 C/C 重写底层依赖是轻量级的 ggml 张量库CPU 就能跑内存占用也比原版小很多。它的核心价值不是又多了一个 Whisper 实现而是把语音识别从需要配置 Python 环境 PyTorch 显卡降到了一个可执行文件 一个模型文件的水平。跟在线 API 相比它的好处更明显音频不上传数据留在本地不按分钟计费随便转多少条不依赖网络在无网环境、内网服务器上都能跑。对我来说最实际的场景是给视频批量生成字幕把一段视频拖进命令行吐出一份 SRT 文件直接进 PR 或剪映调整时间轴效率和成本都碾压在线服务。1.2 和 faster-whisper、在线 API 怎么选我在选型时其实对比过三个方案OpenAI API、faster-whisper、whisper.cpp。OpenAI API识别质量最好但按音频分钟数计费数据要上传网络延迟和限流不可控。我批量处理素材时费用和排队都是问题。faster-whisper基于 CTranslate2 的 Whisper 推理实现速度确实快但依赖 Python 环境部署在干净服务器上还得先装一堆东西。它在服务端做长期驻留服务很合适但作为日常命令行工具略重。whisper.cpp单文件、零 Python 依赖、CPU 友好、支持量化模型最适合装完就跑的本地工具场景。缺点是它的内置后处理功能没有 Python 生态丰富但字幕生成完全够用。我的建议很简单你要是写一次性脚本、做服务端 API、追求极致速度去用 faster-whisper你要是想在本机或生产服务器上做一个稳定、可复现、跨平台的语音转文字工具whisper.cpp 是更省心的选择。1.3 模型选型和硬件预期whisper.cpp 的模型按照体量从小到大有 tiny、base、small、medium、large 几个档位每个档位还有量化版本比如 q5_0、q8_0。这里贴一张我整理过的参考表参数只代表我在常见 CPU 环境下的经验值具体情况以你的机器为准。模型文件体积约推理内存中文识别准确度速度相对原速适合场景tiny75MB约 300MB勉强能听出主题极快远超原速验证流程、低配设备base145MB约 500MB短句还可以很快试运行、快速粗转small466MB约 1GB日常对话可用通常快于原速性价比最高日常推荐medium1.5GB约 3GB明显提升口音能扛较慢要求较高的中文场景large-v32.9GB约 6GB最准专业词更好很慢对精度有极致要求刚上手的人容易犯一个错误直接下载最大的 large 模型然后发现转一条十分钟音频要跑二十分钟劝退。实际上大多数视频字幕场景用 small 或 medium 就足够small 在 i5 级别的 CPU 上速度通常快于原速medium 慢一些但准确度提升明显。建议先用 small 跑通全流程再根据效果决定要不要升级。2. 环境准备与三平台部署2.1 通用准备这四样东西先装好whisper.cpp 的编译环境要求并不复杂所有平台都需要装齐这四样Git拉取源码和更新模型管理脚本。CMake跨平台构建工具whisper.cpp 新版主要用它做编译。C/C 编译器Windows 用 Visual Studio Build Tools 或 MinGWmacOS 用 Xcode Command Line ToolsLinux 用 gcc/g。FFmpeg不是编译必需但处理视频音频几乎是必装的。whisper.cpp 默认读取 16kHz 的 PCM WAV 文件而视频里的音频大多是压缩格式需要先用 FFmpeg 转出来。具体怎么装下面按平台说。2.2 Windows 编译与跑通Windows 上最稳的路线是用 Visual Studio 的编译环境配合 CMake。安装 Visual Studio 2022 时勾选使用 C 的桌面开发工作负载同时安装 Git for Windows 和 CMake然后把三个工具的路径都加进系统 PATH。安装完成后打开 PowerShell 手动验证一下cmake --version git --version没报错就可以拉源码git clone https://github.com/ggerganov/whisper.cpp.git cd whisper.cpp cmake -B build cmake --build build --config Release编译完成后可执行文件在build\bin\Release\whisper-cli.exe。如果懒得配置 Visual Studio也可以直接下载官方 Release 页面里的预编译包不过每个版本不一定都提供 Windows 二进制所以还是建议自己编译一次以后更新版本也方便。有个小坑是 PowerShell 和 CMD 的 UTF-8 编码问题。中文 Windows 默认代码页是 GBKwhisper-cli 输出中文到控制台时经常显示成乱码这通常不影响最终生成的 SRT 文件内容但看着难受。在 PowerShell 里可以先执行chcp 65001切到 UTF-8 代码页输出就正常了。2.3 macOS 编译与跑通macOS 上要先安装 Xcode Command Line Toolsxcode-select --install然后用 Homebrew 装 CMake 和 FFmpegbrew install cmake ffmpeg之后的操作跟 Windows 类似git clone https://github.com/ggerganov/whisper.cpp.git cd whisper.cpp cmake -B build cmake --build build --config Release如果用的是 Apple Silicon 芯片想要 GPU 加速可以在 cmake 时开启 Metal 支持cmake -B build -DGGML_METALON cmake --build build --config Release实测下来M1/M2 芯片的 MacBook 开 Metal 之后medium 模型的推理速度能快不少而且编译时间也不算长。建议 Apple Silicon 用户直接把这行参数加上。编出来的可执行文件仍然在build/bin/whisper-cli。2.4 Linux 编译与跑通Linux 服务器是我用得最多的环境因为可以挂后台批量处理命令也最顺手。以 Ubuntu/Debian 为例sudo apt update sudo apt install -y build-essential git cmake ffmpeg git clone https://github.com/ggerganov/whisper.cpp.git cd whisper.cpp cmake -B build cmake --build build --config Release如果你有 NVIDIA 显卡并且想用 GPU 推理可以再加上cmake -B build -DGGML_CUDAON cmake --build build --config Release但说实话除非你有大量转写任务否则 CPU 加量化模型在大多数场景已经够用。我自己的服务器是纯 CPU用 small 模型批量转字幕速度和效果都满意。如果编译过程中报缺少依赖按提示装对应库就行整体难度不大。2.5 模型下载的两种方式whisper.cpp 项目自带模型下载脚本Linux 和 macOS 下直接用bash models/download-ggml-model.sh small把末尾的small换成base、medium、large-v3等名字即可。脚本会从 Hugging Face 下载对应模型文件到models目录。Windows 没有原生 bash如果你安装了 Git Bash 或 WSL也能跑这个脚本。不想装的话就手动下载模型文件都托管在 Hugging Face 的ggerganov/whisper.cpp仓库里文件命名类似ggml-small.bin、ggml-medium.bin用浏览器下载后放到models目录就行。如果下载速度不理想可以换用国内镜像站或者找一台网络条件好的机器下好再拷贝过来。模型下载完用-m参数指定路径剩下的就交给 whisper-cli。3. 核心用法从语音文件到中文 SRT 字幕3.1 先跑一条最基本的转写命令编译完成、模型就位后先拿一段短音频验证流程。假设audio.wav是已经转好的 16kHz 单声道 WAV 文件执行./build/bin/whisper-cli -m models/ggml-small.bin -f audio.wav终端会开始打印识别进度然后把带时间戳的文本输出到终端。Linux 和 macOS 命令一样Windows 把路径换成.\build\bin\Release\whisper-cli.exe -m models\ggml-small.bin -f audio.wav即可。这一步如果顺利跑通说明编译、模型、音频都没问题。接下来所有复杂用法都是在这个命令上不断加参数。3.2 中文识别的三个调优点whisper 默认会自动检测语言但中文场景下让它自己猜偶尔会出意外。为了保证中文识别的稳定性我建议从三个方面调整第一手动指定语言。-l auto是自动检测-l zh是强制中文。自动检测在音频开头有音乐、静音或英语单词时可能误判成其他语言强制指定中文能减少这种情况./build/bin/whisper-cli -m models/ggml-small.bin -f audio.wav -l zh第二加提示词。-p参数可以给模型一个初始提示告诉它当前音频的领域或风格。比如做技术视频字幕时添加./build/bin/whisper-cli -m models/ggml-small.bin -f audio.wav -l zh -p 以下是关于技术开发的中文讲解视频。提示词对专业术语和语境有一定的引导作用实际测试中能改善一些同音词的选择。第三选对模型档位。这才是中文识别最关键的变量。tiny 和 base 模型识别人名、地名和长句时错误率明显偏高small 算入门medium 开始质变。我个人的经验是日常短视频、播客用 small采访、课程、会议这类对准确度要求高的场景用 medium甚至直接上 large-v3。3.3 视频转字幕的完整流水线FFmpeg 抽音频 whisper 出 SRTwhisper.cpp 不直接读视频文件除非你专门开了 FFmpeg 集成编译选项否则最稳妥的做法是先把视频里的音频抽出来。抽取命令如下ffmpeg -i input.mp4 -ar 16000 -ac 1 -c:a pcm_s16le audio.wav这里有几个参数得解释清楚。-ar 16000把音频重采样为 16kHz这是 Whisper 模型训练时使用的采样率直接喂更高采样率的音频反而会浪费计算-ac 1合并成单声道因为语音识别不需要立体声信息-c:a pcm_s16le指定输出为 16 位整数的 PCM 编码也就是标准的无损 WAV。这三项组合起来就是 whisper 最友好的输入格式。音频文件到手后生成 SRT 字幕./build/bin/whisper-cli -m models/ggml-small.bin -f audio.wav -l zh -osrt -of subtitle-osrt表示输出 SRT 字幕格式-of subtitle指定输出文件名前缀最终生成的文件就是subtitle.srt。打开看一下内容大概是这样的结构1 00:00:00,000 -- 00:00:04,000 大家好今天我们来讲一下本地语音转文字工具 2 00:00:04,000 -- 00:00:08,000 配置最麻烦的地方其实在编译环境这种文件可以直接拖进 VLC、PotPlayer 播放器看效果也可以导入剪辑软件进行微调。3.4 更多输出格式VTT、JSON、LRC、TXTwhisper-cli 支持好几种输出格式实际用处各不相同-otxt纯文本不带时间戳适合快速看全文。-ovttWebVTT 字幕格式网页视频平台兼容性比 SRT 好。-ojsonJSON 格式包含每个 segment 的起止时间和文本适合程序二次处理。-olrcLRC 歌词格式做歌词文件或 K 歌字幕有用。-ocsvCSV 格式方便导入 Excel 做统计或调整。多个输出格式可以同时指定。比如./build/bin/whisper-cli -m models/ggml-small.bin -f audio.wav -l zh -osrt -otxt -ojson -of result一条命令同时生成result.srt、result.txt、result.json后续想怎么处理都有原始数据。我一般默认至少出 SRT 和 JSON 两份SRT 给人看JSON 给脚本处理。4. 批量实战给一个视频集生成 SRT 并嵌入视频4.1 准备批量处理脚本实际做字幕的时候一个视频一个视频手动敲命令太累。我把抽音频和识别封装成脚本扔进服务器后台跑。下面是一个 Bash 版本适合 Linux/macOS#!/bin/bash mkdir -p wavs subtitles for file in videos/*.mp4; do base$(basename $file .mp4) echo 处理中$base ffmpeg -y -i $file -ar 16000 -ac 1 -c:a pcm_s16le wavs/${base}.wav ./build/bin/whisper-cli -m models/ggml-medium.bin -f wavs/${base}.wav -l zh -osrt -of subtitles/${base} doneWindows 上的 PowerShell 版本思路一样Get-ChildItem .\videos\*.mp4 | ForEach-Object { $base $_.BaseName ffmpeg -y -i $_.FullName -ar 16000 -ac 1 -c:a pcm_s16le .\wavs\$base.wav .\build\bin\Release\whisper-cli.exe -m models\ggml-medium.bin -f .\wavs\$base.wav -l zh -osrt -of .\subtitles\$base }注意脚本里的-y是让 FFmpeg 覆盖同名文件免得处理一半卡在交互确认上。批量处理几十个视频的时候交互确认会让人抓狂。4.2 运行与验证跑完脚本后检查subtitles目录下生成的.srt文件数量和大小。一个常见问题是某些视频本身没有音频轨道FFmpeg 会报错脚本直接中断。为了避免这种情况可以在脚本里加一层判断if [ ! -f wavs/${base}.wav ]; then echo 警告${base} 可能没有音频轨道跳过 continue fi批量处理后建议随机抽两个 SRT 文件人工检查时间轴和断句。whisper 把长句切成分段的时间点通常比较准偶尔会有整段提前或延后 0.5 秒的情况这在剪辑软件里微调一下就行。4.3 把字幕直接封装进视频SRT 字幕文件可以和视频一起放在播放器里外挂加载但如果想直接把字幕压进视频文件方便直接发给别人有两种方式。一种是编码进画面字幕变成像素的一部分任何播放器都能看到但无法关闭重新转码耗时另一种是封装成内置字幕轨保留开关能力速度快。我推荐第二种以 MP4 为例ffmpeg -i input.mp4 -i subtitles/subtitle.srt -c copy -c:s mov_text output_with_sub.mp4-c copy表示视频和音频轨道直接复制不重新编码秒级完成-c:s mov_text把字幕转成 MP4 容器支持的格式封装进去。如果是 MKV 文件封装 SRT 更简单ffmpeg -i input.mkv -i subtitles/subtitle.srt -c copy -c:s srt output_with_sub.mkv播放时按字幕切换快捷键选对应音轨就能看到中文硬字幕效果。这个方法适合把成品发给老人小孩看省得他们自己开字幕。5. 常见问题与避坑指南5.1 报错速查表我使用过程中遇到最多的问题汇总成下面的对照表报错或现象可能原因处理办法failed to load model模型路径不对或文件未下载完整检查-m参数路径和文件大小failed to read audio音频不是 16kHz WAV 或 FFmpeg 未安装先用 FFmpeg 转成标准 WAVnot enough memory模型太大或内存不足换用 q5_0/q8_0 量化模型或 small 档输出中文乱码Windows 控制台代码页不是 UTF-8先执行chcp 65001编译时找不到 CMakeWindows 环境变量未配置重装 CMake 并勾选添加到 PATHmacOS 报cannot find -lompOpenMP 库缺失brew install libomp排查这类问题有个通用思路先确认模型能加载再确认音频能被正确读取最后才去排查识别效果。我见过很多人一上来就怀疑识别不准确结果其实是音频采样率不对whisper 接收到的本来就是畸变输入。5.2 中文识别不准怎么办中文识别效果不佳先别急着怪工具通常的原因是这三个第一模型档位过低。tiny 和 base 的中文能力很有限我能理解省内存的想法但中文识别真的建议从 small 起步。第二音频质量差。背景音乐、混响、多人重叠说话、电话录音都会让识别率断崖式下降。Whisper 对清晰人声的识别能力很强但对噪声是非常敏感的。如果视频里有人声和背景音乐混在一起声学上是硬伤再大的模型也救不回来。第三缺少上下文。-p提示词能帮模型建立预期。比如做医疗类视频提示词写成以下是医学健康科普视频包含专业医学术语识别的稳定度会明显不同。如果上面的手段都用了还是不满意那就是模型档位问题。升级到 medium 或 large-v3同时把提示词写好中文识别率会有一个肉眼可见的提升。5.3 接口对接出现 415 的排查思路如果你是开发者打算把 whisper.cpp 包成一个本地 HTTP 服务然后接到 Dify 这类工作流平台很可能会遇到一个奇怪的错误接口返回 HTTP 415。这个状态码表示不支持的媒体类型通常不是你识别代码的问题而是请求格式不匹配。排查思路按顺序来确认接口接收的是multipart/form-data还是application/json。很多语音转文字 API 要求音频文件走文件上传字段Content-Type 必须是multipart/form-data。检查文件字段名是否和接口定义一致比如服务端要求参数名是audio但你传成了file对方解析不到音频响应就会是 415 或 400。确认音频格式是否满足工具约定。whisper.cpp 本身对输入格式敏感如果服务端只接受 WAV客户端传了 MP3在底层就可能读不出来进而返回错误。这类问题最大的特点就是工具本身是好的但接口之间对不上。调通一次之后最好把测试用的请求样例保存下来下次对接其他平台直接复制粘贴。5.4 SRT 字幕和 SRT 推流协议别搞混搜索SRT时你会发现这个词有两个毫不相关的含义。一个是本文一直在用的 SubRip 字幕格式文件名后缀是.srt给视频做字幕用的另一个是直播领域里的 SRT 传输协议Secure Reliable Transport用于视频推流和传输常出现在 vMix、OBS 这类直播工具的推流设置里。这两个概念单纯是同名缩写没有任何关系。如果你是在查字幕问题搜到一堆推流参数配置别疑惑换个关键词加字幕或SubRip再搜。做视频编辑的人知道这个区分能省不少弯路。回到 whisper.cpp 本身我自己的使用体感是它不像一个需要精心伺候的实验品反而像一个稳定可靠的命令行工具。你把它编译好、模型选对、音频格式处理好剩下的就是往脚本里丢视频、收 SRT 文件。现在我的日常工作流里视频剪辑的第一步就是跑一遍它把粗剪字幕生成出来省下的时间比想象中多得多。如果你也想把语音转文字做成自己工具链里的一环后面还可以考虑把它包成 HTTP 服务或者接到本地的模型工作流里实现语音输入、大模型回答的完整离线链路。这篇文章覆盖的都是基础但关键的环节先把这条链路跑通再按自己的需求往上叠功能就好。