当前位置: 首页 > news >正文

【Python】从 MP4 文件中提取中英双语字幕并生成双语字幕文件(如 .srt)

文章目录

    • 🎯 目标
    • ✅ 所需工具与库
      • 安装依赖
    • 🔍 第一步:查看 MP4 中的字幕轨道
    • 📥 第二步:用 ffmpeg 提取字幕为 .srt 文件
    • 🔗 第三步:合并中英文字幕为双语字幕
    • ✅ 改进版:智能时间匹配合并双语字幕(推荐脚本)
      • 🔧 使用方法
    • ✅ 最终成果
    • 💡 补充说明
    • 🧩 完整脚本结构概览
    • 🚀 进阶建议

在 Windows 系统下使用 Python 从 MP4 文件中提取中英双语字幕并生成双语字幕文件(如 .srt),可以分为以下几个步骤:


🎯 目标

  1. 从 MP4 文件中提取内嵌的中文和英文字幕流。
  2. 将提取出的字幕转换为标准 .srt 格式。
  3. 合并中英文字幕,生成 双语字幕(例如:上行英文,下行中文)。

✅ 所需工具与库

  • ffmpeg:用于提取字幕流(MP4 中可能包含 subripassmov_text 等格式的内嵌字幕)
  • pysubs2:处理 SRT/ASS 字幕格式,支持转换和合并
  • Python 3.x

安装依赖

pip install pysubs2

注意:你需要先安装 ffmpeg 并将其加入系统 PATH。可从官网下载或使用 https://www.gyan.dev/ffmpeg/builds/ 提供的 Windows 构建版本。


🔍 第一步:查看 MP4 中的字幕轨道

使用 ffprobe(ffmpeg 自带)来检查有哪些字幕流:

import subprocess
import jsondef list_subtitle_streams(video_path):cmd = ['ffprobe','-v', 'quiet','-print_format', 'json','-show_streams','-select_streams', 's',  # 只看字幕流video_path]result = subprocess.run(cmd, capture_output=True, text=True)data = json.loads(result.stdout)subtitles = []for i, stream in enumerate(data['streams']):tags = stream.get('tags', {})language = tags.get('language', 'und')subtype = stream.get('codec_name', '')title = tags.get('title', '')subtitles.append({'index': stream['index'],'type': subtype,'lang': language,'title': title,'tags': tags})print(f"[{i}] Index: {stream['index']}, Lang: {language}, Title: {title}, Type: {subtype}")return subtitles# 示例调用
video_file = "example.mp4"
subs = list_subtitle_streams(video_file)

输出示例:

[0] Index: 3, Lang: eng, Type: mov_text
[1] Index: 4, Lang: chi, Type: mov_text

记下英文和中文对应的 index(比如 3 和 4)。


📥 第二步:用 ffmpeg 提取字幕为 .srt 文件

def extract_subtitle_stream(video_path, stream_index, output_srt):cmd = ['ffmpeg','-i', video_path,'-map', f'0:{stream_index}','-c:s', 'srt',output_srt,'-y'  # 覆盖输出]result = subprocess.run(cmd, capture_output=True, text=True)if result.returncode == 0:print(f"✅ 成功提取字幕到 {output_srt}")else:print("❌ 提取失败:", result.stderr)raise Exception(result.stderr)# 提取英文和中文字幕
extract_subtitle_stream(video_file, stream_index=3, output_srt="en.srt")
extract_subtitle_stream(video_file, stream_index=4, output_srt="zh.srt")

⚠️ 如果原始字幕是 mov_text 类型,ffmpeg 可以直接转成 .srt;如果是 ass 或其他复杂格式,建议先保存为 .ass 再用 pysubs2 处理。


🔗 第三步:合并中英文字幕为双语字幕

使用 pysubs2 读取两个 .srt 文件,并按时间轴合并。

import pysubs2def create_bilingual_srt(en_srt_path, zh_srt_path, output_path):# 加载字幕en_subs = pysubs2.load(en_srt_path, encoding="utf-8")zh_subs = pysubs2.load(zh_srt_path, encoding="utf-8")# 创建新的字幕对象bilingual_subs = pysubs2.SSAFile()# 按事件时间合并from collections import defaultdictmerged_events = defaultdict(dict)# 添加英文字幕for ev in en_subs:key = (ev.start, ev.end)merged_events[key]['en'] = ev.text# 添加中文字幕for ev in zh_subs:key = (ev.start, ev.end)merged_events[key]['zh'] = ev.text# 构造双语字幕for (start, end), texts in merged_events.items():en_text = texts.get('en', '')zh_text = texts.get('zh', '')# 双语格式:上英下中combined_text = f"{en_text}\n{zh_text}" if en_text and zh_text else (en_text or zh_text)new_event = pysubs2.SSAEvent(start=start, end=end, text=combined_text)bilingual_subs.events.append(new_event)# 排序bilingual_subs.sort()# 保存bilingual_subs.save(output_path, encoding="utf-8-sig")  # utf-8-sig 防止乱码print(f"🎉 双语字幕已保存至: {output_path}")# 调用函数
create_bilingual_srt("en.srt", "zh.srt", "bilingual.srt")

✅ 改进版:智能时间匹配合并双语字幕(推荐脚本)

import pysubs2
from typing import List, Tupledef check_subtitle_order(subs: pysubs2.ssafile.SSAFile) -> bool:"""检查字幕的顺序是否正确"""for i in range(len(subs) - 1):if subs[i].end > subs[i + 1].start:return Falsereturn Truedef merge_subtitles(zh_path: str, en_path: str, output_path: str):# 加载字幕zh_subs = pysubs2.load(zh_path, encoding="utf-8")en_subs = pysubs2.load(en_path, encoding="utf-8")# 按开始时间排序zh_subs.sort()en_subs.sort()# 检查字幕的顺序是否正确if not check_subtitle_order(zh_subs) or not check_subtitle_order(en_subs):raise ValueError("❌ 字幕顺序错误,请检查!")# 合并所有事件(中文 + 英文),然后按开始时间排序all_events = []for event in zh_subs:all_events.append(("zh", event.start, event.end, event.text))for event in en_subs:all_events.append(("en", event.start, event.end, event.text))# 按开始时间排序all_events.sort(key=lambda x: x[1])all_events_org = all_events.copy()subs_result = []i = 0while i < len(all_events) - 1:kind, start, end, text = all_events[i]kind2, start2, end2, text2 = all_events[i + 1]zh_line = text if kind == 'zh' else Noneen_line = text if kind == 'en' else None# 第一种情况:如果两个事件无重叠,则直接输出if start2 >= end:subs_result.append((start, end, zh_line, en_line))# 第二种情况:如果两个事件有重叠,且 end < end2elif end <= end2:subs_result.append((start, start2, zh_line, en_line))zh_line = text if kind == 'zh' else text2en_line = text2 if kind2 == 'en' else textsubs_result.append((start2, end, zh_line, en_line))all_events[i + 1] = (kind2, end, end2, text2)# 第三种情况:如果两个事件有重叠,且 end > end2elif end > end2:subs_result.append((start, start2, zh_line, en_line))zh_line = text if kind == 'zh' else text2en_line = text2 if kind2 == 'en' else textsubs_result.append((start2, end2, zh_line, en_line))all_events[i] = (kind, end2, end, text)i += 1i += 1if i == len(all_events) - 1:kind, start, end, text = all_events[i]zh_line = text if kind == 'zh' else Noneen_line = text if kind == 'en' else Nonesubs_result.append((start, end, zh_line, en_line))def get_subs_merge(subs_result: List[Tuple[int, int, str, str]]):subs_merge = []i = 0while i < len(subs_result) - 1:# 对于中文和英文有一个为空,且另一个重复的两行,进行合并zh_line = subs_result[i][2]en_line = subs_result[i][3]zh_line_next = subs_result[i + 1][2]en_line_next = subs_result[i + 1][3]start = subs_result[i][0]end = subs_result[i][1]start_next = subs_result[i + 1][0]end_next = subs_result[i + 1][1]if zh_line == zh_line_next and en_line == en_line_next:subs_merge.append((min(start, start_next), max(end, end_next), zh_line, en_line))i += 2continueelif (en_line is None or en_line_next is None) and zh_line == zh_line_next:if en_line is None:en_line = en_line_nextsubs_merge.append((min(start, start_next), max(end, end_next), zh_line, en_line))i += 2continueelif (zh_line is None or zh_line_next is None) and en_line == en_line_next:if zh_line is None:zh_line = zh_line_nextsubs_merge.append((min(start, start_next), max(end, end_next), zh_line, en_line))i += 2continuesubs_merge.append(subs_result[i])i += 1if i == len(subs_result) - 1:subs_merge.append(subs_result[i])return subs_mergesubs_merge = get_subs_merge(subs_result)while len(subs_merge) != len(subs_result):subs_result = subs_mergesubs_merge = get_subs_merge(subs_result)# 构建输出字幕对象merged_subs = pysubs2.SSAFile()for t0, t1, zh_line, en_line in subs_merge:# 添加到输出字幕event = pysubs2.SSAEvent()event.start = t0event.end = t1event.text = f'{zh_line}\n{en_line}'merged_subs.events.append(event)merged_subs.save(output_path, encoding="utf-8")print(f"✅ 双语字幕已保存至: {output_path}")

🔧 使用方法

merge_subtitles("en.srt", "zh.srt", "bilingual_aligned.srt")

✅ 最终成果

你将得到一个 bilingual.srt 文件,每条字幕显示为:

1
00:00:10,000 --> 00:00:13,000
你好,最近怎么样?
Hello, how are you?

💡 补充说明

问题解决方案
字幕编码乱码使用 encoding="utf-8-sig" 或尝试 "gbk"
时间轴不匹配使用 pysubs2.adjust() 方法对齐或做时间插值
MP4 无内嵌字幕此方法无效,需 OCR 提取(可用 VSR 工具 + paddleOCR
外挂字幕直接加载 .srt 文件即可

🧩 完整脚本结构概览

# main.py
1. list_subtitle_streams(video.mp4)
2. extract_subtitle_stream(... index=3 -> en.srt)
3. extract_subtitle_stream(... index=4 -> zh.srt)
# 4. create_bilingual_srt("en.srt", "zh.srt", "bilingual.srt")
4. merge_subtitles("en.srt", "zh.srt", "bilingual_aligned.srt")

🚀 进阶建议

  • 使用 pysubs2 支持样式定制(字体、颜色等)。
  • 若想生成外挂双语字幕供播放器使用,可将 .srt 放在视频同目录并重命名为 video.chi.eng.srt
  • 批量处理多个视频?加个 os.listdir() 循环即可。
http://www.dtcms.com/a/479774.html

相关文章:

  • 基于ffmpeg库,在AGX上编译jetsonFFmpeg库带有硬件加速的h264_nvmpi视频编解码器
  • wordpress熊掌号自动提交seo如何使用wordpress优化
  • 网站维护费一般多少钱湖南好搜网站建设
  • 机器人软件开发和网站开发wordpress后台登录
  • 3d演示中国空间站建造历程牡丹江建站
  • 服务器网站管理系统泰山信息科技有限公司
  • 网站备案是域名备案还是服务器备案长沙房价一览表
  • 行业网站名称广州公司网站托管
  • wordpress站点地址写错网页设计师考试报名
  • 保定涿州网站建设网站开发人员的工作
  • [Qlib] 数据处理`DataHandlerLP` | `Alpha158`
  • wordpress批量拿站263企业邮箱腾讯登录入口
  • 网站图片设置方法在网站上做远程教育系统多少钱
  • 深度学习(三)
  • 珠海本地网站设计公司做网站售后好的公司
  • 门户网站宣传方案做一个网站如何赚钱
  • 网站开发设计流程文档广告网页推广方案
  • 网站维护模式移动网站适配
  • 营销网站建设的目的北京百度总部电话
  • C++STL---静态数组array
  • 东莞樟木头网站设计使用vue做简单网站教程
  • 济南想建设网站长宁网站建设价格
  • 【开题答辩全过程】以 保定基于java的超市库存管理系统为例,包含答辩的问题和答案
  • 设计好的建设专业网站上海新建设建筑设计有限公司网站
  • 建立一个团购网站需要多少钱昭通微网站建设
  • 基于 Oracle 数据泵(expdp/impdp) 的数据导入导出
  • Oracle RAC Global Cache Load Profile
  • 关于做网站的毕业设计如何制作简单的网站
  • AI大模型的市场目前怎么样?
  • self attention, masked self attention, cross attention