doc2video / movie_editor.py
zhao1977's picture
Upload 15 files
dd74184 verified
from moviepy.editor import ImageClip, ColorClip, concatenate_videoclips, CompositeVideoClip
import os
import re
import natsort
from PIL import Image
import numpy as np
from concurrent.futures import ThreadPoolExecutor
def process_image(file, duration, target_size):
with Image.open(file) as img:
width, height = img.size
ratio = width / height
new_width, new_height = target_size
if width > target_size[0] or height > target_size[1]:
if ratio > target_size[0] / target_size[1]:
new_width = target_size[0]
new_height = int(new_width / ratio)
else:
new_height = target_size[1]
new_width = int(new_height * ratio)
resized_img = img.resize((new_width, new_height), resample=Image.Resampling.LANCZOS)
img_clip = ImageClip(np.array(resized_img)).set_duration(duration).set_position('center')
return img_clip
def images_to_video_with_durations(input_image_path, output_video_path, durations, fps, base_name):
# 获取所有符合条件的图片,并按文件名中的数字排序
pattern = re.compile(rf'^{re.escape(base_name)}_(\d+)\.png$')
image_files = [
os.path.join(input_image_path, file)
for file in os.listdir(input_image_path)
if pattern.match(file)
]
image_files = natsort.natsorted(image_files, key=lambda x: int(pattern.match(os.path.basename(x)).group(1)))
# 确定视频的背景尺寸
target_size = (1280, 720)
# 创建背景剪辑
bg_clip = ColorClip(size=target_size, color=(255, 255, 255), duration=sum(durations))
# 使用多线程处理图像文件
with ThreadPoolExecutor() as executor:
clips = list(executor.map(process_image, image_files, durations, [target_size] * len(image_files)))
# 将所有剪辑叠加到背景上
composite_clips = [CompositeVideoClip([bg_clip.subclip(sum(durations[:i]), sum(durations[:i+1])), clip])
for i, clip in enumerate(clips)]
# 使用concatenate_videoclips函数将所有剪辑串联起来
final_clip = concatenate_videoclips(composite_clips, method="compose")
# 写入视频文件
output_filename = f"{base_name}.mp4"
final_clip.write_videofile(os.path.join(output_video_path, output_filename), fps=fps)