<p>The key is using the overlay filter to embed the subtitles on a transparent or fixed-color background. Adjust the <code>size</code> and <code>rate</code> to match your input video.</p>
<h2>Transparent version</h2>
<p><code>ffmpeg -i my_video.mkv -f lavfi -i &quot;color=size=1920x1080:rate=23.98:color=black@0.0,format=rgba&quot; -filter_complex &quot;[1:v][0:s]overlay,mpdecimate[out]&quot; -map &quot;[out]&quot; -an -vsync vfr frames_%04d.png</code></p>
<p>This means:</p>
<ul>
<li><code>-i my_video.mkv</code>: Input filename</li>
<li><code>-f lavfi</code>: The next input is a <a href="https://ffmpeg.org/ffmpeg-devices.html#lavfi" rel="nofollow noreferrer"><code>libavfilter</code> graph specification</a>.</li>
<li><code>-i &quot;color=size=1920x1080:rate=23.98:color=black@0.0,format=rgba&quot;</code>: Produce a video stream that is 1080p with a 23.98 fps frame rate. The <code>@0.0</code> specifier indicates a fully-transparent color, which requires <code>format=rgba</code>.</li>
<li><code>-filter_complex &quot;[1:v][0:s]overlay,mpdecimate[out]&quot;</code>: Overlay the first subtitle stream in input source 0 (the original video) atop the first video stream in input source 1 (the <code>lavfi</code> output). Decimate the output frames by removing all duplicates. Output a stream named &quot;out&quot;.</li>
<li><code>-map &quot;[out]&quot;</code>: Use the stream named &quot;out&quot; in the final output.</li>
<li><code>-an</code>: Audio is disabled.</li>
<li><code>-vsync vfr</code>: Drop frame timestamps so that each unique frame, in sequence, is output only once.</li>
<li><code>frames_%04d.png</code>: Output frames_0000.png where <code>0000</code> is an increasing number. If you expect more than 10000 unique frames, increase <code>%04d</code> to <code>%05d</code> for 5 digits, etc.</li>
</ul>
<h2>Non-transparent version (much faster?)</h2>
<p>If you can tolerate, or prefer, a non-transparent background, the process may run much faster. It goes 3-4x faster on my machine. Just remove the <code>@0.0,format=rgba</code> part.</p>
<p><code>ffmpeg -i my_video.mkv -f lavfi -i &quot;color=size=1920x1080:rate=23.98:color=black&quot; -filter_complex &quot;[1:v][0:s]overlay,mpdecimate[out]&quot; -map &quot;[out]&quot; -an -vsync vfr frames_%04d.png</code></p>
<h2>Output</h2>
<p>You'll get a PNG for each frame of unique subtitle content, plus a frame of black/transparent in between. Maybe there's a way to filter out those blank frames, but for now I can handle that outside ffmpeg.</p>
<h2>Caution</h2>
<p>If you add <code>-t</code> to limit the time of the extracted subtitles, be sure to add it twice: once after the <code>-i</code> for the input video and once after the <code>-i</code> for the black frames &amp; subtitles. This will ensure that both streams terminate at the specified time; otherwise one stream will keep going for the full video duration.</p>

CC BY-SA 4.0
2023-11-28T02:53:06.240Z
2024-03-23T15:06:44.793Z
2024-03-23T15:06:44.793Z
Ethan T
<p>I need to extract bitmap-based subtitles to a standard image format like PNG or BMP. Preserving transparency would be a bonus. I don't need to convert to text, and I don't want a subtitle-specific format.</p>

<ffmpeg><subtitles>
How do you extract bitmap subtitles to a standard image format using ffmpeg?
Ethan T
# How do you extract bitmap subtitles to a standard image format using ffmpeg?

(Asked by: username_0 on 2023-11-28)

I need to extract bitmap-based subtitles to a standard image format like PNG or BMP. Preserving transparency would be a bonus. I don't need to convert to text, and I don't want a subtitle-specific format.

**Tags:** ffmpeg, subtitles


---

## 1 answers

### Answer by username_0 on 2023-11-28. Score: 2

The key is using the overlay filter to embed the subtitles on a transparent or fixed-color background. Adjust the `size` and `rate` to match your input video.

## Transparent version

`ffmpeg -i my_video.mkv -f lavfi -i "color=size=1920x1080:rate=23.98:color=black@0.0,format=rgba" -filter_complex "[1:v][0:s]overlay,mpdecimate[out]" -map "[out]" -an -vsync vfr frames_%04d.png`

This means:

* `-i my_video.mkv`: Input filename
* `-f lavfi`: The next input is a [`libavfilter` graph specification](https://ffmpeg.org/ffmpeg-devices.html#lavfi).
* `-i "color=size=1920x1080:rate=23.98:color=black@0.0,format=rgba"`: Produce a video stream that is 1080p with a 23.98 fps frame rate. The `@0.0` specifier indicates a fully-transparent color, which requires `format=rgba`.
* `-filter_complex "[1:v][0:s]overlay,mpdecimate[out]"`: Overlay the first subtitle stream in input source 0 (the original video) atop the first video stream in input source 1 (the `lavfi` output). Decimate the output frames by removing all duplicates. Output a stream named "out".
* `-map "[out]"`: Use the stream named "out" in the final output.
* `-an`: Audio is disabled.
* `-vsync vfr`: Drop frame timestamps so that each unique frame, in sequence, is output only once.
* `frames_%04d.png`: Output frames\_0000.png where `0000` is an increasing number. If you expect more than 10000 unique frames, increase `%04d` to `%05d` for 5 digits, etc.

## Non-transparent version (much faster?)

If you can tolerate, or prefer, a non-transparent background, the process may run much faster. It goes 3-4x faster on my machine. Just remove the `@0.0,format=rgba` part.

`ffmpeg -i my_video.mkv -f lavfi -i "color=size=1920x1080:rate=23.98:color=black" -filter_complex "[1:v][0:s]overlay,mpdecimate[out]" -map "[out]" -an -vsync vfr frames_%04d.png`

## Output

You'll get a PNG for each frame of unique subtitle content, plus a frame of black/transparent in between. Maybe there's a way to filter out those blank frames, but for now I can handle that outside ffmpeg.

## Caution

If you add `-t` to limit the time of the extracted subtitles, be sure to add it twice: once after the `-i` for the input video and once after the `-i` for the black frames & subtitles. This will ensure that both streams terminate at the specified time; otherwise one stream will keep going for the full video duration.


---

