I am new to stakoverflow and I was hoping to get some help with a python code.
我是STAKOVERFLOW的新手,我希望能得到一些关于Python代码的帮助。
I've written a code that transforms an image from a folder into a 5-second video. The concept involves taking a single image and gradually zooming in as it plays. However, I've encountered an issue where the videos generated initially have black bars around the image. These black bars disappear as the image progressively zooms in and fills the screen. My intention was for the image to occupy the entire screen right from the beginning of the video and then zoom in further from that point onward. I'm struggling to figure out how to achieve this specific effect. Can anyone help?
我已经编写了一段代码,可以将文件夹中的图像转换为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()
I'm attempting to make the image begin at 100% scale within the video and then progressively zoom in. It's ok for parts of the image to be outside the video's boundaries by the end of the zooming process.
我试图让图像在视频中以100%的比例开始,然后逐渐放大。在缩放过程结束时,图像的某些部分在视频边界之外是可以的。
更多回答
优秀答案推荐
I ran your code. it does produce video with black margins and incorrect final video resolution (width, height).
我查了你的代码。它确实会产生带有黑色边缘和不正确的最终视频分辨率(宽度、高度)的视频。
Moviepy works well, the problem is in the algorithm.
Moviepy运行得很好,问题出在算法上。
Firstly, at the very beginning you need to resize the image by different way.
Secondly and most importantly, you are not cropping the image. Although you write about crop in the #reference, there is actually no crop in your code.
首先,在一开始,你需要通过不同的方式调整图像的大小。其次,最重要的是,你没有裁剪图像。虽然你在#reference中写了crop,但实际上你的代码中没有crop。
Based on your code, I wrote my own version of the code to create one zooming video from one image ( jpg, png etc.). It works well for all source images with different aspect ratios.
基于您的代码,我编写了我自己的代码版本,从一个图像(jpg、png等)创建一个缩放视频。它对所有具有不同长宽比的源图像都能很好地工作。
import numpy as np
import moviepy.editor as mp
image_file = 'image.jpg'
output_file ='zooming_video.mp4'
def create_zooming_video(image_path, output_path, duration=5, resolution=(1080, 1920)):
img = mp.ImageClip(image_path)
# initial and final zoom scales
initial_zoom = 1.0
final_zoom = 1.5
# Calculate aspect ratio source image and final video
aspect_ratio_final_video = resolution[0] / resolution[1]
aspect_ratio_source_image = img.size[0] / img.size[1]
# Resize the image to fit the final video after crop
# it depending on aspect ratio source image
if aspect_ratio_source_image > aspect_ratio_final_video :
img = img.resize(height=resolution[1])
else:
img = img.resize(width=resolution[0])
# Calculate the zooming scale for each frame
zoom_scales = np.linspace(initial_zoom, final_zoom, int(duration * 30)) # 30 frames per second
# 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_duration(1 / 30) # Each frame lasts 1/30 seconds
# Calculate position to keep the CROPPED image centered
frame_center_x = frame.size[0]/2
frame_center_y = frame.size[1]/2
# CROP frame
cropped_frame = frame.crop(x_center=frame_center_x, y_center=frame_center_y,
width=resolution[0], height=resolution[1])
zooming_frames.append(cropped_frame)
# Create the zooming animation clip
zooming_clip = mp.concatenate_videoclips(zooming_frames, method="compose")
zooming_clip = zooming_clip.set_duration(duration)
zooming_clip = zooming_clip.set_fps(30)
zooming_clip.write_videofile(output_path, preset ='ultrafast',
bitrate='5000k', codec='mpeg4',)
#______ main ____________
create_zooming_video(image_file, output_file)
I tested the code on images with different aspect ratios. here are the results:
我在不同长宽比的图像上测试了代码。以下是结果:
variant 1:
变体1:
source "horizontal" image .jpg
https://imgur.com/PLOd1rA
来源“水平”图像.jpg https://imgur.com/PLOd1rA
final zooming video 9:16
https://imgur.com/hQVLEx9
最终缩放视频9:16 https://imgur.com/hQVLEx9
variant 2:
变体2:
source "vertical" image .png
https://imgur.com/cIoBWMD
源“垂直”图像.png https://imgur.com/cIoBWMD
final zooming video 9:16
https://imgur.com/3fcqEzr
最终缩放视频9:16 https://imgur.com/3fcqEzr
If my answer solves your question, please mark this answer as "solved" ✔ on the left side of this answer. Thanks.
如果我的答案解决了您的问题,请在此答案左侧将此答案标记为“已解决”✔。谢谢。
...
..。
Tip: I found that creating a video from a jpg image is 5 times faster than from a png. For productivity reasons, it makes sense to first convert all png files in your folder to jpg format using a batch converter (not Python).
For HD video (1080 x 1920) the difference is not visible.
That's what I will do personally. For Windows I use this free batch image processing tool https://www.xnview.com/en/xnconvert/
小贴士:我发现用jpg格式的图片制作视频比用png格式的图片快5倍。出于生产效率的原因,首先使用批处理转换器(而不是Python)将文件夹中的所有PNG文件转换为jpg格式是有意义的。对于高清视频(1080 X 1920),差异并不明显。这就是我个人要做的。我在Windows上使用了这个免费的批处理图像处理工具https://www.xnview.com/en/xnconvert/
更多回答
我是一名优秀的程序员,十分优秀!