# FFmpeg in Python: A Practical Guide with Code Examples

> Learn how to use FFmpeg in Python with the ffmpeg-python library. Covers format conversion, audio extraction, video trimming, frame extraction, thumbnails, and a simpler API-based alternative with Templated.

- **Author**: Pedro Campos
- **Published**: 2026-03-18
- **Updated**: 2026-04-20
- **Category**: Tutorial
- **Tags**: video api, ffmpeg
- **Read time**: 11 min read
- **URL**: https://templated.io/blog/ffmpeg-in-python-a-practical-guide-with-code-examples/

---

## Introduction

Python developers can already automate almost everything. Data pipelines, image generation, document creation. The language has a library for nearly every task.

Video is the one area where most Python developers haven't fully explored what's possible. FFmpeg changes that completely.

With **FFmpeg** in Python, you can convert video formats, trim clips, extract frames, [generate thumbnails](https://templated.io/blog/how-to-create-beautiful-video-thumbnails-for-instagram-guide/), and process media files programmatically with just a few lines of code.

You don't need any video editing software neither any manual work. Just Python doing what it does best: automating things.

In this tutorial, we'll walk through exactly how to use FFmpeg in Python with practical examples you can start using right away.

## What is FFmpeg?

[FFmpeg](https://ffmpeg.org/) is a free, open-source, cross-platform solution for recording, converting, and streaming audio and video. It's widely regarded as the Swiss Army knife of multimedia processing and is used by countless applications behind the scenes — from VLC and YouTube to Instagram and Spotify.

FFmpeg can:

- **Decode and encode** virtually any audio/video format
- **Transcode** media between formats
- **Mux and demux** streams
- **Filter** video and audio (resize, crop, overlay, adjust speed, etc.)
- **Stream** media over network protocols

FFmpeg includes several core libraries such as **libavcodec** (encoding/decoding), **libavformat** (muxing/demuxing), **libavfilter** (filtering), and **libswscale** (scaling). It runs on Linux, macOS, and Windows.

While FFmpeg is extremely powerful, its command-line interface can be complex and difficult to read. The **ffmpeg-python** library comes in — it provides a clean, Pythonic wrapper around FFmpeg's CLI.

## Prerequisites

Before we start, make sure you have the following installed:

- **Python 3.8+** (we'll use Python 3.11 in examples)
- **pip** (Python package manager)
- **FFmpeg** installed on your system

### Installing FFmpeg

FFmpeg must be installed separately — the Python library is only a wrapper and does not include FFmpeg itself.

**macOS (Homebrew):**

```bash
brew install ffmpeg
```

**Ubuntu/Debian:**

```bash
sudo apt update && sudo apt install ffmpeg
```

**Windows:**

Download from [ffmpeg.org/download.html](https://ffmpeg.org/download.html) and add it to your system PATH.

Verify your installation:

```bash
ffmpeg -version
```

## Installing the ffmpeg-python Library

Install the Python wrapper with pip:

```bash
pip install ffmpeg-python
```

> **Important:** The library is called `ffmpeg-python` when installing via pip, but you import it as `ffmpeg` in your code. Don't confuse it with the `ffmpeg` package (without `-python`), which is a different library.

Basic usage:

```python
import ffmpeg

# Use ffmpeg here to perform various operations
```

## Using ffmpeg-python: Practical Examples

Let's explore common media processing tasks with working code examples. Each example builds on the basics, going from simple format conversion to more advanced operations.

### 1. Convert Video Format (MP4 to WebM)

The simplest use case is [converting a video from one format to another](https://templated.io/tools/video-format-converter/). FFmpeg automatically selects the appropriate codecs based on the output file extension.

```python
import ffmpeg

(
    ffmpeg
    .input("input.mp4")
    .output("output.webm")
    .run()
)
```

This converts an MP4 file to WebM format. You can convert between virtually any formats FFmpeg supports — MP4, AVI, MOV, MKV, WMV, FLV, and more.

To specify a particular video codec:

```python
import ffmpeg

(
    ffmpeg
    .input("input.mp4")
    .output("output.webm", vcodec="libvpx-vp9")
    .run()
)
```

<!-- [Image: Terminal output showing successful format conversion] -->

### 2. Extract Audio from a Video (MP4 to MP3)

Need just the audio track from a video? FFmpeg makes this straightforward:

```python
import ffmpeg

(
    ffmpeg
    .input("input.mp4")
    .output("audio.mp3")
    .run()
)
```

To specify a particular audio codec:

```python
import ffmpeg

(
    ffmpeg
    .input("input.mp4")
    .output("audio.mp3", acodec="libmp3lame", audio_bitrate="192k")
    .run()
)
```

> **Tip:** You can check all available codecs by running `ffmpeg -codecs` in your terminal. The [FFmpeg codec documentation](https://ffmpeg.org/ffmpeg-codecs.html) provides detailed information about each codec.

### 3. Trim a Video

Trimming lets you extract a specific segment from a video.For a one-off clip, the [free video trimmer](https://templated.io/tools/trim-video/) does this in the browser with no code. You specify the start time and end time:

```python
import ffmpeg

start_time = "00:00:10"
end_time = "00:00:20"

(
    ffmpeg
    .input("input.mp4", ss=start_time, to=end_time)
    .output("trimmed_output.mp4")
    .run()
)
```

This extracts the segment from 10 seconds to 20 seconds. The `ss` parameter sets the start time, and `to` sets the end time.

You can also use seconds directly:

```python
import ffmpeg

(
    ffmpeg
    .input("input.mp4", ss=10, t=15)
    .output("trimmed_output.mp4")
    .run()
)
```

Here, `ss=10` starts at 10 seconds and `t=15` sets the duration to 15 seconds.

<!-- [Image: Side-by-side comparison of original video timeline and trimmed segment] -->

### 4. Extract Frames from a Video

You can extract individual frames as image files. This is useful for creating previews, analyzing video content, or building training datasets for machine learning.

**Extract a specific number of frames:**

```python
import ffmpeg

(
    ffmpeg
    .input("input.mp4")
    .output("frame_%d.png", vframes=5)
    .run()
)
```

This outputs the first 5 frames as `frame_1.png`, `frame_2.png`, etc.

**Extract frames at a specific rate (e.g., 1 frame per second):**

```python
import ffmpeg

(
    ffmpeg
    .input("input.mp4")
    .output("frame_%d.png", vf="fps=1")
    .run()
)
```

<!-- [Image: Grid showing extracted frames from a video at 1fps] -->

**Extract frames starting from a specific timestamp:**

```python
import ffmpeg

(
    ffmpeg
    .input("input.mp4", ss="00:00:15")
    .output("frame_%d.png", vframes=3)
    .run()
)
```

This extracts 3 frames starting from the 15-second mark.

### 5. Create a Thumbnail from a Video

Generating thumbnails is a common requirement for video platforms, media galleries, and content management systems.

**Extract a single frame as a thumbnail:**

```python
import ffmpeg

(
    ffmpeg
    .input("input.mp4", ss="00:00:05")
    .output("thumbnail.png", vframes=1)
    .run()
)
```

This grabs a single frame at the 5-second mark.

**Let FFmpeg automatically select the best thumbnail:**

FFmpeg's `thumbnail` filter analyzes the video and selects the most representative frame:

```python
import ffmpeg

(
    ffmpeg
    .input("input.mp4")
    .filter("thumbnail")
    .output("thumbnail_auto.png")
    .run()
)
```

You can also control the batch size the filter evaluates:

```python
import ffmpeg

(
    ffmpeg
    .input("input.mp4")
    .filter("thumbnail", n=300)
    .output("thumbnail_auto.png")
    .run()
)
```

A larger `n` value means FFmpeg evaluates more frames before selecting the best one, which can produce better results at the cost of processing time.

<!-- [Image: Comparison of manually selected vs. auto-selected thumbnails] -->

### 6. Resize a Video

Resizing is useful when you need to prepare videos for different platforms or[ reduce file sizes](https://templated.io/tools/compress-video/):

```python
import ffmpeg

(
    ffmpeg
    .input("input.mp4")
    .filter("scale", 1280, 720)
    .output("resized_output.mp4")
    .run()
)
```

To maintain aspect ratio, set one dimension to `-1`:

```python
import ffmpeg

(
    ffmpeg
    .input("input.mp4")
    .filter("scale", 1280, -1)
    .output("resized_output.mp4")
    .run()
)
```

### 7. Add a Watermark to a Video

Overlay an image (like a logo) on top of a video:

```python
import ffmpeg

video = ffmpeg.input("input.mp4")
watermark = ffmpeg.input("logo.png")

(
    ffmpeg
    .overlay(video, watermark, x=10, y=10)
    .output(video.audio, "watermarked_output.mp4")
    .run()
)
```

The `x` and `y` parameters control the position of the watermark. To place it in the bottom-right corner:

```python
import ffmpeg

video = ffmpeg.input("input.mp4")
watermark = ffmpeg.input("logo.png")

(
    ffmpeg
    .overlay(video, watermark, x="main_w-overlay_w-10", y="main_h-overlay_h-10")
    .output(video.audio, "watermarked_output.mp4")
    .run()
)
```

### 8. Concatenate Multiple Videos

Combine multiple video files into one:

```python
import ffmpeg

input1 = ffmpeg.input("video1.mp4")
input2 = ffmpeg.input("video2.mp4")
input3 = ffmpeg.input("video3.mp4")

(
    ffmpeg
    .concat(input1, input2, input3)
    .output("combined_output.mp4")
    .run()
)
```

To include audio streams as well:

```python
import ffmpeg

input1 = ffmpeg.input("video1.mp4")
input2 = ffmpeg.input("video2.mp4")

(
    ffmpeg
    .concat(input1.video, input1.audio, input2.video, input2.audio, v=1, a=1)
    .output("combined_with_audio.mp4")
    .run()
)
```

### 9. Get Video Metadata

Before processing, you may want to inspect a video's properties:

```python
import ffmpeg

probe = ffmpeg.probe("input.mp4")

# Get video stream info
video_stream = next(
    (stream for stream in probe["streams"] if stream["codec_type"] == "video"),
    None
)

if video_stream:
    print(f"Codec: {video_stream['codec_name']}")
    print(f"Resolution: {video_stream['width']}x{video_stream['height']}")
    print(f"Duration: {float(video_stream.get('duration', 0)):.2f}s")
    print(f"Frame rate: {video_stream['r_frame_rate']}")
```

## 5 Common Challenges with FFmpeg in Python

While FFmpeg is incredibly powerful, there are some common challenges you'll encounter:

1. **Installation complexity** — FFmpeg must be installed separately on every machine, and versions can differ across environments (local dev, CI/CD, production servers).

2. **Cryptic error messages** — FFmpeg's error output can be difficult to parse and debug, especially for complex filter chains.

3. **No visual editing** — Building video compositions (text overlays, animations, transitions) requires constructing complex filter graphs entirely in code.

4. **Scaling issues** — Processing videos is CPU-intensive. Handling high volumes requires managing infrastructure, queuing, and parallelization yourself.

5. **No template system** — If you want to generate multiple videos with the same layout but different content (e.g., personalized marketing videos), you need to rebuild the filter chain each time.

## A Simpler Alternative: Templated API

If your use case involves generating videos programmatically — especially with text, images, logos, or other dynamic content — there's a much simpler approach than writing complex FFmpeg filter chains.Templated is one option here. If you want to see the others, we [compared six template-based video automation APIs](https://templated.io/blog/best-template-based-video-automation-apis/).

[Templated](https://templated.io) provides a **visual template editor** and a **REST API** that lets you [generate videos](https://templated.io/video-automation-api/) (as well as images and PDFs) with a single API call. Instead of building complex filter graphs in code, you design your template visually and then render it with dynamic data.

As video creation becomes more common in marketing workflows, the need for faster production is also growing. Statistics suggest that,[41% of brands now use AI for video creation](https://templated.io/blog/video-marketing-statistics-and-trends/), up from 18% the previous year.

### FFmpeg vs Templated API: Why Use Templated Instead of FFmpeg?

| Feature | FFmpeg + Python | Templated API |
| - | - | - |
| **Setup** | Install FFmpeg + Python library on every machine | No installation — just an API key |
| **Design** | Code-only, no visual preview | Drag-and-drop visual editor |
| **Text overlays** | Complex filter chains | Built-in, with custom fonts and styles |
| **Dynamic content** | Rebuild filters for each variation | Pass data via API, same template |
| **Scaling** | Manage your own infrastructure | Auto-scaling, 99.9% uptime |
| **Maintenance** | Update FFmpeg, handle OS compatibility | Fully managed |

### How It Works

1. **Design your template** in the visual editor with drag-and-drop elements (text, images, shapes, videos)
2. **Call the API** with your dynamic data
3. **Get your rendered video** back — ready to use

Check out how the Templated editor works:

[Watch the video on YouTube](https://www.youtube.com/watch?v=WXH5XcbSLuA)

### Example: Generate a Video with Templated API

To render a video, you set `format` to `"mp4"` and can control `duration` (in milliseconds, max 90 seconds) and `fps` (1–60, default 30).

Here's how you'd generate a personalized video using Python and the Templated API:

```python
import requests

api_key = "YOUR_API_KEY"
template_id = "YOUR_TEMPLATE_ID"

url = "https://api.templated.io/v1/render"
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {api_key}"
}

data = {
    "template": template_id,
    "format": "mp4",
    "duration": 10000,  # 10 seconds (in milliseconds)
    "fps": 30,
    "layers": {
        "headline": {
            "text": "Welcome to Our Platform!",
            "color": "#FFFFFF",
            "animation": {
                "in": {
                    "type": "slide",
                    "direction": "left",
                    "duration": 500
                },
                "start": 0,
                "end": 8000
            }
        },
        "subtitle": {
            "text": "Start your free trial today",
            "color": "#CCCCCC",
            "animation": {
                "in": {
                    "type": "fade",
                    "duration": 800
                },
                "start": 1000
            }
        },
        "logo": {
            "image_url": "https://example.com/my-logo.png"
        },
        "background-video": {
            "image_url": "https://example.com/my-background.mp4"
        }
    }
}

response = requests.post(url, json=data, headers=headers)

if response.status_code == 200:
    result = response.json()
    print(f"Video URL: {result['url']}")
else:
    print(f"Error: {response.status_code}")
    print(response.text)
```

That's it, no FFmpeg installation, no filter chains, no infrastructure to manage. You design the template once in the visual editor, and then render unlimited variations by changing the data you send to the API.

### Video Rendering Parameters

Here's a quick reference of the video-specific parameters:

| Parameter | Type | Description | Default |
| - | - | - | - |
| `format` | string | Set to `"mp4"` for video output | `"jpg"` |
| `duration` | number | Video duration in milliseconds (max 90000) | `5000` |
| `fps` | number | Frames per second (1–60) | `30` |

### Layer Animations

You can add entrance, looping, and exit animations to any layer via the `animation` property — all configurable via the API:

| Category | Types | Notes |
| - | - | - |
| **in** (entrance) | `slide`, `fade`, `zoom`, `rotate` | Supports `direction` and `writingStyle` for text |
| **loop** (repeating) | `spin`, `pulse` | Runs continuously during the layer's visible time |
| **out** (exit) | `slide`, `fade`, `zoom` | Same direction options as entrance |

Each layer also supports `start` and `end` (in milliseconds) to control when it appears and disappears in the video timeline.

For example, to slide in a title at 1 second, pulse it, and fade it out before the end:

```python
"title": {
    "text": "Breaking News",
    "animation": {
        "in": {"type": "slide", "direction": "left", "duration": 500},
        "loop": {"type": "pulse", "duration": 1000},
        "out": {"type": "fade", "duration": 500},
        "start": 1000,
        "end": 8000
    }
}
```

### Use Cases Where Templated Shines

- **Personalized marketing videos** — Generate thousands of custom videos with names, offers, and branding
- **Social media content** — [Create platform-specific video content](https://templated.io/use-cases/image-automation-api/social-media/) at scale (Instagram Reels, TikTok, YouTube Shorts)
- **E-commerce product videos** — Automatically [generate product showcase videos](https://templated.io/use-cases/image-automation-api/ecommerce/) from catalog data
- **Event invitations** — Create personalized video invitations with dynamic guest names and event details
- **Reporting dashboards** — Generate video summaries of data and analytics

## Getting Started with Templated

1. [Sign up](https://app.templated.io/signup) for a free account
2. Design your video template in the visual editor — or choose from the [template library](https://app.templated.io/templates)
3. Grab your API key from the dashboard
4. Make an API call from your Python code to render the video

## Conclusion

FFmpeg is an incredibly powerful tool for media processing, and the `ffmpeg-python` library makes it accessible from Python. For tasks like format conversion, trimming, audio extraction, and frame manipulation, it's hard to beat.

However, when your goal is to **generate videos with dynamic content** — text overlays, logos, personalized elements, animations — FFmpeg's complexity quickly becomes a bottleneck. You end up spending more time writing and debugging filter chains than actually building your product.

[Templated](https://templated.io) offers an alternative. With its [visual template editor](https://templated.io/blog/quick-ways-to-generate-templates-for-your-automation/) and simple [REST API](https://templated.io/integrations/api/), you can design professional video templates once and render unlimited variations with a single API call. No FFmpeg installation, no complex filter graphs, no infrastructure to manage.

Whether you choose FFmpeg for low-level media processing or Templated for dynamic video generation, Python gives you the flexibility to integrate both into your workflow.

[Sign up for a free Templated account](https://app.templated.io/signup) and start generating videos with a simple API call!
