环境
- 环境变量可以找到ffmpeg
- PC安装python
原始问题
目录D:\UE_mp4\source下有许多子文件夹,子文件夹中包含很多mp4文件,每个mp4的格式为filename.mp4,并且同目录下可能存在filename.en.srt,filename.srt,如果存在一种字幕文件使用ffmpeg合入到mp4文件里,如果存在两种字幕文件先合并字幕文件再把合并后的字幕文件合入到mp4文件中,
我的PC性能很强,使用10个进程同时处理,
合并后的文件按照原目录结构输出到D:\UE_mp4\test_merge目录下
给出的代码
import os
import shutil
import subprocess
from concurrent.futures import ProcessPoolExecutor
source_dir = r'D:\UE_mp4\source'
target_dir = r'D:\UE_mp4\test_merge'
processes = 10 # 你想要使用的进程数
def combine_subtitles(eng_subtitle, chn_subtitle, combined_subtitle):
with open(eng_subtitle, 'r', encoding='utf-8') as eng, open(chn_subtitle, 'r', encoding='utf-8') as chn:
with open(combined_subtitle, 'w', encoding='utf-8') as combined:
subtitle_number = 1
while True:
eng_number = eng.readline()
chn_number = chn.readline()
# 判断是否到达文件末尾
if not eng_number or not chn_number:
break
eng_time = eng.readline()
chn_time = chn.readline()
# 读取并合并字幕内容,直到遇到空行
eng_content = ""
chn_content = ""
line = eng.readline()
while line.strip() != "":
eng_content += line
line = eng.readline()
line = chn.readline()
while line.strip() != "":
chn_content += line
line = chn.readline()
# 写入合并后的字幕
combined.write(f"{subtitle_number}\n")
combined.write(eng_time) # 由于时间线应该相同,只写入一次
combined.write(eng_content)
combined.write(chn_content)
combined.write("\n") # 在字幕块之间添加空行
subtitle_number += 1
def merge_subtitles_and_video(video_file, subtitle_file, target_file):
command = [
'ffmpeg',
'-i', video_file,
'-i', subtitle_file,
'-c', 'copy',
'-c:s', 'mov_text', # 使用mov_text选项来编码字幕
target_file
]
subprocess.run(command, check=True)
def process_video(root, file):
# 构建视频和可能的字幕文件路径
video_path = os.path.join(root, file)
subtitle_en_path = os.path.splitext(video_path)[0] + '.en.srt'
subtitle_path = os.path.splitext(video_path)[0] + '.srt'
combined_subtitle_path = os.path.splitext(video_path)[0] + '.combined.srt'
target_path = root.replace(source_dir, target_dir)
# 确保目标目录存在
if not os.path.exists(target_path):
os.makedirs(target_path)
# 合并字幕(如果存在两种字幕)
if os.path.exists(subtitle_en_path) and os.path.exists(subtitle_path):
combine_subtitles(subtitle_en_path, subtitle_path, combined_subtitle_path)
subtitle_to_use = combined_subtitle_path
elif os.path.exists(subtitle_en_path):
subtitle_to_use = subtitle_en_path
elif os.path.exists(subtitle_path):
subtitle_to_use = subtitle_path
else:
subtitle_to_use = None
# 构建目标视频文件路径
target_video_path = os.path.join(target_path, file)
# 如果存在字幕文件,则合并
if subtitle_to_use:
merge_subtitles_and_video(video_path, subtitle_to_use, target_video_path)
else:
# 如果不存在字幕文件,只复制视频文件
shutil.copy2(video_path, target_video_path)
# 清理临时合并的字幕文件
if os.path.exists(combined_subtitle_path):
os.remove(combined_subtitle_path)
# 遍历源目录并找到所有的视频文件
def main():
with ProcessPoolExecutor(max_workers=processes) as executor:
for root, dirs, files in os.walk(source_dir):
for file in files:
if file.lower().endswith('.mp4'):
executor.submit(process_video, root, file)
if __name__ == '__main__':
main()