Spaces:
Running
Running
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) |