AI字幕翻译流水线搭建:从语音识别到SRT字幕生成实践
很多做视频内容的朋友这两年应该都听过“AI熟肉”这个词。所谓“AI熟肉”指的是用AI工具完成视频音频的语音识别、翻译、字幕生成甚至配音替代传统人工听译和逐句翻译的繁琐流程。以前一个小时的视频人工听译加打轴可能要花一整天现在借助开源模型和自动化脚本可以把整个流程压缩到几十分钟而且质量已经相当可用。在正式动手之前先说明一点本文讨论的是技术流程和工程实现目标是帮助有合法授权的视频素材、个人学习资料或自制内容做字幕本地化。请务必遵守版权规定不要对未经授权的内容进行二次加工和传播。本文将围绕“AI字幕翻译流水线”的完整搭建过程展开从语音识别、文本翻译到字幕文件生成给出可复制的代码、命令行和常见坑位处理方案适合对AI应用开发、音视频处理感兴趣的开发者参考。1. AI字幕翻译是什么为什么值得自己做1.1 从人工听译到AI流水线传统的外语视频字幕制作流程大致是听译人员反复播放音频片段人工判断说话内容再把翻译好的文本按时间轴写到字幕文件里。这个流程有几个明显的痛点耗时极长1小时视频通常需要5到10小时甚至更久。对听译人员的听力要求高语速快、背景噪、专有名词多时容易出错。时间轴打点极度枯燥大量重复劳动。AI字幕翻译流水线则把上述过程拆成三个可自动化的环节语音识别ASRAutomatic Speech Recognition把音频转成带时间戳的文字。机器翻译MTMachine 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 或 pysrtSRT 字幕文件读写翻译引擎可选用离线模型或大模型API2.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, devicecpu, compute_typeint8) segments, info model.transcribe(audio.wav, languageja, vad_filterTrue) 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 上常用int8GPU 上可用float16提升速度。language指定音频语言可以提升识别准确率。vad_filter开启后自动过滤静音对长音频很有用。3.2 文本翻译的几种路线语音识别得到原文后下一步是把原文翻译成目标语言。常见方案有三种。方案一离线翻译模型Hugging Face 上有大量开源翻译模型例如 Helsinki-NLP 的 opus-mt 系列覆盖日译英、中译英等常见语言对。优点是不依赖网络数据隐私好缺点是小模型翻译质量一般容易丢失语境。from transformers import pipeline translator pipeline(translation, modelHelsinki-NLP/opus-mt-ja-en) result translator(こんにちは、世界) print(result[0][translation_text])方案二大模型API翻译如果条件允许调用大模型API做翻译质量和上下文理解会明显更好尤其是口语化内容、语气词的翻译。这类方案需要准备API密钥并注意调用成本。方案三本地大模型翻译在本地用 Ollama 等方式运行开源大模型兼顾质量与隐私。适合机器配置较高、对数据安全敏感的团队。实际生产环境里很多团队的做法是“先用离线模型跑出初稿再用大模型做二次润色”这样成本和效果比较均衡。3.3 字幕文件格式SRT 和 ASSSRT 是最通用的字幕格式结构非常简单1 00:00:01,000 -- 00:00:04,000 Hello, world!一个序号、一个时间轴、一行文本。多行字幕用空行分隔。ASS 格式功能更强支持字体、颜色、位置等样式设置适合做特效字幕但结构更复杂。本文以 SRT 为主方便直接嵌入播放器。Python 的srt库可以很方便地构建 SRT 内容import srt subtitles [ srt.Subtitle(index1, start1000, end4000, contentHello, 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_outputTrue, textTrue) 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_sizesmall, languageNone): # device 可根据环境调整这里默认 CPU model WhisperModel(model_size, devicecpu, compute_typeint8) segments, info model.transcribe( audio_path, languagelanguage, vad_filterTrue, beam_size5 ) 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, encodingutf-8) as f: json.dump(result, f, ensure_asciiFalse, indent2) print(f识别完成共 {len(result)} 条片段保存到 transcript.json) if __name__ __main__: transcribe_audio(audio.wav, model_sizesmall, languageja)运行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_langja, target_langzh): # 以通用 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, jsonpayload, headersheaders, timeout30) resp.raise_for_status() return resp.json()[choices][0][message][content]方式二使用开源翻译模型如果你想完全本地运行可以直接用 opus-mt 系列# translate.py 中的本地版本 def translate_text_local(text, source_langja, target_langzh): from transformers import pipeline # 日译中需要选择合适的模型建议先到 Hugging Face 查找 model_name fHelsinki-NLP/opus-mt-{source_lang}-{target_lang} pipe pipeline(translation, modelmodel_name) result pipe(text) return result[0][translation_text]实际测试时一些小型 opus-mt 模型的日译中效果有限如果发现质量不好可以改用大模型API或者增加一个二次润色步骤。翻译完整 JSON# translate.py import json def translate_transcript(input_filetranscript.json, output_filetranslated.json, lang_pair(ja, zh)): with open(input_file, encodingutf-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, encodingutf-8) as f: json.dump(translated, f, ensure_asciiFalse, indent2) 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(secondsseconds) def generate_srt(translated_file, output_file, modebilingual): with open(translated_file, encodingutf-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( indexindex, startstart, endend, contentcontent ) ) index 1 with open(output_file, w, encodingutf-8) as f: f.write(srt.compose(subtitles)) print(f字幕已生成{output_file}) if __name__ __main__: generate_srt(translated.json, output/bilingual.srt, modebilingual) generate_srt(translated.json, output/chinese.srt, modetarget)生成的 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 subtitlesoutput/chinese.srt -c:a copy output_video_with_sub.mp4注意几个坑FFmpeg 的subtitles滤镜要求字幕文件路径中的特殊字符做转义尤其是 Windows 路径里的冒号和反斜杠。中文字幕需要字体支持否则可能显示为方框。可以在滤镜里指定字体ffmpeg -i input_video.mp4 -vf subtitlesoutput/chinese.srt:force_styleFontNameMicrosoft YaHei,FontSize16 -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_sizesmall, lang_pair(ja, zh)): os.makedirs(output, exist_okTrue) 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_sizemodel_size, languagelang_pair[0]) print(3/4 文本翻译) translate_transcript(transcript_file, translated_file, lang_pairlang_pair) print(4/4 生成字幕) generate_srt(translated_file, srt_bilingual, modebilingual) generate_srt(translated_file, srt_chinese, modetarget) print(全部完成) if __name__ __main__: main(input_video.mp4, model_sizesmall, lang_pair(ja, zh))运行python pipeline.py这个过程会在命令行持续输出每一条识别和翻译结果方便实时观察效果。5. 常见问题与排查思路5.1 识别结果为空或极少内容问题现象常见原因解决思路识别为空音频采样率或格式不对确认 FFmpeg 输出为 16000Hz 单声道 wav识别为空VAD 把有声音片段过滤掉了把vad_filterFalse再试一次识别结果很少音频里有大量音乐或低语尝试更大模型比如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_typeint8提升速度。有条件的话使用 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_duration1.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 脚本。遇到问题不要急按“音频提取阶段”、“识别阶段”、“翻译阶段”、“生成阶段”四段去定位绝大多数问题都能通过调整参数解决。如果本文对你有帮助可以收藏备用也欢迎在实际跑通后回来分享你的调参经验。