Skip to content

用 GPT API 批量翻译 SRT 字幕 ​

一句话: 下载下面的脚本,设置好 HiveGPT 的 Key,运行 python translate_srt.py 视频.srt --bilingual,就会得到保留原时间轴的双语字幕 视频.bilingual.srt。一集 20 分钟的视频(约 300 条字幕)用 gpt-6-luna 翻译,大约几美分。

更新于 2026-10,脚本在 HiveGPT 上实际跑过:40 条字幕约 30 秒、花费约 $0.0013。

准备 ​

  • Python 3.9 以上,安装 SDK:pip install -U openai
  • 一个 HiveGPT 的 API Key(API 密钥 页创建,分组选 GPT 类分组),放进环境变量:
bash
export HIVEGPT_API_KEY="sk-你的Key"        # macOS / Linux
set HIVEGPT_API_KEY=sk-你的Key             # Windows CMD
  • 一个 .srt 字幕文件。没有字幕的视频,可以先用剪映、Whisper 等工具识别出原文字幕。

脚本 ​

保存为 translate_srt.py:

python
"""把 SRT 字幕翻译成中文(或其他语言),保留编号和时间轴。

用法:
    python translate_srt.py input.srt                 # 输出 input.zh.srt(只有译文)
    python translate_srt.py input.srt --bilingual     # 双语:译文在上,原文在下
    python translate_srt.py input.srt --to 日语 --model gpt-6.1-sol
"""
import argparse, json, os, re, sys, time
from concurrent.futures import ThreadPoolExecutor
from openai import OpenAI

client = OpenAI(base_url="https://hivegpt.cn/v1", api_key=os.environ["HIVEGPT_API_KEY"], timeout=300)

BATCH = 30        # 每次请求翻译多少条字幕
WORKERS = 4       # 同时发几个请求;遇到 429 就调小
EFFORT = "low"    # 推理强度:none / low / medium …,模型不支持 none 时用 low
usage = [0, 0]    # 累计输入、输出 token


def parse_srt(text):
    """返回 [(编号, 时间轴, 字幕文本)]。"""
    blocks = re.split(r"\n\s*\n", text.replace("\r\n", "\n").strip())
    items = []
    for b in blocks:
        lines = b.strip().split("\n")
        if len(lines) >= 2 and "-->" in lines[1]:
            items.append((lines[0].strip(), lines[1].strip(), "\n".join(lines[2:]).strip()))
    return items


SCHEMA = {
    "type": "object",
    "properties": {"items": {"type": "array", "items": {
        "type": "object",
        "properties": {"id": {"type": "integer"}, "text": {"type": "string"}},
        "required": ["id", "text"], "additionalProperties": False,
    }}},
    "required": ["items"], "additionalProperties": False,
}


def translate_batch(batch, target, model, context):
    """batch: [(序号, 原文)],返回 {序号: 译文}。编号对不上就重试。"""
    payload = [{"id": i, "text": t} for i, t in batch]
    for attempt in range(4):
        try:
            resp = client.chat.completions.create(
                model=model,
                messages=[
                    {"role": "system", "content": (
                        f"你是专业的字幕译者。把每条字幕翻译成{target},口语化、简洁,适合在屏幕上读。"
                        "每条单独翻译,不要合并或拆分,id 原样返回;人名、品牌名保留原文。"
                        + (f"\n视频背景:{context}" if context else ""))},
                    {"role": "user", "content": json.dumps(payload, ensure_ascii=False)},
                ],
                response_format={"type": "json_schema", "json_schema": {"name": "subs", "strict": True, "schema": SCHEMA}},
                reasoning_effort=EFFORT,  # 翻译不需要深度推理,调低了快很多也省钱
            )
            usage[0] += resp.usage.prompt_tokens
            usage[1] += resp.usage.completion_tokens
            out = {it["id"]: it["text"].strip() for it in json.loads(resp.choices[0].message.content)["items"]}
            if set(out) == {i for i, _ in batch}:
                return out
            print(f"  第 {batch[0][0]} 条起的一批:返回条数不对,重试", file=sys.stderr)
        except Exception as e:  # 429、超时等:等一会儿再试
            print(f"  第 {batch[0][0]} 条起的一批出错:{e},重试", file=sys.stderr)
        time.sleep(2 ** attempt)
    raise RuntimeError(f"第 {batch[0][0]} 条起的一批翻译失败")


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("srt")
    ap.add_argument("--to", default="简体中文")
    ap.add_argument("--model", default="gpt-6-luna")
    ap.add_argument("--bilingual", action="store_true")
    ap.add_argument("--context", default="", help="一句话说明视频内容,帮助统一术语")
    args = ap.parse_args()

    items = parse_srt(open(args.srt, encoding="utf-8-sig").read())
    texts = [(n, t) for n, (_, _, t) in enumerate(items)]
    batches = [texts[i:i + BATCH] for i in range(0, len(texts), BATCH)]
    print(f"{len(items)} 条字幕,分 {len(batches)} 批翻译…", file=sys.stderr)

    translated = {}
    with ThreadPoolExecutor(WORKERS) as pool:
        for part in pool.map(lambda b: translate_batch(b, args.to, args.model, args.context), batches):
            translated.update(part)

    out_path = re.sub(r"\.srt$", "", args.srt) + (".bilingual.srt" if args.bilingual else ".zh.srt")
    with open(out_path, "w", encoding="utf-8") as f:
        for n, (idx, timing, text) in enumerate(items):
            body = translated[n] + ("\n" + text if args.bilingual else "")
            f.write(f"{idx}\n{timing}\n{body}\n\n")
    print(f"完成:{out_path}(输入 {usage[0]} token,输出 {usage[1]} token)", file=sys.stderr)


if __name__ == "__main__":
    main()

运行 ​

bash
python translate_srt.py 视频.srt                          # 只有译文:视频.zh.srt
python translate_srt.py 视频.srt --bilingual              # 双语:视频.bilingual.srt
python translate_srt.py 视频.srt --context "Vite + React 入门教程"   # 告诉模型视频讲什么,术语更准
python translate_srt.py 视频.srt --to 日语 --model gpt-6.1-sol

翻译效果(双语模式):

text
1
00:00:00,000 --> 00:00:02,500
大家好,欢迎回到我们的频道。
Hi everyone, welcome back to the channel.

2
00:00:03,000 --> 00:00:05,500
今天我们来做一个小型 Web 应用。
Today we're going to build a tiny web app.

生成的 .srt 可以直接拖进播放器(PotPlayer、IINA、VLC),或导入剪映、Premiere 等剪辑软件。

脚本是怎么保证不乱的 ​

  • 按批翻译:每次发 30 条,比一条一条发快得多、也便宜(固定的说明只发一次);又不会一次太多导致漏条。
  • 带编号返回:每条字幕带 id 发过去,用 JSON Schema 要求模型按 id 原样返回。返回的编号和发过去的对不上,就自动重试,所以不会出现译文错位。
  • 时间轴不经过模型:时间轴和编号由脚本原样写回,模型只碰文字,时间不会被改坏。
  • 调低推理强度:reasoning_effort="low"。翻译不需要深度推理,实测比默认设置快好几倍。

花多少钱 ​

字幕翻译主要是输入 token。实测 40 条英文短句用了约 9700 个输入 token、600 个输出 token:

模型40 条一集约 300 条
gpt-6-luna约 $0.0013约 $0.01
gpt-6.1-sol约 $0.025约 $0.2

日常视频用 gpt-6-luna 就够;专业内容(医学、法律、技术讲座)对术语要求高,换 gpt-6.1-sol 并加上 --context。各模型价格见 GPT 模型怎么选。

常见问题 ​

现象原因处理
KeyError: 'HIVEGPT_API_KEY'没设置环境变量按上面「准备」设置后,在同一个终端里运行
一直提示「返回条数不对,重试」字幕太长或太乱,模型漏条把 BATCH 调小到 15
429 / 请求太频繁并发太多把 WORKERS 调小到 1–2,见 429 报错
报 reasoning_effort 不支持模型不支持这个参数删掉 reasoning_effort=EFFORT 这一行
译文太书面、太长提示词不够具体改 system 提示词,例如「每条不超过 15 个字」
人名、术语前后不一致每批单独翻译用 --context 写上人名和术语,例如「主讲人 Ada,产品叫 Nova」
打开 srt 乱码原文件不是 UTF-8用记事本 / VS Code 另存为 UTF-8 再运行

能翻译 ASS、VTT 字幕吗? 这个脚本只处理 SRT。可以先用 FFmpeg 转格式:ffmpeg -i 视频.vtt 视频.srt。

能直接翻译视频里的声音吗? 要先把语音识别成字幕(剪映的「识别字幕」、Whisper 等),再用这个脚本翻译。

更多:批量总结文档 · 批量处理 Excel · Python 完整示例 · Bob、Pot 划词翻译

代码示例在页面里运行时使用 HiveGPT 的模型接口。延伸阅读来自 JavaGuide(Apache-2.0),版权归原作者。