The code works as I want, but it consumes a lot of RAM. I'm lucky to have enough RAM, but when I run it, it uses anywhere from 20GB to 30GB of RAM depending on the audio. Is there anything I can do to optimize it?
from moviepy.editor import *
import numpy as np
import os
import gc
def process_frame(t, audio_array, image_clip, fps):
"""Generate a single frame at time `t`."""
audio_start = int(t * 44100)
audio_end = int((t + 1 / fps) * 44100)
audio_frame = audio_array[audio_start:audio_end]
rms = np.sqrt(np.mean(np.square(audio_frame)))
target_size = max(70, int(image_clip.size[0] * (1 + rms * 0.1)))
frame = (
image_clip.copy()
.resize(height=target_size)
.fx(vfx.colorx, 0.5 + rms * 0.25)
.on_color(size=(target_size, target_size), color=(0, 255, 0))
.get_frame(t) # Generate the actual frame for time `t`.
)
del audio_frame # Free memory for audio_frame
gc.collect() # Collect garbage
return frame
def main():
audio_file = "arrebatao.mp3"
image_file = "image.png"
output_filename = "stickero.mp4"
# Load audio and image
audio_clip = AudioFileClip(audio_file)
audio_duration = audio_clip.duration
audio_array = audio_clip.to_soundarray(fps=44100)
image_clip = ImageClip(image_file)
fps = 60
# Prepare the video writer
output_size = (image_clip.size[0], image_clip.size[1])
video_writer = VideoFileClip(
output_filename,
fps=fps,
codec="libx264",
audio_codec="aac",
audio_bitrate="192k",
)
# Generate frames incrementally
for t in np.arange(0, audio_duration, 1 / fps):
frame = process_frame(t, audio_array, image_clip, fps)
video_writer.write_frame(frame) # Write the frame directly to file
video_writer.close() # Finalize the video
del audio_clip, image_clip, audio_array # Free memory
gc.collect() # Collect garbage
if __name__ == "__main__":
main()
I tried making it render in chunks to free up memory, but it didn't make a difference; it still consumed a lot.
ram