尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

用FFmpeg与Whisper打造慢速英语学习材料:从变速、字幕到TTS

用FFmpeg与Whisper打造慢速英语学习材料:从变速、字幕到TTS 很多英语学习者在练听力时都有过这样的体验拿到一段英文视频第一反应就是把播放器速度调到 0.5 倍速。速度确实慢下来了声音却变得又尖又飘像隔着水听人说话更麻烦的是即使每个单词都听清了没有字幕、没有注解遇到连读、弱读和俚语照样卡住。所谓“慢速英语”通常并不是简单地把播放器放慢而是指一套加工好的学习材料变速不变调的音频、逐句对齐的字幕、词汇注释最好还有一句句跟读的示范。过去制作这样一套材料需要人工对着音频打时间轴、剪句子工作量非常大所以多数人最后只能放弃。这篇文章真正想解决的问题是如何用 FFmpeg、Whisper、TTS 这些开源工具把一段任意英语音频或视频自动加工成一份“慢速英语学习包”。读完之后你可以实现这样一个流程输入一个视频文件脚本自动完成音频提取、时间伸缩、语音识别、字幕生成、词汇表导出最后得到几个可以直接用于学习的文件。先给一个明确判断真正决定一套慢速英语材料质量的核心不是“放慢多少倍”而是两件事——变速之后音调是否保真字幕与音频是否逐句对齐。这两个环节在工具链上都需要专门处理而不是把播放器拖慢那么简单。1. 慢速英语材料为什么不能只靠“播放器 0.5 倍速”先聊聊普通播放器的 0.5 倍速。大多数播放器在降速时为了简单起见会直接拉伸音频波形这会改变播放时长同时也会改变声音的频谱结构听感上就是音调变高、声音变尖。如果播放器做了一点补偿音调可能保持住了但仍然无法解决第二个问题没有配套字幕。精听训练里字幕不是奢侈品而是刚需。没有字幕你就不知道听到的gonna到底是going to还是gotta的缩写没有文本你想查词都不知道该搜什么。慢速英语学习材料本质上不是“一个慢速音频文件”而是一组配套产物。它至少包含几样东西变速不变调的慢速音频用于降低听辨门槛与音频对齐的字幕原速版和慢速版各一份转写文本方便通读和查词词汇表精简出高频生词可选的跟读示范音频例如用 TTS 生成清晰的朗读版。换句话说制作慢速英语材料是一个“加工流水线”原始音频进来经过语音识别、字幕时间轴调整、文本生成、词汇抽取、TTS 合成最后输出一套结构化的学习文件。如果跳过这些步骤只用播放器放慢那学习时还是要在软件里反复拖进度条、切窗口、查词典效率反而更低。所以我们要做的不是“给音频减速”而是“重建一份适合精听的多模态文本”。2. 核心原理变速不变调与时间伸缩要理解慢速音频怎么做先要分清两个概念变调pitch shifting和变速不变调time stretching。变调是改变声音的基频比如男生声音变成女生声音变速不变调则是在保持基频不变的前提下把音频时长拉长或缩短。慢速英语需要的是后者。FFmpeg 里对应的滤镜是atempo。这是一个时间伸缩滤镜范围限制在 0.5 到 2.0 之间。atempo0.75表示时长变为原来的 1 / 0.75 倍大约 1.33 倍语速降为原来的 75%。atempo2.0则是加快一倍。如果你需要比 0.5 更慢的速度不能直接传atempo0.4因为 FFmpeg 会直接报错。解决办法是串联两个滤镜。比如想降到 0.4 倍速可以写成atempo0.5,atempo0.8两个滤镜的乘积 0.5 × 0.8 0.4。这里还有一个容易被忽略的工程问题字幕时间轴。如果你先对原速音频做了语音识别得到的是原速时间轴当音频被降到 0.75 倍速后时长变长字幕的时间戳也必须整体缩放。具体来说新时间戳 原时间戳 / 倍速。如果倍速是 0.75那么原来第 10 秒处的字幕在慢速音频里应该出现在 10 / 0.75 ≈ 13.33 秒处。这个换算不能靠播放器“自动加载字幕”完成必须提前处理好。3. 适合制作慢速英语材料的素材与场景不是所有英语音频都适合做成慢速英语材料。适合制作的素材通常有这么几个特征说话人清晰、语速中等或偏快、背景噪音少、句子结构完整。比较典型的包括英语新闻短片、对话类播客、访谈节目、公开课片段、动画片对话、分级读物配套音频。不太适合的场景是音乐音调变化频繁时间伸缩后会有明显伪影、多人同时说话且重叠严重语音识别很难分离出干净文本、纯噪音或现场录音Whisper 的转写质量会下降字幕对不齐学习价值低。版权问题也需要提醒一句。你要制作的材料如果来自商业课程、付费播客、剧集或电影最好确认是否有权进行二次加工。个人学习用途和公开发布是两回事不要把自己的学习材料随意传播。还有一个实际建议第一次做的时候先找一段 1 到 2 分钟的片段不要贪长。慢速英语材料的制作流程是可重复、可批量跑的但第一次跑通之前你会遇到转写参数、时间轴换算、编码格式等各种细节问题。小片段能让你快速验证每一步是否正确等流程稳定后再批量处理长材料。4. 环境准备与前置条件这套流程依赖的工具比较少但每一个都必不可少。第一是 FFmpeg负责音频提取和时间伸缩。Windows 用户可以从 FFmpeg 官网下载可执行文件并加入 PATHmacOS 用户可以直接用 Homebrew 安装Ubuntu 和 Debian 用户可以用 apt 安装。第二是 Python 3.9 或更高版本用于跑 Whisper 识别脚本和字幕处理脚本。第三是 faster-whisper这里用它来做语音识别和字幕生成。它比原版 whisper 的推理速度快很多CPU 也能跑。第四是可选工具 edge-tts用于生成慢速朗读示范。如果你不需要 TTS 跟读音频可以跳过这一步。安装依赖的命令如下# macOS brew install ffmpeg # Ubuntu / Debian sudo apt update sudo apt install ffmpegpip install faster-whisper pip install edge-tts版本方面我这里不写死具体版本号因为工具链迭代比较快。建议以实际安装时的最新稳定版为准。faster-whisper 首次运行时会下载对应模型模型默认缓存在用户目录下网络环境正常时一般可以顺利完成。5. 核心流程拆解与代码实现下面按步骤拆解整条流水线。代码会分成多个小文件方便维护也方便你按需挑选一部分放进自己的项目里。5.1 从视频中提取音频原始输入如果是视频先提取成 WAV 格式的音频。这里统一转成 16kHz 单声道因为对语音识别来说16kHz 已经足够而且能显著减小音频文件体积加快后续处理速度。ffmpeg -i input.mp4 -vn -acodec pcm_s16le -ar 16000 -ac 1 audio.wav参数含义-vn不要视频流-acodec pcm_s16le输出 16 位 PCM 编码的 WAV-ar 16000采样率 16kHz-ac 1单声道。如果你手里已经是音频文件比如 MP3也可以直接执行同样命令把input.mp4换成你的文件路径即可。文件路径中如果包含中文或空格建议用引号包起来避免命令行解析出错。5.2 对音频做变速不变调使用 atempo 滤镜生成慢速版本。先拿 0.75 倍速举例ffmpeg -i audio.wav -filter:a atempo0.75 -c:a pcm_s16le slow_audio.wav这个文件会作为主要的学习音频。听感上语速明显变慢但音调不会变成“鸭子叫”。如果需要更低的倍速比如 0.4就需要串联两个 atempoffmpeg -i audio.wav -filter:a atempo0.5,atempo0.8 -c:a pcm_s16le slow_audio.wav这里 0.5 × 0.8 0.4。串联时注意顺序对结果没有影响乘法结果就是最终倍速。从工程角度看atempo在低倍速比如低于 0.5时有时候会产生轻微的不自然感所以不建议一开始就调到 0.4。0.75 或 0.8 对大多数学习者已经足够。如果确实需要更慢再尝试 0.6 或 0.5。5.3 用 Whisper 生成原速字幕这一步是整条流水线里最关键的一步。我们用 faster-whisper 对原速音频做识别输出标准 SRT 字幕文件。这里有一个重要的工程选择对原速音频识别而不是对慢速音频识别。原因很简单Whisper 在大数据上训练时见过大量正常语速的语音直接识别原速音频准确率通常更高慢速音频反而可能让模型产生奇怪的断句。下面是完整的转写脚本。文件路径slow_english/transcribe.pyimport sys from faster_whisper import WhisperModel def format_ts(seconds: float) - str: ms int(round(seconds * 1000)) h, rem divmod(ms, 3600000) m, rem divmod(rem, 60000) s, ms divmod(rem, 1000) return f{h:02}:{m:02}:{s:02},{ms:03} def main(): audio_in sys.argv[1] srt_out sys.argv[2] model WhisperModel(small, devicecpu, compute_typeint8) segments, _ model.transcribe( audio_in, languageen, vad_filterTrue, ) with open(srt_out, w, encodingutf-8) as f: for i, seg in enumerate(segments, 1): f.write(f{i}\n) f.write(f{format_ts(seg.start)} -- {format_ts(seg.end)}\n) f.write(f{seg.text.strip()}\n\n) if __name__ __main__: main()运行方式python slow_english/transcribe.py audio.wav transcript.srt脚本中几个参数值得解释一下WhisperModel(small, devicecpu, compute_typeint8)使用 small 模型CPU 推理int8 量化。对一般对话片段small 模型在准确率和速度之间比较平衡。如果你有独立显卡可以把devicecuda然后把模型换成medium或large-v3转写质量会更高。languageen强制指定英语。如果不指定Whisper 会尝试自动检测语言遇到混合语言时反而可能出错。vad_filterTrue启用语音活动检测过滤掉静音和纯音乐片段能减少无效识别也能避免输出过于碎片化的时间轴。生成的transcript.srt大致长这样1 00:00:00,200 -- 00:00:03,400 Oh no... Will Dad get his idea back? 2 00:00:03,600 -- 00:00:06,100 Maybe he left it in the kitchen.这里面的文本会作为后续词汇表和 TTS 朗读的输入所以如果发现专有名词识别错误可以手动改一下 SRT 里的文本。5.4 生成全文文本和词汇表有了 SRT 之后下一步是生成纯文本和词汇表。词汇表这一步用正则分词 停用词过滤把高频虚词和常见功能词去掉剩下的词就是这份材料里的重点词汇。这个策略相对简单但已经足够给学习者一个清晰的方向。文件路径slow_english/text_assets.pyimport sys import re import csv from pathlib import Path STOPWORDS { the, a, an, and, or, but, to, of, in, on, for, with, is, are, was, were, will, would, can, could, do, does, did, i, you, he, she, it, we, they, his, her, their, my, your, our, that, this, these, those, there, then, than, as, at, by, from, not, no, yes, be, have, has, had, get, got, one, two, } def main(): srt_path sys.argv[1] out_dir Path(sys.argv[2]) out_dir.mkdir(parentsTrue, exist_okTrue) lines Path(srt_path).read_text(encodingutf-8).splitlines() sentences [] for line in lines: if line and -- not in line and not line.isdigit(): sentences.append(line.strip()) full_text .join(sentences) (out_dir / transcript.txt).write_text(full_text, encodingutf-8) words re.findall(r[A-Za-z], full_text.lower()) freq {} for w in words: if w not in STOPWORDS: freq[w] freq.get(w, 0) 1 with open(out_dir / vocabulary.csv, w, encodingutf-8, newline) as f: writer csv.writer(f) writer.writerow([word, count, context]) for w, c in sorted(freq.items(), keylambda x: -x[1]): writer.writerow([w, c, ]) if __name__ __main__: main()运行方式python slow_english/text_assets.py transcript.srt material生成的vocabulary.csv里context字段暂时为空。这个字段是留给学习者的你可以在拿到 CSV 后手动补充每个单词在原文中的例句或者接入你熟悉的词典 API 自动填充。这里不强行接第三方接口是为了保证脚本开箱即用。5.5 缩放字幕时间轴匹配慢速音频因为慢速音频的时长是原速音频的 1 / 倍速 倍所以原速字幕里的时间戳也要跟着缩放。这个脚本会读取原速 SRT输出慢速版 SRT。文件路径slow_english/rescale_srt.pyimport sys def to_ms(ts: str) - float: h, m, rest ts.split(:) s, ms rest.split(,) return (int(h) * 3600 int(m) * 60 int(s)) * 1000 int(ms) def to_srt(ms: float) - str: h, rem divmod(int(ms), 3600000) m, rem divmod(rem, 60000) s, ms divmod(rem, 1000) return f{h:02}:{m:02}:{s:02},{ms:03} def rescale(srt_in: str, srt_out: str, factor: float): with open(srt_in, encodingutf-8) as f: content f.read() new_lines [] for line in content.splitlines(): if -- in line: start_s, end_s line.split( -- ) start_ms to_ms(start_s) / factor end_ms to_ms(end_s) / factor new_lines.append(f{to_srt(start_ms)} -- {to_srt(end_ms)}) else: new_lines.append(line) with open(srt_out, w, encodingutf-8) as f: f.write(\n.join(new_lines)) if __name__ __main__: rescale(sys.argv[1], sys.argv[2], float(sys.argv[3]))运行方式python slow_english/rescale_srt.py transcript.srt slow_transcript.srt 0.75为什么要单独做这一步而不是直接用 Whisper 识别慢速音频因为语音识别模型的性能对输入语速很敏感慢速音频可能让模型产生不必要的停顿或重复。用原速音频识别再统一缩放时间轴是更可控的做法。这也是我这里刻意区分“转写”和“时间轴处理”两个步骤的原因。5.6 用 TTS 生成慢速跟读示范可选如果你的学习材料里需要一句“标准慢速朗读”可以用 edge-tts 从文本直接合成音频。比如文章开头那句示例台词edge-tts \ --voice en-US-JennyNeural \ --rate-25% \ --text Oh no... Will Dad get his idea back? \ --write-media sample_slow.mp3这里--rate-25%表示比默认语速放慢 25%也就是大约 0.75 倍速的朗读。en-US-JennyNeural是一个非常自然的英语女声适合当作跟读示范。需要说明的是edge-tts 调用的是云端 TTS 服务合成时要求设备能正常访问该服务。生成的文件适合个人学习使用如果要发布或商用需要留意服务条款和版权边界。对大多数学习场景来说用一段 20 秒的材料生成跟读版完全够用。5.7 一键封装把上面的步骤串成一个 shell 脚本以后输入一个视频文件就能自动得到整套材料。文件路径make_material.sh#!/usr/bin/env bash set -euo pipefail INPUT$1 OUT_DIR${2:-material} FACTOR${3:-0.75} mkdir -p $OUT_DIR ffmpeg -y -i $INPUT -vn -acodec pcm_s16le -ar 16000 -ac 1 $OUT_DIR/audio.wav ffmpeg -y -i $OUT_DIR/audio.wav -filter:a atempo$FACTOR -c:a pcm_s16le $OUT_DIR/slow_audio.wav python slow_english/transcribe.py $OUT_DIR/audio.wav $OUT_DIR/transcript.srt python slow_english/text_assets.py $OUT_DIR/transcript.srt $OUT_DIR python slow_english/rescale_srt.py $OUT_DIR/transcript.srt $OUT_DIR/slow_transcript.srt $FACTOR echo 完成材料输出到 $OUT_DIR运行bash make_material.sh your_input.mp4 material 0.75这个脚本默认把倍速放在第三个参数。如果你想处理批量文件可以再用一个外层循环遍历目录里的所有视频这里不展开但思路是一样的。6. 运行结果与效果验证脚本跑完后material目录下会多出这些文件material/ ├── audio.wav # 原速 16kHz 单声道音频 ├── slow_audio.wav # 变速不变调后的慢速音频 ├── transcript.srt # 原速字幕 ├── slow_transcript.srt # 慢速字幕 ├── transcript.txt # 转写全文 └── vocabulary.csv # 词汇表验证第一步听。播放slow_audio.wav确认语速明显变慢、音调没有失真这是整套方案最重要的判断标准。如果听起来有明显的“金属声”可以先检查倍速设置再考虑换成 0.8 试听。验证第二步看时间轴。打开slow_transcript.srt对照slow_audio.wav检查前几句字幕是否和语音大致对齐。通常不会做到逐字对齐只要整句能对上就行。验证第三步看时长。用 ffprobe 检查两个音频的时长原速音频和慢速音频的时长比值应该接近 1 / 倍速。比如倍速 0.75那么慢速音频时长大约是原速的 1.33 倍。ffprobe -v error -show_entries formatduration \ -of defaultnoprint_wrappers1:nokey1 material/audio.wav ffprobe -v error -show_entries formatduration \ -of defaultnoprint_wrappers1:nokey1 material/slow_audio.wav验证第四步看词汇表。打开vocabulary.csv确认里面没有大量误把the、and这种停用词收进去。如果收进去太多可以扩充脚本里的STOPWORDS集合。7. 常见问题与排查思路实际跑流程时可能遇到下面这些问题问题现象可能原因排查方式解决方案变速后声音发闷、有明显金属声倍速过低atempo 处理产生的伪影更明显先用 0.8 倍速试听对比降低低倍速需求或串联多个滤镜必要时用 Audacity 高质量变速导出atempo 设置为 0.4 时报错atempo 滤波器只支持 0.5 到 2.0查看 FFmpeg 错误日志拆成多个滤镜串联如atempo0.5,atempo0.8Whisper 转写时间很长模型过大或未开启 VAD查看 CPU/GPU 占用试跑 10 秒小片段换成small或base模型开启vad_filterTrueSRT 字幕中文乱码SRT 文件编码不是 UTF-8或播放器默认编码不匹配用编辑器查看文件编码脚本已按 UTF-8 写出播放器里手动设置为 UTF-8字幕与慢速音频不对齐忘了对字幕时间轴做缩放对比transcript.srt和slow_transcript.srt的时间戳执行rescale_srt.py用倍速值缩小或放大时间戳脚本找不到 ffmpeg 命令FFmpeg 未安装或未加入 PATH在终端执行ffmpeg -version安装 FFmpeg并将可执行目录加入 PATH第一批模型下载失败网络问题或模型缓存目录不可写查看错误信息设置缓存目录环境变量或换用更小的模型转录文本里专有名词错误小模型对低频词识别不够准查看transcript.txt手动修改 SRT 文本再重新生成词汇表排查这类问题有一个通用顺序先看命令本身是否执行成功再看中间产物是否生成最后看最终输出。比如字幕对不齐先确认slow_audio.wav是否存在、时长是否正确再确认slow_transcript.srt是否由rescale_srt.py生成而不是直接改了个文件名。这样能快速定位问题在哪一层。8. 工程化建议与最佳实践把这套流程真正用在日常学习或教学项目中有几个建议值得参考。第一倍速选择要克制。0.75 或 0.8 是很舒服的慢速区间足够让耳朵跟上语速又不会因为过度拉伸产生明显失真。0.5 及以下只适合个别“完全听不懂”的片段不建议整篇都这样处理。第二坚持“小片段先行”。第一次跑通前用一段 30 秒到 1 分钟的材料验证全部环节。等确认脚本没有问题了再扩展到完整章节。批量处理时一个视频对应一个输出目录不要把所有产物混在一起。第三保持原速材料和慢速材料并存。原速音频用于后期调速、重新生成字幕慢速音频用于日常学习transcript.txt用于快速检索文本vocabulary.csv用于复习。少了哪一个后续想重新加工都要重跑成本反而更高。第四模型选择按机器配置来。CPU 机器推荐smallint8速度可以接受如果有 NVIDIA GPU推荐medium或large-v3转写准确率会明显更高。模型体积会影响转写质量但不影响已经生成的音频文件所以可以根据机器情况随时切换。第五对转写结果保持人工审核的意识。Whisper 在清晰对话里表现很好但专有名词、连读、俚语仍可能出错。尤其是给公开课程、演讲配音错一个字就可能影响理解。生成材料后最好快速通读一遍transcript.txt改动后重新生成词汇表。第六版权意识要放在工程流程之前。这套工具链适合处理你自己录制的内容、开源材料、已获得授权的内容。对商业付费课程、平台独家视频不要随意下载并加工传播。工具本身是中性的但使用边界要由使用者把握。第七目录和文件命名尽量规范。例如material/目录内部统一使用audio.wav、slow_audio.wav、transcript.srt、slow_transcript.srt这样的固定名称。脚本和课程管理都依赖稳定命名后期批量处理时能省很多事。第八日志记录要舍得。脚本里可以加一行简单的echo或tee记录每次运行的处理时间、输入文件、倍速参数。机器性能波动、模型更新都可能影响结果有日志才能定位变化来源。9. 总结与后续实践建议慢速英语材料的制作本质上不是一个“播放器降速”问题而是一条从音频提取、时间伸缩、语音识别、字幕生成到词汇抽取的加工流水线。这里介绍的这套流程用到的是 FFmpeg、faster-whisper、edge-tts 这几个开源工具脚本拆成独立文件任何一步都可以单独替换或调整。从材料来看核心质量取决于变速是否保真、字幕是否对齐而不是用了多大模型、转写了多少分钟。如果你准备开始实践我的建议是找一段 1 分钟左右的英文视频先用 0.75 倍速走一遍整条流程不要急着调整参数。跑通之后再试着改倍速、换模型、增加 TTS 跟读。把材料从“能生成”打磨到“能用来学习”你才会真正理解哪些参数对听力训练影响最大。下一步可以深入的方向包括把词汇表与间隔重复工具打通把 SRT 按句切片做成卡片或者在网页端做一个完整的英语学习材料预览页面。工具链到这里只是基础真正值钱的是你对自己学习场景的理解。
返回列表