You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MoviePy制作图片缩放视频:消除初始黑边实现全屏启动缩放

问题描述

我是StackOverflow新手,需要Python代码帮助。我写了一段代码,能把文件夹里的图片转成5秒视频,实现单张图片渐进放大的效果,但现在有问题:生成的视频初始阶段图片周围有黑边,随着放大黑边才消失。我想要图片从视频开始就占满整个屏幕,之后继续放大,允许视频结束时部分图像超出视频边界。

原代码:

import os
import glob
import numpy as np
import moviepy.editor as mp

def create_zooming_video(image_path, output_path, duration=5, resolution=(1080, 1920)):
    img = mp.ImageClip(image_path)
    
    # Calculate the initial and final zoom scales
    initial_zoom = 1.0
    final_zoom = 1.5
    
    # Calculate the zooming scale for each frame
    zoom_scales = np.linspace(initial_zoom, final_zoom, int(duration * 30))  # 30 frames per second
    
    # Calculate the dimensions for the cropped image
    cropped_width = resolution[0]
    cropped_height = int(resolution[0] * (img.size[1] / img.size[0]))
    
    # Resize the image to fit the cropped dimensions
    img = img.resize((cropped_width, cropped_height))
    
    # Create a list to hold each frame of the zooming animation
    zooming_frames = []
    for scale in zoom_scales:
        frame = img.resize(scale)
        frame = frame.set_position(("center", "center"))
        frame = frame.set_duration(1 / 30)  # Each frame lasts 1/30 seconds
        zooming_frames.append(frame)
    
    # Create the zooming animation clip
    zooming_clip = mp.concatenate_videoclips(zooming_frames, method="compose")
    
    # Calculate position to keep the zoomed image centered
    position = ("center", "center")
    
    zooming_clip = zooming_clip.set_position(position)
    zooming_clip = zooming_clip.set_duration(duration)
    zooming_clip = zooming_clip.set_fps(30)
    
    zooming_clip.write_videofile(output_path, codec="libx264")

def main():
    output_folder = "output_videos"
    os.makedirs(output_folder, exist_ok=True)

    png_files = glob.glob("*.png")

    for png_file in png_files:
        filename_without_extension = os.path.splitext(png_file)[0]
        output_path = os.path.join(output_folder, f"{filename_without_extension}.mp4")
        create_zooming_video(png_file, output_path)

if __name__ == "__main__":
    main()
解决方案

问题根源在于你最初的缩放逻辑:你把图片固定缩放到视频宽度,但如果图片长宽比和目标视频(1080x1920竖屏)不匹配,高度就会不足,导致初始状态下屏幕出现黑边。要实现“从满屏开始放大”的效果,需要先计算能让图片刚好覆盖整个视频的初始缩放比例,之后在这个基础上继续放大,同时每帧都对图片进行居中裁剪,确保始终填满屏幕。

修改后的代码:

import os
import glob
import numpy as np
import moviepy.editor as mp

def create_zooming_video(image_path, output_path, duration=5, resolution=(1080, 1920)):
    img = mp.ImageClip(image_path)
    video_w, video_h = resolution
    
    # 计算让图片刚好覆盖整个视频的初始缩放比例
    scale_w = video_w / img.size[0]
    scale_h = video_h / img.size[1]
    initial_zoom = max(scale_w, scale_h)
    # 最终缩放比例:在满屏基础上再放大1.5倍
    final_zoom = initial_zoom * 1.5
    
    # 生成逐帧的缩放比例序列
    zoom_scales = np.linspace(initial_zoom, final_zoom, int(duration * 30))
    
    zooming_frames = []
    for scale in zoom_scales:
        # 按当前比例缩放图片
        scaled_img = img.resize(scale)
        # 居中裁剪到视频分辨率,确保无黑边
        cropped_img = scaled_img.crop(
            x_center=scaled_img.size[0]/2,
            y_center=scaled_img.size[1]/2,
            width=video_w,
            height=video_h
        )
        cropped_img = cropped_img.set_duration(1/30)
        zooming_frames.append(cropped_img)
    
    # 拼接所有帧组成视频
    zooming_clip = mp.concatenate_videoclips(zooming_frames, method="compose")
    zooming_clip = zooming_clip.set_fps(30)
    
    zooming_clip.write_videofile(output_path, codec="libx264")

def main():
    output_folder = "output_videos"
    os.makedirs(output_folder, exist_ok=True)

    png_files = glob.glob("*.png")

    for png_file in png_files:
        filename_without_extension = os.path.splitext(png_file)[0]
        output_path = os.path.join(output_folder, f"{filename_without_extension}.mp4")
        create_zooming_video(png_file, output_path)

if __name__ == "__main__":
    main()

关键修改说明

  • 初始缩放比例计算:对比图片与视频的宽高比例,取较大值作为初始缩放倍数,保证图片一开始就能完全覆盖视频屏幕,彻底消除初始黑边。
  • 居中裁剪:每帧缩放后都对图片进行居中裁剪,无论放大到多大,视频画面始终被图片填满,超出屏幕的部分会被自动裁切,完全符合你的需求。
  • 调整缩放范围:最终缩放在初始满屏的基础上再放大1.5倍,实现“从满屏开始放大,结束时部分图像超出边界”的效果。

内容的提问来源于stack exchange,提问作者Boris Razmiki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 06:55:58