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

如何用MoviePy实现固定分辨率的指定比例缩放?求方案及替代库

解决方案:用MoviePy实现内容缩放+保持原分辨率

MoviePy实现方法

你之前用resize函数没达到预期效果,是因为resize是直接修改视频的整体分辨率尺寸,而你需要的是缩放视频内容后,保留原1080P的画布(用黑边填充空白区域)。可以通过「缩放内容+合成背景」的方式实现:

具体步骤与代码示例

from moviepy.editor import VideoFileClip, ColorClip, CompositeVideoClip

# 1. 加载原1080P视频
original_clip = VideoFileClip("your_video.mp4")
original_w, original_h = original_clip.size  # 对应1920, 1080

# 2. 指定缩放比例(示例:缩放到原内容的0.7倍)
scale_factor = 0.7
scaled_w = int(original_w * scale_factor)
scaled_h = int(original_h * scale_factor)

# 3. 仅缩放视频内容(这里用resize修改内容尺寸,而非整体分辨率)
scaled_clip = original_clip.resize((scaled_w, scaled_h))

# 4. 创建原分辨率的黑色背景画布
bg_clip = ColorClip(size=(original_w, original_h), color=(0,0,0), duration=original_clip.duration)

# 5. 将缩放后的内容放在背景中央,合成最终视频
final_clip = CompositeVideoClip([bg_clip, scaled_clip.set_position("center")])

# 6. 导出视频(保持原1080P分辨率)
final_clip.write_videofile("scaled_video.mp4", codec="libx264", fps=original_clip.fps)

如果需要按固定比例缩放内容(比如把内容改成1:1比例后适配原画布),可以调整缩放尺寸的计算逻辑:

# 示例:将内容按1:1比例缩放,适配原1080P画布
target_aspect = 1.0  # 1:1比例
content_aspect = original_w / original_h

if content_aspect > target_aspect:
    # 原视频是宽屏,按高度基准缩放
    scaled_h = int(original_h * scale_factor)
    scaled_w = int(scaled_h * target_aspect)
else:
    # 原视频是竖屏,按宽度基准缩放
    scaled_w = int(original_w * scale_factor)
    scaled_h = int(scaled_w / target_aspect)

scaled_clip = original_clip.resize((scaled_w, scaled_h))

替代库方案(除OpenCV外)

如果不想用MoviePy,这两个开箱即用的库可以试试:

1. FFmpeg-python

基于FFmpeg的Python封装,直接调用FFmpeg滤镜实现,语法贴近原生命令:

import ffmpeg

input_stream = ffmpeg.input("your_video.mp4")
# scale滤镜缩放内容,pad滤镜填充黑边保持原1080P分辨率
output_stream = input_stream.filter("scale", w="iw*0.7", h="ih*0.7").filter("pad", w=1920, h=1080, x="(ow-iw)/2", y="(oh-ih)/2")
output_stream.output("scaled_video.mp4").run()

2. PyAV

基于FFmpeg的另一个Python绑定,处理逻辑更底层但灵活性更高:

import av

input_container = av.open("your_video.mp4")
output_container = av.open("scaled_video.mp4", "w")

# 复制原视频流参数,保持1080P分辨率
stream = output_container.add_stream("h264", rate=input_container.streams.video[0].rate)
stream.width = 1920
stream.height = 1080
stream.pix_fmt = "yuv420p"

for frame in input_container.decode(video=0):
    # 缩放单帧内容
    scaled_frame = frame.resize(width=int(frame.width*0.7), height=int(frame.height*0.7))
    # 创建原分辨率的空帧,填充黑边
    new_frame = av.VideoFrame(width=1920, height=1080, format="yuv420p")
    # 将缩放后的帧复制到新帧中央
    new_frame.plane[0].copy_from(scaled_frame.plane[0], dst=( (1920-scaled_frame.width)//2, (1080-scaled_frame.height)//2 ) )
    new_frame.plane[1].copy_from(scaled_frame.plane[1], dst=( (1920//2 - scaled_frame.width//2)//2, (1080//2 - scaled_frame.height//2)//2 ) )
    new_frame.plane[2].copy_from(scaled_frame.plane[2], dst=( (1920//2 - scaled_frame.width//2)//2, (1080//2 - scaled_frame.height//2)//2 ) )
    
    for packet in stream.encode(new_frame):
        output_container.mux(packet)

# 完成剩余编码
for packet in stream.encode():
    output_container.mux(packet)

input_container.close()
output_container.close()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 10:36:22