ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Mac自动给视频加字幕:ffmpeg+autosub/whisper实操指南

Mac自动给视频加字幕:ffmpeg+autosub/whisper实操指南 拍视频容易剪字幕难——这句话几乎是我做内容的真实写照。以前一期20分钟的教程视频光对字幕时间轴就能耗掉一个晚上。后来我把mac自动给视频加字幕这套流程彻底跑顺了核心工具就是ffmpeg和autosubffmpeg负责从视频里抽音频、最后把字幕封装回视频或直接烧录进画面autosub负责把语音识别成带时间轴的字幕文件。整条链路免费、可脚本化、批量友好。想给vlog、课程录屏、会议回放快速加字幕的朋友这篇就是我完整跑通后的实操记录。先说说适用范围。如果你只是偶尔剪一两个片子用剪辑软件自带的智能字幕可能更省事。但如果你跟我一样每周要处理好几条视频或者手上有大量讲座、培训、内部资料需要统一加字幕命令行方案的优势就很明显了——不需要把素材导入某个工程一条命令处理一个文件几十个视频可以用脚本循环跑晚上挂机第二天直接收成品。下面我会从方案思路讲到环境安装再到每一步的实操命令和踩坑点尽量做到看完就能照着操作。1. 项目思路与选型分析1.1 为什么选 ffmpeg autosub 这套组合现在市面上能自动加字幕的工具挺多的剪辑软件自带功能、在线字幕网站、各种AI工具都有。但它们大多有几个共通的问题要么字幕时长或者次数有限制要么必须把素材传上别人的服务器要么很难和已有工作流打通。我个人的诉求比较明确免费、本地运行、可批量、可脚本化。ffmpeg 本身是视频处理界的“瑞士军刀”切视频、抽音频、转格式、加滤镜、封装字幕全能干而且完全本地执行。autosub 则是把“语音识别成字幕”这件事独立出来的命令行工具它负责从音频里识别出文字并生成带时间轴的 SRT 字幕文件。这两个工具一个管视频处理一个管语音转写刚好把整个流程闭环起来。相比之下用剪辑软件的自动字幕功能虽然交互体验好、识别准确率也不错但它依赖联网服务而且素材要进入软件工程体系想批量处理就得手动重复操作。命令行方案的核心理念是“流水线可拆解、可复用”每一步都能单独调试出了问题也知道去哪修。1.2 自动加字幕的完整工作链路很多人以为“自动加字幕”是一个按钮完成的事实际背后是一条标准流水线视频文件进来先用 ffmpeg 把音轨抽出来处理成语音识别引擎最适应的格式然后把音频交给识别引擎生成带时间码的文字稿最后再用 ffmpeg 把字幕文件封装回视频或者作为独立字幕轨道放进去。这条链路里ffmpeg 出现在开头和结尾中间是识别环节。每一步都可以单独换方案开头抽音频的方式可以调整采样率、声道中间识别引擎可以换成不同模型结尾封装可以选择软字幕还是硬字幕。这种灵活度是剪辑软件给不了的也是我推荐这套方案最重要的原因。1.3 关于 autosub 的一个关键提醒这里必须先打个预防针。老玩家提到的 autosub指的是 GitHub 上那个用 Python 写的开源字幕生成工具它通过调用语音识别 API 把音频转成字幕。想法很完整但那是很多年前的项目底层依赖偏老对现在的 Python3 环境和某些系统库兼容性很差。你要是直接pip install autosub然后跑十有八九会碰到一堆依赖报错。所以我的实操建议是把 autosub 当作整条链路里的“第二步”来理解。如果你能搞定它老旧的依赖那么用起来没问题搞不定也很正常直接用 OpenAI 开源的 whisper 顶替第二步后面生成 SRT、封装回视频的流程完全一样。这篇文章里我会把两条路都讲清楚你可以根据情况选。2. 环境准备mac 上的安装与配置实录2.1 先把 homebrew 打理好mac 上安装工具最省心的方式就是 homebrew。如果你已经装过可以先跳过没装过的话去 homebrew 官网复制安装命令到终端执行就行。装的过程中最常见的坑是网络不稳、卡在Updating Homebrew或者下载文件超时。我自己的处理方式是给 brew 设置国内镜像源核心思路是配置HOMEBREW_API_DOMAIN和HOMEBREW_BOTTLE_DOMAIN这两个环境变量然后重新执行brew update。另外还有个偷懒的参数HOMEBREW_NO_AUTO_UPDATE1它可以让 brew 在安装软件时跳过自动更新适合你不想每次都被漫长的更新卡住的情况。Apple Silicon 和 Intel 芯片的 mac 目录路径不一样但换源思路完全一致。这里有个小习惯所有环境变量可以写进~/.zshrc以后每次开终端自动生效。不然你这次设了变量能用关掉终端下次又忘了。2.2 安装 ffmpeg 并验证关键编码器brew 就绪后安装 ffmpeg 只需要一条命令brew install ffmpeg这条命令会连着一堆依赖一起装包括视频编码库、音频编码库、字幕渲染库等等耗时取决于网络情况。装完务必验证一下ffmpeg -version ffmpeg -encoders | grep 264第二条命令是为了确认系统里有 libx264 编码器。如果没有后面做硬字幕烧录时会直接失败。brew 官方源编译的 ffmpeg 默认带上了大多数常用组件正常情况不用自己手动编。还有一个验证点看看 ffmpeg 是否支持字幕滤镜ffmpeg -filters | grep subtitles只要能看到subtitles这一行说明 libass 被编译进去了中文字幕烧录才有保障。如果没看到后面烧录硬字幕会遇到Unknown filter或者找不到字体之类的报错。2.3 autosub 与它的替代者whisperautosub 的安装其实很简单pip install autosub问题在于装完之后跑起来很容易报错。原项目依赖的语音识别 API 需要单独配置网络和密钥而且好多 Python 依赖库已经和现在的环境冲突。我试了几次最后果断转向了 whisper反而清净了。whisper 是本地运行的开源语音识别模型安装方式也简单建议单独建一个虚拟环境避免污染系统 Pythonbrew install python3.11 python3 -m venv ~/.whisper-venv source ~/.whisper-venv/bin/activate pip install -U pip pip install -U openai-whisper第一次运行 whisper 时会自动下载模型文件模型小则几百 MB大则好几个 GB会存放在~/.cache/whisper目录。我的建议是先用小模型跑通流程确认整条链路没问题再换大模型提升识别准确率。如果你用的 mac 是 M 系列芯片还可以考虑whisper-ctranslate2这个优化版它在 Apple Silicon 上跑得更快安装量也更小。这个后面可以单独聊。2.4 顺手做一个环境自检正式开始前建议统一跑一遍自检命令which ffmpeg ffmpeg -version whisper --help如果你电脑上同时装过 conda、miniconda 或者其它 Python 环境很容易出现ffmpeg或whisper指向了错误的路径。检查一下which ffmpeg的结果应该指向/opt/homebrew/bin/ffmpegApple Silicon 路径或/usr/local/bin/ffmpegIntel 路径如果不是就要检查 PATH 变量顺序。3. 核心实操一条龙跑通自动加字幕3.1 第一步抽出干净的单声道音频字幕识别引擎吃的是音频不识视频画面。所以先用 ffmpeg 把音轨单独抽出来同时把格式统一成识别引擎最适应的样子mkdir -p work ffmpeg -y -i input.mp4 -vn -ac 1 -ar 16000 -c:a pcm_s16le work/input.wav这条命令的参数逐个解释一下-y如果输出文件已存在直接覆盖省得每次手动确认。-vn忽略视频流只处理音频。-ac 1强制把声道合并成单声道。-ar 16000把采样率统一成 16kHz。-c:a pcm_s16le用无损 PCM 编码写成 WAV。为什么要干这件事因为手机、相机、录屏软件转出来的音频格式五花八门有 48kHz、有双声道、有 AAC 压缩过的。语音识别模型一般在 16kHz 单声道的无损 WAV 上表现最稳定识别速度和准确率都更好。这一步虽然看起来多余但对后面的识别效果影响很大。3.2 第二步语音识别生成 SRT 字幕如果你已经搞定了 autosub 的依赖可以用它来生成autosub -i work/input.wav -o work/input.srt -S zh -D zh -F srt这里的参数分别指定输入音频、输出字幕文件、源语言中文、目标语言中文、输出格式 SRT。autosub 的思路是把音频切成片段逐段调用语音识别接口再把结果拼回完整字幕。问题在于它调用的接口需要单独配置密钥和网络而且识别速度很慢用起来实在费劲。所以我日常主力用的还是 whisperwhisper work/input.wav --language zh --task transcribe --output_format srt --output_dir work这条命令指定了输入音频、语言中文、任务是“转写”而不是“翻译”、输出 SRT 格式、输出目录放到 work 文件夹。运行之后work 目录下会多出 SRT、TXT、VTT 等文件核心需要的是 SRT。模型怎么选我实测下来tiny和base模型速度最快但错误率偏高适合快速验证流程small模型在中文口语上的表现已经比较可用medium准确率更好但对内存和耗时要求更高。如果你视频本身音质清晰、普通话标准small足够如果夹杂大量专业术语或者说话人语速快建议直接上medium。3.3 第三步把字幕封装回视频软字幕SRT 文件到手后有两种方式把它和视频合在一起。第一种是软字幕也就是把字幕作为独立轨道封装进 MP4不改变画面像素速度快、画质无损ffmpeg -y -i input.mp4 -i work/input.srt -c copy -c:s mov_text -metadata:s:s:0 languagechi output.mp4-c copy表示视频流和音频流都直接复制不重新编码所以这条命令几十秒就跑完。-c:s mov_text是把字幕转成 MP4 支持的字幕格式。-metadata:s:s:0 languagechi设置字幕语言为中文方便播放器按语言选择。这种方式的好处是视频质量完全不变字幕还可以随时关闭或重新替换。缺点是有兼容性风险比如 QuickTime 默认不显示 mov_text 字幕部分老播放器也不认。我自己常用的播放器是 IINA 和 VLC都能正常显示。3.4 第四步把字幕烧进画面硬字幕如果追求“任何播放器打开都能看到字幕”那就直接把字幕烧录进画面里。这一步会重新编码视频耗时相对较长ffmpeg -y -i input.mp4 -vf subtitleswork/input.srt:force_styleFontNamePingFang SC,FontSize18,PrimaryColourH00FFFFFF,Outline1,Shadow1 -c:v libx264 -preset fast -crf 20 -c:a copy output_hardsub.mp4关键点是subtitles滤镜。它调用 libass 把字幕渲染成图形再叠加到视频画面上。force_style后面指定的是字幕样式字体用苹方、字号 18、白色字体、带描边和阴影确保任何画面上都能看清。这里有几个我踩过的坑字幕文件如果不在当前目录路径要写对且路径里有空格、中文的时候容易翻车。最简单的做法是先cd到字幕所在目录再执行 ffmpeg或者把路径用引号严格包住。中文字体问题很常见。FontNamePingFang SC在 mac 上一般能用但如果系统字体缓存异常会报Fontconfig error。可以先执行fc-list :langzh看看系统识别到了哪些中文字体再挑一个存在的名字填进去。SRT 文件必须是 UTF-8 编码最好不带 BOM否则烧录时可能乱码。如果你从某些软件导出的字幕文件是 GBK 编码先用文本编辑器转成 UTF-8 再操作。3.5 把完整流程写成本机脚本手动跑一遍两条命令还好但每次都要敲一长串就烦了。我把整套流程固化成了一个脚本放到~/bin目录下以后给任何视频加字幕就一行命令的事#!/bin/bash input$1 base${input%.*} mkdir -p work ffmpeg -y -i $input -vn -ac 1 -ar 16000 -c:a pcm_s16le work/${base}.wav whisper work/${base}.wav --language zh --task transcribe --output_format srt --output_dir work ffmpeg -y -i $input -i work/${base}.srt -c copy -c:s mov_text ${base}_sub.mp4 rm -rf work保存为auto_sub.sh然后执行chmod x ~/bin/auto_sub.sh之后想给视频加字幕跑一行auto_sub.sh 我的视频.mp4就行。脚本默认做软字幕封装速度快想烧录硬字幕把最后那一条 ffmpeg 命令换成上一小节里的烧录命令即可。4. 进阶玩法批量处理与字幕校正4.1 批量给一堆视频加字幕命令行最大的优势就是批量。假设你有一个目录全是录屏课程想全部加上字幕直接一个循环搞定for f in *.mp4; do auto_sub.sh $f done或者用 find 更灵活可以排除已经生成过的文件find . -name *.mp4 -not -name *_sub* -exec auto_sub.sh {} \;不过提醒一下whisper 很吃 CPU/GPU 资源。我在 M 系列芯片的 mac 上一次只跑一个任务风扇就已经开始响了Intel 老款 mac 更建议老老实实排队跑一次开十个并行任务反而可能拖慢整体速度甚至导致系统卡顿。4.2 识别错字的快速修正语音识别再强也会有错字尤其是专有名词、人名、生僻词。SRT 本质是文本文件批量修正直接用 sed 正则替换就行sed -i s/某某某专业术语/正确写法/g work/input.srtmac 的 sed 和 Linux 不同-i后面必须跟一个参数哪怕是空字符串不然会报错。这个细节当初卡了我好一会儿。如果你的替换规则比较复杂比如要把某个经常听错的人名全部纠正也可以写个简单的 Python 脚本处理逻辑就是读文件、替换、写回。这比在剪辑软件里一条一条改要快太多了。4.3 时间轴偏移的整体调整还有一种情况字幕本身识别得没错但和画面口型整体对不上比如所有字幕都晚了 0.3 秒。不管是 whisper 还是 autosub偶尔都会出现这种整体偏移的问题尤其是在处理片头、片尾有静音段的视频时。最简单的处理办法是把 SRT 的时间轴整体前移或后移。写个小脚本解析 SRT 里的时间戳把起止时间都加上或减去一个固定偏移再写回文件。SRT 的时间格式是HH:MM:SS,mmm处理思路就是把每个时间戳转成毫秒加上偏移后再转回去。注意字幕结束时间不能超过视频总时长否则部分播放器会解析异常。4.4 顺带做一版英文或双语字幕whisper 有个 translate 模式可以把中文语音直接翻译成英文字幕输出whisper work/input.wav --language zh --task translate --output_format srt --output_dir work生成的英文字幕翻译质量属于“大致能看懂”的水平胜在速度快、完全免费。如果你想发布面更广的内容可以用这条命令先出一版英文底稿再人工润色一下比从零翻译省力得多。如果你需要的是中英双语字幕在同一画面显示可以把中文 SRT 和英文 SRT 都准备好再用 ffmpeg 的subtitles滤镜叠加两次或者用字幕编辑软件合并这里就不展开细讲了。5. 常见问题排查与避坑记录5.1 安装环节的问题现象可能原因解决办法brew install ffmpeg卡住不动网络原因或 brew 自动更新太慢配置国内镜像源或临时设置HOMEBREW_NO_AUTO_UPDATE1跳过自动更新ffmpeg 命令找不到安装路径不在 PATH 里执行which ffmpeg检查路径必要时brew link ffmpegpip install autosub报一堆依赖错误原版 autosub 依赖老旧与新环境不兼容放弃原版改用 whisper 方案whisper 命令找不到虚拟环境没激活重新执行source ~/.whisper-venv/bin/activate5.2 字幕生成环节的问题现象可能原因解决办法首次运行 whisper 下载模型失败网络波动多试几次或手动下载模型放入~/.cache/whisper识别出来的文字大量乱码音频采样率太高或声道混乱确认抽音频步骤用了-ar 16000 -ac 1识别结果断句奇怪原视频语速太快或背景噪音大尽量使用原声清晰的素材必要时先做音频降噪autosub 报ModuleNotFoundError缺依赖或调用的 API 库版本冲突直接用 whisper 替代自动识别步骤5.3 视频合成环节的问题现象可能原因解决办法中文字幕烧录成方块字体缺失或字体名不对用fc-list :langzh查看系统中文体再指定正确字体烧录时提示找不到字幕文件路径包含空格或中文将字幕文件放到当前目录或正确转义路径引号SRT 中文乱码编码不是 UTF-8用文本编辑器把字幕另存为 UTF-8 无 BOM硬字幕编码非常慢默认编码参数太保守加-preset fast -crf 20速度和画质比较平衡软字幕在播放器里不显示mov_text 兼容性差换用 IINA/VLC/PotPlayer或者用硬字幕方案输出 MP4 无法播放播放器太老不认识 mov_text 字幕轨道换 MKV 容器封装或者直接烧录硬字幕这套流程我自己用了大半年最直观的改变是一期视频从“剪完再花两小时对字幕”变成了“剪完挂一条命令喝杯咖啡回来直接出片”。自动识别不是万能的专有名词、口音重的地方依旧需要人工扫一遍但整体效率提升非常明显。最后再分享一个小经验正式处理长视频之前一定先用 1 分钟左右的片段跑通全流程确认字幕出来、合成没问题再扔给整个素材跑不然等了一个小时才发现字幕时间轴整体偏移返工成本很高。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进