How to Configure the File Writer for Different Output Formats (MP4, GIF, MOV) in Manim
Manim uses the SceneFileWriter class to pipe raw frame data through ffmpeg, selecting the output container and codec based on CLI flags or configuration values for movie_file_extension, video_codec, and pixel_format.
The 3b1b/manim library renders mathematical animations by writing each frame to an image buffer and then encoding the sequence into a video file. The output format—whether MP4, GIF, or MOV with transparency—is determined before rendering begins through the configuration system and the SceneFileWriter class in manimlib/scene/scene_file_writer.py.
How Output Formats Are Determined
The rendering pipeline translates user input into ffmpeg arguments through three stages: CLI parsing, extension mapping, and writer configuration.
CLI Argument Parsing
Command-line flags are defined in manimlib/config.py (lines 109–113):
parser.add_argument("-i", "--gif", action="store_true",
help="Save the video as gif")
parser.add_argument("-t", "--transparent", action="store_true",
help="Render to a movie file with an alpha channel")
Additional flags like --vcodec and --pix_fmt allow manual override of the encoder and pixel format.
File Extension Logic
The get_file_ext() function in manimlib/config.py (lines 64–71) maps flags to file extensions:
def get_file_ext(args: Namespace) -> str:
if args.transparent:
file_ext = ".mov"
elif args.gif:
file_ext = ".gif"
else:
file_ext = ".mp4"
return file_ext
Updating the File Writer Configuration
The update_file_writer_config() function (lines 68–77) merges CLI values into the global manim_config:
def update_file_writer_config(config: Dict, args: Namespace):
file_writer_config = config.file_writer
file_writer_config.update(
movie_file_extension=(get_file_ext(args)), # ← .mp4, .gif, or .mov
video_codec=args.vcodec if args.vcodec else '',
pixel_format=args.pix_fmt if args.pix_fmt else '',
# ... other settings
)
Codec selection logic (lines 83–90) handles format-specific defaults:
if args.vcodec:
file_writer_config.video_codec = args.vcodec
elif args.transparent:
file_writer_config.video_codec = 'prores_ks'
file_writer_config.pixel_format = ''
elif args.gif:
file_writer_config.video_codec = '' # GIF uses no video codec
Configuring Output Formats
You can control the output format through three methods: CLI flags, YAML configuration files, or programmatic configuration.
Via Command Line Flags
| Desired Format | CLI Flag | Example Command |
|---|---|---|
| MP4 (default) | none | manim -pql my_scene.py MyScene |
| GIF | --gif |
manim -pql my_scene.py MyScene --gif |
| MOV (transparent) | --transparent |
manim -pql my_scene.py MyScene --transparent |
Override specific codecs with --vcodec and pixel formats with --pix_fmt:
manim -pql my_scene.py MyScene --transparent --vcodec prores_ks
Via Configuration File
Create a custom_config.yml file to set default output formats:
file_writer:
movie_file_extension: ".gif"
video_codec: "" # Empty for GIF
pixel_format: ""
output_directory: "media/videos"
Manim loads this configuration automatically when placed in the project root or specified via environment variables.
Programmatically Inside a Script
Modify the configuration at runtime before rendering:
from manimlib import *
class MyScene(Scene):
def construct(self):
# Animation code here
self.play(Write(Text("Hello World")))
if __name__ == "__main__":
from manimlib import manim_config
# Configure for GIF output
manim_config.file_writer.movie_file_extension = ".gif"
manim_config.file_writer.video_codec = ""
from manimlib import render_scene
render_scene(MyScene)
How SceneFileWriter Builds the FFmpeg Command
The SceneFileWriter class in manimlib/scene/scene_file_writer.py constructs the final ffmpeg command in open_movie_pipe. It uses the configuration values set earlier:
# manimlib/scene/scene_file_writer.py (simplified)
command = [
self.ffmpeg_bin,
'-y',
'-f', 'rawvideo',
'-s', f'{width}x{height}',
'-pix_fmt', 'rgba',
'-r', str(fps),
'-i', '-',
'-an',
'-loglevel', 'error',
]
if self.video_codec:
command += ['-vcodec', self.video_codec]
if self.pixel_format:
command += ['-pix_fmt', self.pixel_format]
command += [self.temp_file_path]
For MP4, this results in -vcodec libx264 -pix_fmt yuv420p. For MOV with transparency, it uses -vcodec prores_ks with no pixel format flag, allowing the ProRes codec to handle the alpha channel. For GIF, no video codec flag is passed, letting ffmpeg use its default GIF encoder.
Summary
- Manim delegates video encoding to ffmpeg through the
SceneFileWriterclass, configured viamovie_file_extension,video_codec, andpixel_format. - CLI flags
--gifand--transparentautomatically set the appropriate extensions and codecs inmanimlib/config.py. - Configuration files allow persistent format settings without modifying code.
- Programmatic control is available through
manim_config.file_writerbefore callingrender_scene. - Source files to reference:
manimlib/config.pyfor argument parsing andmanimlib/scene/scene_file_writer.pyfor ffmpeg command construction.
Frequently Asked Questions
How do I render a transparent video in Manim?
Use the --transparent flag when running your scene. This sets the file extension to .mov and the video codec to prores_ks in manimlib/config.py, allowing the ProRes format to preserve the alpha channel. The command looks like: manim -pql my_scene.py MyScene --transparent.
Can I change the default output format from MP4 to GIF permanently?
Yes. Create a custom_config.yml file in your project directory and set movie_file_extension: ".gif" and video_codec: "" under the file_writer section. Manim loads this configuration automatically, making GIF the default output for all subsequent renders without needing the --gif flag.
What video codecs work best with Manim for different formats?
For MP4, the default libx264 with yuv420p pixel format provides the best compatibility. For MOV with transparency, prores_ks is used automatically when --transparent is passed. For GIF, no video codec is specified (empty string), allowing ffmpeg to use its native GIF encoder. You can override any codec using the --vcodec CLI argument.
How does Manim handle the ffmpeg command generation?
The SceneFileWriter class in manimlib/scene/scene_file_writer.py constructs the ffmpeg command in its open_movie_pipe method. It builds a base command with raw video input, then conditionally adds -vcodec and -pix_fmt flags based on the video_codec and pixel_format configuration values set in manimlib/config.py.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →