用DeepSeek和faster-whisper构建葡语转中文字幕流水线
2026/9/17 13:25:23 网站建设 项目流程

这次我们来看一个非常具体、甚至有点怀旧的需求:给一部 1990 年的 OVA 动画生成葡语转中文字幕,翻译环节交给 DeepSeek 完成。严格说,这不是一个“双击启动”的开源项目,而是一条由音轨提取、语音识别、机器翻译、字幕合成组成的 AI 字幕流水线。最有价值的点在于:DeepSeek 翻译走 API 调用,本地不需要跑大语言模型,资源压力集中在语音识别环节;如果只做文本翻译,CPU 机器也能扛。

这篇文章会把整条流水线拆成可复现的步骤,从音频提取开始,到 faster-whisper 输出带时间戳的葡语文本,再到 DeepSeek 批量翻译成中文,最后生成 SRT 字幕。同时会聊多集批量任务怎么组织、API 并发怎么控制、时间轴漂移怎么排查,以及做这类“老片重译”时最容易忽略的版权边界。

1. 核心能力速览

能力项说明
目标任务葡萄牙语音轨 → 中文 SRT 字幕
翻译引擎DeepSeek API,采用 OpenAI 兼容调用格式
语音识别faster-whisper 本地推理,可选 CPU / GPU
本地硬件要求文本翻译阶段基本无显卡要求;语音转写阶段取决于 Whisper 模型大小
显存占用主要来自 Whisper 本地推理,建议先用小模型测试,再根据实际资源升级
批量能力支持按集目录循环处理,可加并发与失败重试
输出格式SRT 字幕、JSON 中间结果、纯文本
适用素材老动画 OVA、外语短视频、个人已授权内容
合规边界字幕仅限个人学习、研究或已获得授权的场景,公开发布需自行确认版权

这套流程的定位不是“全自动生成完美字幕”,而是把字幕翻译中最耗时的“听写 + 翻译”环节脚本化。你仍然需要做最后的校对,但整体工作量会比手工听译低很多。

2. 适用场景:什么样的内容适合这套流程

这套流程更适合那些“有现成音轨、需要快速得到可读中文初稿”的内容。以 1990 年的 OVA 动画为例,这类老片子有几个典型特征:音轨年代久远,背景音和对话混在一起;角色名没有统一译法;口语化表达多;如果原始字幕是葡萄牙语,那么人工找葡语翻译的成本很高。

比较合适的场景包括:

  • 手上有合法获得的 DVD、BD 或官方数字版片源,想给自己做一份中文字幕。
  • 外语短视频、访谈、课程需要快速粗翻,再人工润色。
  • 字幕组或翻译爱好者做“辅助翻译”的前置环节。
  • 想验证 DeepSeek 在字幕翻译场景下的效果,比如术语一致性、多轮对话上下文保持。

不建议的场景也很明确。

  • 不适合做实时字幕,因为音轨转写和翻译存在明显延迟。
  • 不适合直接发布未授权字幕,尤其涉及老动画版权、角色形象、音轨版权时。
  • 不适合把 API 返回的翻译结果不加校对直接使用,机器翻译会在语气、梗、专有名词上出错。

合规上必须强调一句:你自己要有合法使用片源和音轨的权限。上传到第三方 API 的语音/文本内容也要确认不包含未公开的敏感信息。最终若公开发布字幕或译文,需要对版权和授权进行独立确认。

3. 流程拆解:从葡语音轨到中文字幕的四个环节

把整条链路拆开看,其实只有四个环节。

环节输入输出负责内容
1. 音轨提取视频文件WAV 音频分离音轨,降采样,降低后续处理负载
2. 语音转写WAV 音频JSON 分段文本葡萄牙语识别,带开始时间、结束时间、文本
3. 机器翻译JSON 分段文本JSON 中文文本DeepSeek 逐段或按批翻译
4. 字幕合成中文文本SRT 文件合并时间戳,生成字幕,人工校对

第一个环节不涉及模型,只依赖 ffmpeg。第二个环节是把语音变成可翻译的文本,这里我用 faster-whisper,因为它比原生 Whisper 快,而且支持 int8 量化,CPU 上也能跑。第三个环节交给 DeepSeek API,关键在于分段方式和提示词设计。第四个环节是纯脚本工作,把翻译结果按原时间戳写成 SRT。

整个流程的中间产物最好全部保留。比如转写得到的 JSON 可能包含说话人置信度、分段时间戳;翻译后的 JSON 是生成 SRT 的基础。如果某一步失败,不需要从头再来。

4. 环境准备与前置条件

建议使用 Linux 或 Windows WSL 环境,Python 版本 3.10 以上。Windows 原生 PowerShell 也能跑,但路径和并发处理体验不如 Linux。

需要安装的组件包括:

  • ffmpeg,用于音轨提取和音频格式转换。
  • Python 包:faster-whisper,用于本地语音识别。
  • Python 包:openai,用于调用兼容 OpenAI 格式的 DeepSeek API。
  • 一个 DeepSeek API Key,用于翻译请求。
  • 磁盘空间:一部动画的音轨不大,但转写模型需要几 GB 模型文件,建议预留 10 GB 以上。

安装命令可以这样组织:

# 系统依赖 sudo apt update sudo apt install -y ffmpeg # Python 依赖 pip install faster-whisper openai

如果你要跑 GPU 推理,还需要确认本机 CUDA 环境。faster-whisper 底层依赖 CTranslate2,它会自动选择可用的 CUDA 设备。首次运行某个规模的模型时,会自动从 HuggingFace 下载模型文件,网络稳定一点体验更好。

目录结构建议这样规划:

episodes/ raw/ # 原始视频 audio/ # 提取出的 wav asr/ # faster-whisper 转写结果 json translation/ # DeepSeek 翻译结果 json srt/ # 最终字幕 scripts/ extract_audio.py transcribe.py translate.py build_srt.py

这样做的目的是让每道工序都能单独重跑。比如翻译结果不满意,不需要重新转写音频,直接改提示词重新翻译即可。

5. 实践操作:转写、翻译、SRT 生成与校对

5.1 提取音轨,准备转写素材

先用 ffmpeg 把视频中的音轨提取出来,转成 16kHz 单声道 WAV。降低采样率和声道数能明显减少 Whisper 的计算量,对识别结果影响很小。

ffmpeg -i episodes/raw/ova01.mkv -vn -ac 1 -ar 16000 episodes/audio/ova01.wav

参数说明:

  • -vn:丢弃视频流,只处理音频。
  • -ac 1:转成单声道。
  • -ar 16000:采样率设为 16000,Whisper 的标准输入是 16kHz。

执行完可以用ffprobe检查音频时长和格式,确认没有生成空文件。

5.2 faster-whisper 葡语转写

转写脚本的核心逻辑是加载模型、读取音频、输出带时间戳的段落。先写一个最小的 transcribe.py:

import json import sys from faster_whisper import WhisperModel audio_path = sys.argv[1] output_path = sys.argv[2] # 可选 device="cuda",compute_type="float16" model = WhisperModel("small", device="cpu", compute_type="int8") segments, info = model.transcribe( audio_path, language="pt", vad_filter=True, beam_size=5, ) results = [] for segment in segments: results.append({ "start": segment.start, "end": segment.end, "text": segment.text.strip(), }) with open(output_path, "w", encoding="utf-8") as f: json.dump(results, f, ensure_ascii=False, indent=2) print(f"transcribed segments: {len(results)}")

这里有几个参数值得注意。language="pt"强制指定葡萄牙语,避免模型在开头静音段胡乱猜测语言。vad_filter=True会过滤掉没有语音的片段,对老动画这种经常有 BGM 和停顿的素材很有效。beam_size=5是识别质量和速度的折中,如果发现漏译严重,可以适当降低到 1 或 2。

转写完成后,检查 JSON 里的文本是不是葡语,时间戳是否连续。如果一段文本特别长,说明 Whisper 可能把两个句子粘在一起,后续翻译时要处理。

5.3 用 DeepSeek 翻译葡语文本

翻译阶段不直接拿整段视频文本丢给 DeepSeek,而是按语义块切分。最稳妥的做法是每隔 500 到 1000 字符发送一个请求,并且让模型保留行号。

import json import os import sys from openai import OpenAI client = OpenAI( api_key=os.getenv("DEEPSEEK_API_KEY"), # base_url 以 DeepSeek 官方文档为准 # base_url="https://api.deepseek.com", ) system_prompt = """ 你是一位专业的字幕翻译。你会收到带编号的葡萄牙语字幕文本。 要求: 1. 翻译成自然、简洁的中文口语。 2. 保留原有编号,每行只输出 编号: 翻译结果。 3. 不要添加时间轴,不要解释原文。 4. 角色名如果出现多次,必须全程保持一致。 5. 遇到俚语或语气词,翻译成中文对应表达。 """.strip() def translate_batch(batch: list[str]) -> list[str]: user_content = "\n".join(batch) response = client.chat.completions.create( model="deepseek-chat", messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_content}, ], temperature=0.2, max_tokens=2000, timeout=120, ) content = response.choices[0].message.content.strip() # 这里需要把模型输出的行重新映射到编号 result = {} for line in content.splitlines(): if ":" in line: idx, text = line.split(":", 1) if idx.strip().isdigit(): result[int(idx.strip())] = text.strip() return result if __name__ == "__main__": with open(sys.argv[1], encoding="utf-8") as f: segments = json.load(f) batch = [ f"{i}: {segments[i]['text']}" for i in range(len(segments)) ] translated = translate_batch(batch) for i, seg in enumerate(segments): seg["zh"] = translated.get(i, "") with open(sys.argv[2], "w", encoding="utf-8") as f: json.dump(segments, f, ensure_ascii=False, indent=2)

这里最核心的是提示词。字幕翻译和普通文本翻译不一样,要求短、口语化、保留行号。temperature=0.2是刻意的,字幕翻译场景需要稳定输出,不要发挥。timeout=120是给慢响应留的余量,避免偶发网络波动直接失败。

需要注意的是,大部分翻译脚本里最容易翻车的不是模型,而是输出格式。如果 DeepSeek 返回了 Markdown 列表或额外解释,行号解析就可能漏掉一批。所以我在解析时做了idx.strip().isdigit()判断,解析失败的字幕行宁可空着,也不要错位。

5.4 生成 SRT 与校对时间轴

翻译结果还是 JSON,要转成可直接挂到播放器里的 SRT。

import json import sys def format_timestamp(seconds: float) -> str: millis = int(round(seconds * 1000)) hours, remainder = divmod(millis, 3600000) minutes, remainder = divmod(remainder, 60000) secs, millis = divmod(remainder, 1000) return f"{hours:02}:{minutes:02}:{secs:02},{millis:03}" with open(sys.argv[1], encoding="utf-8") as f: segments = json.load(f) lines = [] for i, seg in enumerate(segments, start=1): start = format_timestamp(seg["start"]) end = format_timestamp(seg["end"]) zh = seg.get("zh", "").strip() if not zh: continue lines.append(f"{i}") lines.append(f"{start} --> {end}") lines.append(zh) lines.append("") with open(sys.argv[2], "w", encoding="utf-8") as f: f.write("\n".join(lines))

这里的format_timestamp把秒数换算成 SRT 标准时间格式。生成后可以直接用播放器加载,检查字幕是否和语音对齐。

实际校对时有几个重点:

  • 第一遍看时间轴:Whisper 对老动画的静音检测偶尔会偏早或偏晚,需要拖动播放器确认每句出现时机。
  • 第二遍看角色名:同一角色在整集中是否统一。
  • 第三遍看断句:如果 Whisper 把两句合在一段,翻译后中文会显得很长,影响观看体验。

机器翻译不可能完美,但初稿质量足够高的话,人工校对时间能压缩到原来的三分之一甚至更少。

6. 批量任务与接口调用优化

6.1 多集批量循环

如果是一个多集 OVA,建议直接在 shell 里跑循环,每集都走完整的“提取 → 转写 → 翻译 → 生成 SRT”流程。

for f in episodes/raw/*.mkv; do base=$(basename "$f" .mkv) python scripts/extract_audio.py "$f" "episodes/audio/$base.wav" python scripts/transcribe.py "episodes/audio/$base.wav" "episodes/asr/$base.json" python scripts/translate.py "episodes/asr/$base.json" "episodes/translation/$base.json" python scripts/build_srt.py "episodes/translation/$base.json" "episodes/srt/$base.srt" echo "done: $base" done

每集之间加一句echo日志,能帮助你定位是哪一集、哪一步失败。不要把所有错误堆到最后一并排查。

6.2 并发、重试与中间结果保存

DeepSeek API 调用属于网络请求,批量任务里最容易踩的坑是请求超时和速率限制。这时盲目并发反而会把问题放大。

更稳妥的做法是:

  • 每集单独串行处理,集与集之间不加并发。
  • 翻译阶段可以控制同时在途请求数,比如 4 个并发。
  • 对 401、429、500 这种状态码做重试,每次重试间隔递增。
  • 转写和翻译的中间结果全部落盘,避免一次失败后重头再来。

下面是一个简单的并发翻译池逻辑,只做示意:

from concurrent.futures import ThreadPoolExecutor, as_completed def safe_translate(batch): for retry in range(3): try: return translate_batch(batch) except Exception as e: print(f"retry {retry}: {e}") time.sleep(2 ** retry) return {} with ThreadPoolExecutor(max_workers=4) as executor: futures = [executor.submit(safe_translate, batch) for batch in batches] for future in as_completed(futures): result = future.result() # 合并结果

并发度不要盲目设高,具体上限要看 DeepSeek 官方 API 的限流策略。稳妥做法是先跑一集,观察请求耗时和失败率,再决定是否加并发。

6.3 提示词和术语表

批量处理多集内容时,角色名不一致是最大的痛点。第一集里叫“丽佳”的角色,第二集可能被翻译成“莉嘉”。

要解决这个问题,可以在提示词里固定一份角色名术语表:

角色名对照: - Lia -> 丽佳 - Bruno -> 布鲁诺 - Sofia -> 索菲亚

DeepSeek 会按照术语表生成翻译,多集之间的统一性会好很多。如果素材本身没有官方中文译名,建议先把所有转写文本跑一遍,统计高频人名,再确定术语表。

7. 资源占用与性能观察

这套流程里,本地资源占用最高的阶段是 faster-whisper 转写。

  • 如果选择small模型 + CPU + int8,普通 CPU 可以跑,但一部 30 分钟的动画可能需要较长时间,建议先转写前 5 分钟测试速度。
  • 如果选择 GPU +smallmedium模型,速度会有明显提升,显存占用也会增加。
  • 如果选择large-v3模型,转写质量最好,但显存和耗时都会明显增加。

具体显存数字不能一概而论,需要以本机nvidia-smi观察为准。我的建议是先跑一次小规模测试,记录峰值显存,再决定是否换更大模型。

DeepSeek 翻译阶段基本不占本地 GPU,只占网络和少量内存。因此整条流程对普通用户的硬件门槛不高。

要降低资源占用,几个思路:

  • 音轨统一转成 16kHz 单声道,减少推理输入。
  • 开启vad_filter,把静音和 BGM 片段过滤掉。
  • 优先用small模型生成初稿,质量不满意再局部重跑。
  • 批量任务不要在跑转写的同时开多个高内存程序。

8. 常见问题与排查方法

问题现象可能原因排查方式解决方案
API 返回 401API Key 未配置或配置错误检查环境变量 DEEPSEEK_API_KEY 是否生效重新设置环境变量,确认没有多余空格
API 请求超时网络波动或单次请求文本过长查看日志中的超时时长和请求字符数减小单批文本长度,增大 timeout
翻译结果行号丢失模型输出格式不稳定打印原始返回内容,检查是否包含 Markdown 列表在提示词中要求严格输出 编号: 文本,并做容错解析
角色名前后不一致未提供术语表对比多集字幕中的同一角色在提示词中加入角色名对照表
时间轴整体偏移Whisper 对静音检测不准播放器加载 SRT,观察前几句是否滞后用字幕编辑工具整体平移时间轴
某一句漏译Whisper 把两个句子合并或音频有噪音查看转写 JSON 中该时间点是否有文本调整 beam_size 或启用 VAD,必要时人工补听
中文翻译过长葡语原文跨多句,导致单条字幕过长检查转写段落是否按句断开在转写后增加分句逻辑,或翻译后二次切分
CPU 转写太慢模型较大或音频过长查看脚本耗时换 small 模型,或改用 GPU 推理

排查问题的顺序建议是:先看日志,再看中间 JSON,最后看原始音频。不要一上来就改提示词或模型参数,先定位是哪个环节出问题。

9. 最佳实践与合规提醒

这套流程能做很多事,但工程化和合规意识必须同步跟上。

第一步,先跑通一集,不要直接把十几集全部扔进循环。第一集的目的是验证音轨质量、Whisper 转写准确率和 DeepSeek 翻译风格是否符合预期。如果第一集就有大量漏译,后面批量跑再多次也是浪费。

第二步,把中间产物当资产管理。转写 JSON 和翻译 JSON 都保留,后续想换模型重新翻译,不需要再转写音频。批量任务建议每次运行都写日志,包括开始时间、结束时间、成功/失败状态、耗时。

第三步,控制接口并发。批量任务里最怕的不是 API 慢,而是无差别重试导致限流加重。重试要有退避策略,并做好最大重试次数限制。

第四步,明确版权边界。这里再次强调:你只能处理自己有合法使用权限的片源和音轨。涉及他人肖像、声音、未公开内容时,不要上传到第三方 API。如果要把字幕公开发布,需要确认原片版权方是否允许二次创作、翻译和字幕分发。即使是老动画,版权状态也可能很复杂。

第五步,机器翻译结果要人工复核。尤其涉及剧情关键信息、角色关系、专有名词时,不能直接照搬。字幕是给人看的,错误译名会直接影响观看体验。

10. 总结与下一步

这套 DeepSeek 字幕工作流的核心价值,是把“听译 + 翻译”变成了可复用的脚本管道。对 1990 年这种老 OVA 素材,转写难点在音轨质量和口语化文本,翻译难点在术语统一和字幕长度控制,但只要把中间流程固定下来,处理多集内容就是反复执行同一套工序。

建议你拿到项目后先跑第 5 节的最小示例,用一集素材验证转写质量、API 翻译效果和 SRT 时间轴。确认没问题后,再加批量循环、并发控制和术语表。最容易踩的坑集中在三个地方:API 返回格式不稳定导致行号错位、批量任务里没有保存中间结果、时间轴漂移后没有及时人工校正。

后续可以继续扩展的方向也很多。比如把转写结果按句号、问号智能分句;把角色名术语表抽成独立配置文件;加上字幕预览工具,一键加载视频和 SRT 进行校对。甚至可以把整条流程封装成命令行工具,让非技术成员也能使用。AI 字幕翻译的体验,关键不在于模型多强,而在于流程是否顺滑。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询