很多做视频内容的朋友,这两年应该都听过“AI熟肉”这个词。所谓“AI熟肉”,指的是用AI工具完成视频音频的语音识别、翻译、字幕生成甚至配音,替代传统人工听译和逐句翻译的繁琐流程。以前一个小时的视频,人工听译加打轴可能要花一整天,现在借助开源模型和自动化脚本,可以把整个流程压缩到几十分钟,而且质量已经相当可用。
在正式动手之前先说明一点:本文讨论的是技术流程和工程实现,目标是帮助有合法授权的视频素材、个人学习资料或自制内容做字幕本地化。请务必遵守版权规定,不要对未经授权的内容进行二次加工和传播。
本文将围绕“AI字幕翻译流水线”的完整搭建过程展开,从语音识别、文本翻译到字幕文件生成,给出可复制的代码、命令行和常见坑位处理方案,适合对AI应用开发、音视频处理感兴趣的开发者参考。
1. AI字幕翻译是什么,为什么值得自己做
1.1 从人工听译到AI流水线
传统的外语视频字幕制作,流程大致是:听译人员反复播放音频片段,人工判断说话内容,再把翻译好的文本按时间轴写到字幕文件里。这个流程有几个明显的痛点:
- 耗时极长,1小时视频通常需要5到10小时甚至更久。
- 对听译人员的听力要求高,语速快、背景噪、专有名词多时容易出错。
- 时间轴打点极度枯燥,大量重复劳动。
AI字幕翻译流水线则把上述过程拆成三个可自动化的环节:
- 语音识别(ASR,Automatic Speech Recognition):把音频转成带时间戳的文字。
- 机器翻译(MT,Machine Translation):把识别出的原文翻译成目标语言。
- 字幕文件生成:按时间戳生成 SRT、ASS 等标准字幕格式。
1.2 需要掌握哪些核心技能
想完整跑通这条流水线,需要几个基础能力:
- Python 基础,能安装依赖、运行脚本。
- 了解 FFmpeg 基本用法,用于音频提取和视频压制。
- 了解常见的字幕文件格式,尤其是 SRT 和 ASS。
- 对模型推理有一点概念,知道模型会消耗多少显存和内存。
这套流程的门槛并不算高,即使没有机器学习基础,只要按照本文步骤操作,也能跑起来。
1.3 有哪些常见的应用场景
- 个人学习:把外语教学视频、技术讲座自动生成本地字幕,方便复看。
- 内容本地化:给自制视频添加多语言字幕,扩大受众。
- 字幕组提效:先让AI生成初稿,再由人工校对,效率比从零开始高得多。
- 语音资料归档:为大量音频会议、访谈录制自动生成文字稿。
2. 环境准备与版本说明
2.1 硬件环境
语音识别模型对计算资源有一定要求。一般来说:
- 如果使用 Whisper 的 tiny、base 模型,纯 CPU 也能运行,但速度较慢。
- 如果使用 small、medium 模型,建议至少有 8GB 以上内存,配合 GPU 效果更好。
- 如果使用 large 系列模型,建议显卡显存不低于 8GB,否则会非常吃力。
本文示例以常见环境为例:Windows 11 或 Ubuntu 20.04 以上的系统,Python 3.10 左右,带 NVIDIA GPU 可选。实际版本请根据你手头的环境调整,核心配置思路是一致的。
2.2 软件准备
需要安装以下软件:
| 软件 | 用途 |
|---|---|
| Python 3.9+ | 运行脚本 |
| FFmpeg | 提取音频、处理视频 |
| faster-whisper | 语音识别,比原始 Whisper 推理更快 |
| srt 或 pysrt | SRT 字幕文件读写 |
| 翻译引擎 | 可选用离线模型或大模型API |
2.3 安装核心依赖
先创建虚拟环境,避免依赖冲突。
python -m venv ai_subtitle_env source ai_subtitle_env/bin/activate # Windows 下用 ai_subtitle_env\Scripts\activate安装必要依赖:
pip install faster-whisper srt pysrtFFmpeg 的安装方式因系统而异。Ubuntu 下可以用:
sudo apt update sudo apt install ffmpegWindows 下建议下载 FFmpeg 官方编译包,解压后把 bin 目录加入系统 PATH。
安装完成后验证:
ffmpeg -version能输出版本信息就说明安装成功。
3. 核心原理拆解:ASR、翻译和字幕格式
3.1 语音识别的基本原理
语音识别模型的作用是把音频波形转换成文本序列,同时给出每个片段对应的时间范围。
以 Whisper 为代表的模型,训练数据覆盖了多语言语音,在日、英、中、韩等语种上都有不错的识别效果。faster-whisper 是 Whisper 模型的优化推理实现,主要改进点包括:
- 使用 CTranslate2 推理引擎,速度比原始 PyTorch 推理快数倍。
- 显存占用更低。
- 支持 VAD(语音活动检测),能自动跳过静音片段。
一个典型的 faster-whisper 调用代码如下:
from faster_whisper import WhisperModel model = WhisperModel("small", device="cpu", compute_type="int8") segments, info = model.transcribe("audio.wav", language="ja", vad_filter=True) for segment in segments: print(f"[{segment.start:.2f} -> {segment.end:.2f}] {segment.text}")这里有几个关键参数:
model_size:模型大小,可以是tiny、base、small、medium、large-v2等。device:指定cpu或cuda。compute_type:计算精度,CPU 上常用int8,GPU 上可用float16提升速度。language:指定音频语言,可以提升识别准确率。vad_filter:开启后自动过滤静音,对长音频很有用。
3.2 文本翻译的几种路线
语音识别得到原文后,下一步是把原文翻译成目标语言。常见方案有三种。
方案一:离线翻译模型
Hugging Face 上有大量开源翻译模型,例如 Helsinki-NLP 的 opus-mt 系列,覆盖日译英、中译英等常见语言对。优点是不依赖网络,数据隐私好;缺点是小模型翻译质量一般,容易丢失语境。
from transformers import pipeline translator = pipeline("translation", model="Helsinki-NLP/opus-mt-ja-en") result = translator("こんにちは、世界") print(result[0]["translation_text"])方案二:大模型API翻译
如果条件允许,调用大模型API做翻译,质量和上下文理解会明显更好,尤其是口语化内容、语气词的翻译。这类方案需要准备API密钥,并注意调用成本。
方案三:本地大模型翻译
在本地用 Ollama 等方式运行开源大模型,兼顾质量与隐私。适合机器配置较高、对数据安全敏感的团队。
实际生产环境里,很多团队的做法是“先用离线模型跑出初稿,再用大模型做二次润色”,这样成本和效果比较均衡。
3.3 字幕文件格式:SRT 和 ASS
SRT 是最通用的字幕格式,结构非常简单:
1 00:00:01,000 --> 00:00:04,000 Hello, world!一个序号、一个时间轴、一行文本。多行字幕用空行分隔。
ASS 格式功能更强,支持字体、颜色、位置等样式设置,适合做特效字幕,但结构更复杂。本文以 SRT 为主,方便直接嵌入播放器。
Python 的srt库可以很方便地构建 SRT 内容:
import srt subtitles = [ srt.Subtitle(index=1, start=1000, end=4000, content="Hello, world!") ] result = srt.compose(subtitles) print(result)注意srt库中时间单位是毫秒,Whisper 返回的时间单位是秒,需要做换算。
4. 完整实战:搭建一条AI字幕翻译流水线
现在把上面的原理串起来,完成一个从视频到双语字幕的完整脚本。
4.1 项目结构
ai_subtitle/ ├── config.yaml # 配置文件 ├── extract_audio.py # 音频提取 ├── transcribe.py # 语音识别 ├── translate.py # 文本翻译 ├── make_srt.py # 字幕生成 ├── pipeline.py # 串联主流程 └── output/ # 输出目录4.2 第一步:从视频提取音频
FFmpeg 可以把视频中的音轨提取成 wav 格式。为什么优先用 wav?因为 wav 是无损格式,后续语音识别时不会因为压缩损失信息。
ffmpeg -i input_video.mp4 -vn -ac 1 -ar 16000 -f wav audio.wav参数说明:
-vn:不处理视频流。-ac 1:把声道合并为单声道。-ar 16000:采样率设为 16000,这是语音识别模型常见的输入采样率。-f wav:输出格式为 wav。
Python 中可以这样封装:
# extract_audio.py import subprocess import sys def extract_audio(video_path, audio_path): cmd = [ "ffmpeg", "-y", "-i", video_path, "-vn", "-ac", "1", "-ar", "16000", "-f", "wav", audio_path ] result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode != 0: print("FFmpeg error:", result.stderr) sys.exit(1) print(f"音频已提取:{audio_path}") if __name__ == "__main__": extract_audio("input_video.mp4", "audio.wav")这里用-y参数允许覆盖输出文件,避免交互式询问中断脚本。
4.3 第二步:语音识别,带时间戳输出
使用 faster-whisper 识别音频,并把每个 segment 保存到 JSON 文件,方便后续翻译和生成字幕。
# transcribe.py import json from faster_whisper import WhisperModel def transcribe_audio(audio_path, model_size="small", language=None): # device 可根据环境调整,这里默认 CPU model = WhisperModel(model_size, device="cpu", compute_type="int8") segments, info = model.transcribe( audio_path, language=language, vad_filter=True, beam_size=5 ) result = [] for segment in segments: item = { "start": segment.start, "end": segment.end, "text": segment.text.strip() } result.append(item) print(f"[{item['start']:.2f} -> {item['end']:.2f}] {item['text']}") with open("transcript.json", "w", encoding="utf-8") as f: json.dump(result, f, ensure_ascii=False, indent=2) print(f"识别完成,共 {len(result)} 条片段,保存到 transcript.json") if __name__ == "__main__": transcribe_audio("audio.wav", model_size="small", language="ja")运行:
python transcribe.py输出结果大致如下:
[0.00 -> 3.50] みなさん、こんにちは [3.52 -> 7.88] 今日は特別な夏祭りを紹介します [8.10 -> 12.60] 一緒に楽しみましょう注意,这里的language参数如果确定知道语言,最好显式传入,比如日语用ja、英语用en,能避免模型自动检测走弯路。
4.4 第三步:文本翻译
这里演示两种翻译方式。
方式一:使用大模型 API 翻译
假设你有一个API密钥,翻译函数可以这样写:
# translate.py import json import requests def translate_text(text, source_lang="ja", target_lang="zh"): # 以通用 OpenAI 兼容接口为例,实际地址和参数按服务商文档调整 url = "https://api.example.com/v1/chat/completions" headers = { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" } payload = { "model": "your-model-name", "messages": [ {"role": "system", "content": f"把{source_lang}翻译成{target_lang},保持口语自然,不要添加解释。"}, {"role": "user", "content": text} ], "temperature": 0.3 } resp = requests.post(url, json=payload, headers=headers, timeout=30) resp.raise_for_status() return resp.json()["choices"][0]["message"]["content"]方式二:使用开源翻译模型
如果你想完全本地运行,可以直接用 opus-mt 系列:
# translate.py 中的本地版本 def translate_text_local(text, source_lang="ja", target_lang="zh"): from transformers import pipeline # 日译中需要选择合适的模型,建议先到 Hugging Face 查找 model_name = f"Helsinki-NLP/opus-mt-{source_lang}-{target_lang}" pipe = pipeline("translation", model=model_name) result = pipe(text) return result[0]["translation_text"]实际测试时,一些小型 opus-mt 模型的日译中效果有限,如果发现质量不好,可以改用大模型API,或者增加一个二次润色步骤。
翻译完整 JSON:
# translate.py import json def translate_transcript(input_file="transcript.json", output_file="translated.json", lang_pair=("ja", "zh")): with open(input_file, encoding="utf-8") as f: transcript = json.load(f) translated = [] for item in transcript: src = item["text"] # 这里根据实际情况调用上面任一翻译函数 dst = translate_text(src, lang_pair[0], lang_pair[1]) translated.append({ "start": item["start"], "end": item["end"], "source": src, "target": dst }) print(f"[{item['start']:.2f} -> {item['end']:.2f}] {src} => {dst}") with open(output_file, "w", encoding="utf-8") as f: json.dump(translated, f, ensure_ascii=False, indent=2) print(f"翻译完成,保存到 {output_file}") if __name__ == "__main__": translate_transcript()4.5 第四步:生成双语SRT字幕
最后一步,把翻译后的 JSON 转成 SRT 文件。可以同时输出纯中文和原文+中文双语两个版本。
# make_srt.py import json import srt from datetime import timedelta def seconds_to_timedelta(seconds): return timedelta(seconds=seconds) def generate_srt(translated_file, output_file, mode="bilingual"): with open(translated_file, encoding="utf-8") as f: items = json.load(f) subtitles = [] index = 1 for item in items: start = int(item["start"] * 1000) end = int(item["end"] * 1000) if mode == "bilingual": content = f"{item['source']}\n{item['target']}" elif mode == "target": content = item["target"] else: content = item["source"] subtitles.append( srt.Subtitle( index=index, start=start, end=end, content=content ) ) index += 1 with open(output_file, "w", encoding="utf-8") as f: f.write(srt.compose(subtitles)) print(f"字幕已生成:{output_file}") if __name__ == "__main__": generate_srt("translated.json", "output/bilingual.srt", mode="bilingual") generate_srt("translated.json", "output/chinese.srt", mode="target")生成的 SRT 示例:
1 00:00:00,000 --> 00:00:03,500 みなさん、こんにちは 大家好 2 00:00:03,520 --> 00:00:07,880 今日は特別な夏祭りを紹介します 今天给大家介绍一个特别的夏日祭典4.6 第五步:把字幕合成到视频
字幕文件生成后,有两种用法。一种是直接在播放器里加载 SRT 文件;另一种是用 FFmpeg 把字幕烧录到视频画面中。
烧录字幕的命令:
ffmpeg -i input_video.mp4 -vf "subtitles=output/chinese.srt" -c:a copy output_video_with_sub.mp4注意几个坑:
- FFmpeg 的
subtitles滤镜要求字幕文件路径中的特殊字符做转义,尤其是 Windows 路径里的冒号和反斜杠。 - 中文字幕需要字体支持,否则可能显示为方框。可以在滤镜里指定字体:
ffmpeg -i input_video.mp4 -vf "subtitles=output/chinese.srt:force_style='FontName=Microsoft YaHei,FontSize=16'" -c:a copy output_video_with_sub.mp4- 如果不希望重新编码音频,可以加
-c:a copy。但视频画面变了,视频流必须重新编码,所以耗时取决于视频长度和机器性能。
4.7 串联全部流程
把以上步骤汇总成一个 pipeline 脚本:
# pipeline.py import os from extract_audio import extract_audio from transcribe import transcribe_audio from translate import translate_transcript from make_srt import generate_srt def main(video_path, model_size="small", lang_pair=("ja", "zh")): os.makedirs("output", exist_ok=True) audio_path = "audio.wav" transcript_file = "transcript.json" translated_file = "translated.json" srt_bilingual = "output/bilingual.srt" srt_chinese = "output/chinese.srt" print("1/4 提取音频") extract_audio(video_path, audio_path) print("2/4 语音识别") transcribe_audio(audio_path, model_size=model_size, language=lang_pair[0]) print("3/4 文本翻译") translate_transcript(transcript_file, translated_file, lang_pair=lang_pair) print("4/4 生成字幕") generate_srt(translated_file, srt_bilingual, mode="bilingual") generate_srt(translated_file, srt_chinese, mode="target") print("全部完成!") if __name__ == "__main__": main("input_video.mp4", model_size="small", lang_pair=("ja", "zh"))运行:
python pipeline.py这个过程会在命令行持续输出每一条识别和翻译结果,方便实时观察效果。
5. 常见问题与排查思路
5.1 识别结果为空或极少内容
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 识别为空 | 音频采样率或格式不对 | 确认 FFmpeg 输出为 16000Hz 单声道 wav |
| 识别为空 | VAD 把有声音片段过滤掉了 | 把vad_filter=False再试一次 |
| 识别结果很少 | 音频里有大量音乐或低语 | 尝试更大模型,比如medium |
| 识别结果乱码 | 语言参数传错 | 确认language参数是否对应音频语言 |
5.2 翻译质量差
翻译质量取决于两个因素:识别原文是否准确,翻译模型是否足够强。如果原文识别已经出错,翻译自然不准。
排查方式:
- 先查看
transcript.json,确认识别文本是否准确。 - 如果识别不准,换更大模型或优化 VAD 参数。
- 如果识别准确但翻译不好,考虑换大模型API或增加润色步骤。
5.3 FFmpeg 字幕烧录报错
常见报错是:
Cannot load font或者:
Fontconfig error: Cannot find font这通常是因为系统缺少中文字体。解决方案:
- 安装字体:Ubuntu 用
apt install fonts-noto-cjk。 - 在
force_style中指定已存在的字体名。 - 使用绝对路径时注意转义,例如 Windows 下可以把路径里的冒号转义为
\\:。
5.4 CPU 推理太慢
如果视频很长,CPU 推理时间会非常久。几种优化方向:
- 使用
tiny或base模型快速出初稿。 - 开启
vad_filter,过滤静音部分,减少无效推理。 - 如果只有 CPU,可以尝试
compute_type="int8"提升速度。 - 有条件的话使用 GPU,推理速度提升明显。
5.5 输出时间轴错位
有些音频开头有较长的 BGM 或空白,会导致字幕整体偏离。解决思路:
- 在提取音频时不要截断开头。
- 识别时使用 VAD,让模型自动跳过静音。
- 生成 SRT 后,用播放器微调整体时间偏移。SRT 本身不支持全局偏移,但很多播放器可以设置字幕延迟。
6. 最佳实践与工程建议
6.1 模型选择策略
不要一上来就上大型模型。实际项目中推荐这样的策略:
- 先用
small模型快速生成初稿,观察识别效果。 - 如果专有名词多、口音重,再升级到
medium。 - 对时长超过1小时的长视频,建议分段处理,避免内存溢出,也方便单独重跑某一段。
- 业务场景中如果有大量相同类型素材,可以固定模型大小和参数,形成标准化流水线。
6.2 字幕断句与重叠处理
Whisper 自动给出的 segment 可能过短,也可能一条字幕塞了两三句话。生产环境中可以在生成 SRT 前做后处理:
- 合并过短片段,比如把小于 1 秒的片段合并到前一条。
- 控制单条字幕最长显示时间,一般不超过 6 秒。
- 如果两条字幕时间重叠,需要做裁剪或调整。
一个简单的片段合并思路:
def merge_short_segments(items, min_duration=1.0): merged = [] for item in items: duration = item["end"] - item["start"] if duration < min_duration and merged: merged[-1]["end"] = item["end"] merged[-1]["text"] += " " + item["text"] else: merged.append(item) return merged6.3 翻译文本的上下文优化
语音识别是逐句处理的,翻译时如果也是逐句翻译,很容易丢失上下文。一个常见的优化方法是在翻译前把相邻几句拼成一个小段落,翻译完后再拆回原句结构。这样处理语气词、省略语时会自然很多。
6.4 日志与断点续跑
长视频处理时,如果中途崩溃,从头再来非常浪费时间。建议在转录 JSON 后立即落盘,翻译时也逐条保存进度,或者至少保存一个“已完成条数”的标记。这样即使中断,也可以从上次位置继续。
6.5 版权与数据安全
这点特别想强调一下。AI字幕翻译提效明显,但它不能成为侵权工具。实际使用中请注意:
- 只处理自己有版权或已获授权的素材。
- 涉及个人隐私或商业机密的音频,优先使用本地模型,不要上传到第三方API。
- 大模型 API 调用会携带文本内容,使用时务必确认服务商的隐私政策。
6.6 工程化落地时预留接口
如果要把这套流程做成一个内部工具或平台,建议从第一天就按“模块化”设计:
- 音频提取、ASR、翻译、字幕生成各自独立。
- 每一步的输入输出都用标准 JSON 落地,方便追查和回滚。
- 翻译引擎做成可插拔式,离线模型和大模型API可以随时切换。
7. 总结与下一步学习方向
本文从 AI字幕翻译的实际需求出发,完整地拆解了一条可运行的流水线:用 FFmpeg 提取音频,用 faster-whisper 做带时间戳的语音识别,用翻译引擎生成目标语言文本,最后用 Python 脚本生成双语 SRT 字幕。整套流程在普通电脑上就能跑通,识别和翻译质量已经可以满足初稿需求,人工校对成本比从零开始低一个量级。
如果继续深入,可以从这几个方向着手:
- 把 faster-whisper 的识别结果接入大型语言模型,用思维链提示词做术语一致化处理。
- 研究 ASS 字幕的样式语法,给字幕加上说话人颜色区分。
- 把流水线封装成 Web 服务,通过任务队列处理批量视频。
- 在 GPU 环境下用 TensorRT 或 ONNX 优化模型推理,进一步压降耗时。
建议你先准备一段自己拥有版权的短视频,从small模型跑起,把整条命令手动执行一遍,再逐步替换为 pipeline 脚本。遇到问题不要急,按“音频提取阶段”、“识别阶段”、“翻译阶段”、“生成阶段”四段去定位,绝大多数问题都能通过调整参数解决。
如果本文对你有帮助,可以收藏备用,也欢迎在实际跑通后回来分享你的调参经验。