如何通过MoviePy解决大量内存使用问题?

时间:2021-08-20 03:53:45

I am trying to make a video from a large number of images using MoviePy. The approach works fine for small numbers of images, but the process is killed for large numbers of images. At about 500 images added, the Python process is using all about half of the volatile memory available. There are many more images than that.

我正在尝试使用MoviePy从大量图像制作视频。该方法适用于少量图像,但该过程因大量图像而被杀死。在添加了大约500个图像时,Python进程使用了​​大约一半可用的易失性内存。还有更多的图像。

How should I address this? I want the processing to complete and I don't mind if the processing takes a bit longer, but it would be good if I could limit the memory and CPU usage in some way. With the current approach, the machine becomes almost unusable while processing.

我该如何解决这个问题?我希望处理完成,我不介意处理是否需要更长时间,但如果我能以某种方式限制内存和CPU使用率,那将会很好。使用当前的方法,机器在处理时变得几乎不可用。

The code is as follows:

代码如下:

import os
import time
from   moviepy.editor import *

def ls_files(
    path = "."
    ):
    return([fileName for fileName in os.listdir(path) if os.path.isfile(
        os.path.join(path, fileName)
    )])

def main():

    listOfFiles = ls_files()
    listOfTileImageFiles = [fileName for fileName in listOfFiles \
        if "_tile.png" in fileName
    ]
    numberOfTiledImages = len(listOfTileImageFiles)

    # Create a video clip for each image.
    print("create video")
    videoClips = []
    imageDurations = []
    for imageNumber in range(0, numberOfTiledImages):
        imageFileName = str(imageNumber) + "_tile.png"
        print("add image {fileName}".format(
            fileName = imageFileName
        ))
        imageClip = ImageClip(imageFileName)
        duration  = 0.1
        videoClip = imageClip.set_duration(duration)
        # Determine the image start time by calculating the sum of the durations
        # of all previous images.
        if imageNumber != 0:
            videoStartTime = sum(imageDurations[0:imageNumber])
        else:
            videoStartTime = 0
        videoClip = videoClip.set_start(videoStartTime)
        videoClips.append(videoClip)
        imageDurations.append(duration)
    fullDuration = sum(imageDurations)
    video = concatenate(videoClips)
    video.write_videofile(
        "video.mp4",
        fps         = 30,
        codec       = "mpeg4",
        audio_codec = "libvorbis"
    )

if __name__ == "__main__":
    main()

1 个解决方案

#1


If I understood correctly, you want to use the different images as the frames of your video.

如果我理解正确,您希望将不同的图像用作视频的帧。

In this case you should use ImageSequenceClip() (it's in the library, but not yet in the web docs, see here for the doc).

在这种情况下,您应该使用ImageSequenceClip()(它在库中,但尚未在Web文档中,请参阅此处的文档)。

Basically, you just write

基本上,你只是写

clip = ImageSequenceClip("some/directory/", fps=10)
clip.write_videofile("result.mp4")

And it will read the images in the directory in alpha-numerical order, while keeping only one frame at a time in the memory.

它将以字母数字顺序读取目录中的图像,同时在内存中一次只保留一帧。

While I am at it, you can also provide a list of filenames or a list of numpy arrays to ImageSequenceClip.

当我在它时,您还可以向ImageSequenceClip提供文件名列表或numpy数组列表。

Note that if you just want to transform images into a video, and not anything else fancy like adding titles or compositing with another video, then you can do it directly with ffmpeg. From memory the command should be:

请注意,如果您只想将图像转换为视频,而不想添加标题或与其他视频合成等其他任何内容,那么您可以直接使用ffmpeg进行操作。从内存中命令应该是:

ffmpeg -i *_tile.png -r 10 -o result.mp4

#1


If I understood correctly, you want to use the different images as the frames of your video.

如果我理解正确,您希望将不同的图像用作视频的帧。

In this case you should use ImageSequenceClip() (it's in the library, but not yet in the web docs, see here for the doc).

在这种情况下,您应该使用ImageSequenceClip()(它在库中,但尚未在Web文档中,请参阅此处的文档)。

Basically, you just write

基本上,你只是写

clip = ImageSequenceClip("some/directory/", fps=10)
clip.write_videofile("result.mp4")

And it will read the images in the directory in alpha-numerical order, while keeping only one frame at a time in the memory.

它将以字母数字顺序读取目录中的图像,同时在内存中一次只保留一帧。

While I am at it, you can also provide a list of filenames or a list of numpy arrays to ImageSequenceClip.

当我在它时,您还可以向ImageSequenceClip提供文件名列表或numpy数组列表。

Note that if you just want to transform images into a video, and not anything else fancy like adding titles or compositing with another video, then you can do it directly with ffmpeg. From memory the command should be:

请注意,如果您只想将图像转换为视频,而不想添加标题或与其他视频合成等其他任何内容,那么您可以直接使用ffmpeg进行操作。从内存中命令应该是:

ffmpeg -i *_tile.png -r 10 -o result.mp4