| import av | |
| from pathlib import Path | |
| import os | |
| def save_videos_from_pil(pil_images, path, fps=8, bitrate=None): | |
| save_fmt = Path(path).suffix | |
| os.makedirs(os.path.dirname(path), exist_ok=True) | |
| width, height = pil_images[0].size | |
| if save_fmt == ".mp4": | |
| codec = "libx264" | |
| container = av.open(path, "w") | |
| stream = container.add_stream(codec, rate=fps, ) | |
| stream.width = width | |
| stream.height = height | |
| if bitrate is not None: | |
| stream.bit_rate = bitrate | |
| for pil_image in pil_images: | |
| av_frame = av.VideoFrame.from_image(pil_image) | |
| container.mux(stream.encode(av_frame)) | |
| container.mux(stream.encode()) | |
| container.close() | |
| elif save_fmt == ".gif": | |
| pil_images[0].save( | |
| fp=path, | |
| format="GIF", | |
| append_images=pil_images[1:], | |
| save_all=True, | |
| duration=(1 / fps * 1000), | |
| loop=0, | |
| ) | |
| else: | |
| raise ValueError("Unsupported file type. Use .mp4 or .gif.") |