Look at this animation. It is created with pyglet, a cross-platform windowing and multimedia library for Python. The animation has 300 frames.
The animation is played at no particular framerate. Each frame that is generated is written to an mp4 video file. Here you see the 5 seconds result video in a video player:
A pyglet.window.Window is created. But instead of running an infinite event loop, it has a run method that renders 300 frames in a for-loop. The resulting video length (5 seconds) is determined by the ffmpeg framerate settings (60 fps).
Each iteration, the label position on the screen is updated and frame data is extracted from the buffer as a list of bytes. The bytes are passed to the VideoWriter that has a reference to an open video stream. The stream was opened in a ffmpeg subprocess and can be written to.
import math import pyglet import subprocess class VideoWriter: def __init__(self): fps = "60" frame_size = "1920x1080" command = [ "ffmpeg", # ffmpeg executable "-y", # overwrite output files "-f", "rawvideo", # force format "-s", frame_size, # frame size "-pix_fmt", "rgba", # pixel format "-r", fps, # frame rate "-i", "-", # input is pipe "-an", # disable audio "-metadata", "comment=Rendered by Loek", "-vf", "vflip", # video filters, vertical flip "-vcodec", "libx264", "-pix_fmt", "yuv420p", "test.mp4" # output file ] self.writing_process = subprocess.Popen(command, stdin=subprocess.PIPE) def write_frame(self, bytes): self.writing_process.stdin.write(bytes) def close(self): self.writing_process.stdin.close() self.writing_process.wait() self.writing_process.terminate() class MainWindow(pyglet.window.Window): def __init__(self, video_writer): super().__init__() self.video_writer = video_writer self.width = 960 self.height = 540 self.label = pyglet.text.Label(":-)", x=100, y=300, font_size=48) self.render() def render(self): self.clear() self.label.draw(); self.flip() def run(self): for x in range(60 * 5): # 5 seconds self.label.x += 2 self.label.y = math.sin(x / 10) * 10 + 400 self.render() event = self.dispatch_events() data = pyglet.image.get_buffer_manager().get_color_buffer().get_image_data().get_data() self.video_writer.write_frame(data) self.video_writer.close() window = MainWindow(VideoWriter()) window.run()
Run the code and test.mp4 should look like this: