# How to Configure the File Writer for Different Output Formats (MP4, GIF, MOV) in Manim

> Learn to configure Manim's SceneFileWriter for MP4 GIF MOV outputs. Control video codec and pixel format via CLI flags or config to customize your animations.

- Repository: [Grant Sanderson/manim](https://github.com/3b1b/manim)
- Tags: how-to-guide
- Published: 2026-02-28

---

**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`](https://github.com/3b1b/manim/blob/main/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`](https://github.com/3b1b/manim/blob/main/manimlib/config.py) (lines 109–113):

```python
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`](https://github.com/3b1b/manim/blob/main/manimlib/config.py) (lines 64–71) maps flags to file extensions:

```python
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`:

```python
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:

```python
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`:

```bash
manim -pql my_scene.py MyScene --transparent --vcodec prores_ks

```

### Via Configuration File

Create a [`custom_config.yml`](https://github.com/3b1b/manim/blob/main/custom_config.yml) file to set default output formats:

```yaml
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:

```python
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`](https://github.com/3b1b/manim/blob/main/manimlib/scene/scene_file_writer.py) constructs the final ffmpeg command in `open_movie_pipe`. It uses the configuration values set earlier:

```python

# 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 `SceneFileWriter` class, configured via `movie_file_extension`, `video_codec`, and `pixel_format`.
- **CLI flags** `--gif` and `--transparent` automatically set the appropriate extensions and codecs in [`manimlib/config.py`](https://github.com/3b1b/manim/blob/main/manimlib/config.py).
- **Configuration files** allow persistent format settings without modifying code.
- **Programmatic control** is available through `manim_config.file_writer` before calling `render_scene`.
- **Source files to reference**: [`manimlib/config.py`](https://github.com/3b1b/manim/blob/main/manimlib/config.py) for argument parsing and [`manimlib/scene/scene_file_writer.py`](https://github.com/3b1b/manim/blob/main/manimlib/scene/scene_file_writer.py) for 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`](https://github.com/3b1b/manim/blob/main/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`](https://github.com/3b1b/manim/blob/main/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`](https://github.com/3b1b/manim/blob/main/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`](https://github.com/3b1b/manim/blob/main/manimlib/config.py).