每天刷 YouTube 的时候,总能看到优质的 AI 教程、技术演讲和产品发布。问题来了——大部分没有中文字幕。靠听的,偶尔漏几句;靠浏览器插件翻译,质量参差不齐,还经常断在 buffering 上。

手动做字幕?一个 10 分钟的视频,听写、断句、翻译、调时间轴,至少花一个小时。如果是一小时的视频,一下午就搭进去了。

所以我把整个流程自动化了:下载视频 → 转录英文 → 翻译中文 → 烧录字幕,端到端跑完大概 3 分钟(取决于视频长度)。这篇文章把每一步拆开讲,给你所有可以直接复制的命令和代码。

整体工作流

先看全貌:

1
2
3
4
5
6
7
YouTube 链接
→ yt-dlp 下载视频
→ ffmpeg 提取音频
→ Whisper 语音识别,生成英文字幕 (SRT)
→ 翻译成中文 (SRT)
→ moviepy 烧录双语字幕到视频
→ (可选) ffmpeg 截取 GIF 预览

需要安装的工具:yt-dlpffmpeg、Python 3.10+,以及几个 Python 库。下面一步步来。

第一步:用 yt-dlp 下载视频

yt-dlpyoutube-dl 的活跃分支,下载速度快,格式支持全。

1
2
3
4
5
6
7
# 安装
pip install -U yt-dlp

# 下载视频(最佳画质,mp4 优先)
yt-dlp -f "bv*[ext=mp4]+ba[ext=m4a]/b[ext=mp4]/b" \
-o "%(title)s.%(ext)s" \
"https://www.youtube.com/watch?v=VIDEO_ID"

如果只需要音频来做转录,可以跳过视频下载,直接拿音频:

1
2
3
yt-dlp -x --audio-format mp3 \
-o "audio.%(ext)s" \
"https://www.youtube.com/watch?v=VIDEO_ID"

但后面烧录字幕需要视频文件,所以一般情况下还是下载完整视频。

第二步:用 ffmpeg 提取音频

Whisper 处理的是音频文件,所以需要从视频里提取出来:

1
ffmpeg -i input.mp4 -vn -acodec pcm_s16le -ar 16000 -ac 1 audio.wav

参数解释:

  • -vn:不要视频流
  • -ar 16000:采样率 16kHz,Whisper 的推荐值
  • -ac 1:单声道,识别效果更稳定

这一步很快,通常几秒钟。

第三步:用 Whisper 自动语音识别

Whisper 是 OpenAI 开源的语音识别模型,支持 99 种语言。对于英文视频,识别准确率非常高。

1
2
3
4
5
6
7
8
9
# 安装
pip install -U openai-whisper

# 转录并直接输出 SRT 字幕文件
whisper audio.wav \
--model medium \
--language en \
--output_format srt \
--output_dir ./

模型大小选择:

  • tiny / base:速度快,准确率一般,适合短视频
  • small:平衡选择,10 分钟视频大概 1 分钟跑完
  • medium:准确率高,需要 5GB 显存
  • large:最高准确率,显存需求大,速度慢

没有 GPU 也能跑,就是慢一些。M 系列 Mac 用 MPS 后端还挺快的。

运行完你会得到 audio.srt,这就是英文字幕文件。

也可以在 Python 里调用,方便后续流水线串联:

1
2
3
4
5
6
7
8
9
10
import whisper

model = whisper.load_model("medium")
result = model.transcribe("audio.wav", language="en", verbose=False)

# 生成 SRT 格式
from whisper.utils import get_writer
with open("audio.srt", "w", encoding="utf-8") as f:
writer = get_writer("srt", ".")
writer(result, "audio.wav", {"highlight_words": False})

第四步:翻译成中文

拿到英文 SRT 之后,需要把每一条字幕翻译成中文。直接用全文翻译会比逐条翻译更连贯,因为上下文能保留。

这里用 OpenAI 的 API 来做翻译,你也可以换成其他大模型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import re

def parse_srt(content):
"""解析 SRT 文件,返回 [(index, timestamp, text)] 列表"""
blocks = re.split(r'\n\s*\n', content.strip())
entries = []
for block in blocks:
lines = block.strip().split('\n')
if len(lines) >= 3:
index = lines[0].strip()
timestamp = lines[1].strip()
text = '\n'.join(lines[2:])
entries.append((index, timestamp, text))
return entries

def translate_srt(input_path, output_path, api_key):
from openai import OpenAI
client = OpenAI(api_key=api_key)

with open(input_path, 'r', encoding='utf-8') as f:
content = f.read()

entries = parse_srt(content)

# 把所有文本拼成一段,用分隔符标记
texts = [e[2] for e in entries]
combined = '\n|||\n'.join(texts)

prompt = f"""将以下英文字幕翻译成中文。保持原文的换行和分隔符 |||,
输出格式和输入完全对应,不要增减分隔符的数量:

{combined}"""

resp = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "你是一个专业的视频字幕翻译,翻译简洁自然,适合阅读。"},
{"role": "user", "content": prompt}
],
temperature=0.3
)

translated = resp.choices[0].message.content.strip()
translated_texts = translated.split('\n|||\n')

# 重新组装 SRT
with open(output_path, 'w', encoding='utf-8') as f:
for i, (index, timestamp, _) in enumerate(entries):
f.write(f"{index}\n{timestamp}\n{translated_texts[i].strip()}\n\n")

print(f"翻译完成: {output_path}")

# 使用
translate_srt("audio.srt", "audio_zh.srt", "your-api-key")

想做成双语字幕?把原文和翻译拼在一起就行:

1
2
3
4
5
6
7
8
9
10
def make_bilingual_srt(en_srt, zh_srt, output_path):
"""合并英文和中文 SRT 为双语字幕"""
with open(en_srt, 'r') as f:
en_entries = parse_srt(f.read())
with open(zh_srt, 'r') as f:
zh_entries = parse_srt(f.read())

with open(output_path, 'w', encoding='utf-8') as f:
for (idx, ts, en_text), (_, _, zh_text) in zip(en_entries, zh_entries):
f.write(f"{idx}\n{ts}\n{en_text.strip()}\n{zh_text.strip()}\n\n")

第五步:用 moviepy 烧录字幕到视频

字幕文件准备好了,最后一步是把字幕”烧”进视频画面里。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from moviepy.editor import VideoFileClip, TextClip, CompositeVideoClip
from moviepy.video.tools.subtitles import SubtitlesClip

def burn_subtitles(video_path, srt_path, output_path, font_size=24):
video = VideoFileClip(video_path)

# 生成字幕片段
def make_text_clip(txt):
# 支持多行(双语字幕)
return TextClip(
txt,
fontsize=font_size,
font='Arial', # Mac 上可以用 'PingFang-SC' 显示中文
color='white',
stroke_color='black',
stroke_width=1,
method='caption',
size=(video.w * 0.9, None),
align='south'
)

subtitles = SubtitlesClip(srt_path, make_text_clip)
subtitles = subtitles.set_position(('center', 0.85), relative=True)

result = CompositeVideoClip([video, subtitles])
result.write_videofile(
output_path,
codec='libx264',
audio_codec='aac',
fps=video.fps,
threads=4
)
video.close()

# 烧录双语字幕
burn_subtitles("input.mp4", "bilingual.srt", "output.mp4")

几个注意点:

  • Mac 上显示中文,字体改成 'PingFang-SC'/System/Library/Fonts/PingFang.ttc
  • ImageMagick 是 moviepy 的依赖,Mac 上用 brew install imagemagick 安装
  • 烧录速度取决于视频长度和 CPU,10 分钟视频大概 2-3 分钟

第六步:生成 GIF 预览

做完视频,顺手截一段 GIF 预览,方便分享:

1
2
3
4
# 截取第 30 秒开始的 5 秒,生成 GIF
ffmpeg -ss 30 -t 5 -i output.mp4 \
-vf "fps=15,scale=480:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" \
-loop 0 preview.gif

-ss 30 是起始时间,-t 5 是时长,scale=480 限制宽度,保持 GIF 体积可控。

进阶:用 edge-tts 做中文配音

如果光看字幕还不够,想加上中文语音旁白,可以用微软的 edge-tts,免费且效果不错。

1
pip install edge-tts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import edge_tts
import asyncio

async def generate_tts(text, output_path):
# 选择中文语音
voice = "zh-CN-YunxiNeural" # 男声,自然流畅
communicate = edge_tts.Communicate(text, voice)
await communicate.save(output_path)

# 把中文字幕文本合并,生成配音
with open("audio_zh.srt", "r") as f:
zh_text = " ".join(line.strip() for line in f.readlines()
if line.strip() and not line.strip().isdigit()
and "-->" not in line)

asyncio.run(generate_tts(zh_text, "chinese_voice.mp3"))

可用中文语音列表:

1
edge-tts --list-voices | grep zh-CN

推荐几个:

  • zh-CN-YunxiNeural:男声,年轻自然
  • zh-CN-XiaoxiaoNeural:女声,温柔清晰
  • zh-CN-YunjianNeural:男声,沉稳有力

然后把配音替换到视频里:

1
2
3
ffmpeg -i output.mp4 -i chinese_voice.mp3 \
-c:v copy -c:a aac -map 0:v:0 -map 1:a:0 \
final.mp4

注意配音时长要和视频时长大致匹配,如果差太多可以用 ffmpegatempo 滤镜调速。

一键脚本

把上面的步骤串起来,做成一个完整脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#!/usr/bin/env python3
"""YouTube 视频自动翻译字幕工具"""
import subprocess
import sys
import os

def main(youtube_url, api_key=None):
# 1. 下载视频
print("📥 下载视频...")
subprocess.run([
"yt-dlp", "-f", "bv*[ext=mp4]+ba[ext=m4a]/b",
"-o", "input.%(ext)s", youtube_url
], check=True)

# 2. 提取音频
print("🎵 提取音频...")
subprocess.run([
"ffmpeg", "-y", "-i", "input.mp4",
"-vn", "-acodec", "pcm_s16le", "-ar", "16000", "-ac", "1",
"audio.wav"
], check=True)

# 3. Whisper 转录
print("🗣️ 语音识别...")
subprocess.run([
"whisper", "audio.wav",
"--model", "medium", "--language", "en",
"--output_format", "srt", "--output_dir", "./"
], check=True)

# 4. 翻译
if api_key:
print("🌐 翻译中文字幕...")
translate_srt("audio.srt", "audio_zh.srt", api_key)
make_bilingual_srt("audio.srt", "audio_zh.srt", "bilingual.srt")
srt_file = "bilingual.srt"
else:
srt_file = "audio.srt"

# 5. 烧录字幕
print("🎬 烧录字幕...")
burn_subtitles("input.mp4", srt_file, "output.mp4")

# 6. GIF 预览
print("🖼️ 生成 GIF...")
subprocess.run([
"ffmpeg", "-y", "-ss", "10", "-t", "5", "-i", "output.mp4",
"-vf", "fps=15,scale=480:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse",
"-loop", "0", "preview.gif"
], check=True)

print("✅ 完成!输出文件: output.mp4, preview.gif")

if __name__ == "__main__":
url = sys.argv[1]
key = sys.argv[2] if len(sys.argv) > 2 else None
main(url, key)

用法:

1
2
3
4
5
# 只有英文字幕
python translate.py "https://www.youtube.com/watch?v=XXXX"

# 双语字幕 + 中文翻译
python translate.py "https://www.youtube.com/watch?v=XXXX" "sk-your-api-key"

小结

整个流程跑通之后,看 YouTube 技术视频的体验完全不一样了。3 分钟自动出字幕,比手动快了 20 倍,而且 Whisper 的识别准确率在英文清晰的情况下能到 95% 以上。

几个可以继续优化的方向:

  • 批量处理:丢一个播放列表链接进去,自动逐个翻译
  • 术语表:给翻译模型一份术语对照表,保证技术名词一致性
  • 样式定制:字幕字体、颜色、描边、位置全部可调
  • 内容摘要:翻译完之后顺手让大模型生成一份视频摘要

工具链都是开源的,跑起来零成本(除了翻译 API 的几毛钱)。周末花一个小时搭好环境,以后就是一键的事。

参考链接