astromonerd
astromonerd

Reputation: 937

ffmpeg: Incompatible pixel format 'yuv420p' for codec 'png', auto-selecting format 'rgb24'

I have a bunch of .png files

file_000.png
file_005.png
file_010.png

I am using an inherited ffmpeg script to stitch together .png files into an .mp4 file. I don't understand all the flags, but I've used this script successfully in the past

## images_to_movie.sh
set -o noglob

in_files=$1
out_file=$2

ffmpeg \
    -framerate 10 \
    -loglevel warning \
    -pattern_type glob -i $in_files \
    -pix_fmt yuv420p \
    -vf 'crop=trunc(iw/2)*2:trunc(ih/2)*2:0:0' \
    -y \
    $out_file

with the command

./images_to_movie file_*.png files.mp4

I am now receiving the error

Incompatible pixel format 'yuv420p' for codec 'png', auto-selecting format 'rgb24'

Some searching reveals that

-pix_fmt yuv420p

is deprecated and I should instead use

-pix_fmt yuv420p -color_range 2

but the error remains. I tried using

-pix_fmt rgb24

and the error disappears but I'm no .mp4 file is created.

How do I need to modify this script to create an .mp4 ?

Upvotes: 0

Views: 4013

Answers (1)

Charles Duffy
Charles Duffy

Reputation: 295679

What's Going Wrong

file_*.png isn't being passed to your program at all -- neither is files.mp4.

Instead, when you run ./images_to_movie file_*.png files.mp4, what your shell actually invokes is ./images_to_movie file_000.png file_005.png file_010.png files.mp4.

Thus, file_000.png is treated as the only input file, and file_005.png is treated as the output file to use. The extra arguments (file_010.png and files.mp4) are in positions $3 and $4; are never read; and are thus ignored entirely.


How To Fix It

The original code assumes that ./images_to_movie file_*.png files.mp4 will put file_*.png in $1 and files.mp4 in $2. Unless file_*.png has no matches, that assumption is false.

set -o noglob prevents glob expansion from taking place after your script is started, but nothing in your script's contents can prevent the calling script from expanding globs beforehand. Thus, you want an invocation with quotes, akin to:

./images_to_movie 'file_*.png' files.mp4

...and script contents akin to:

#!/usr/bin/env bash

in_files=$1
out_file=$2

ffmpeg \
    -framerate 10 \
    -loglevel warning \
    -pattern_type glob -i "$in_files" \
    -pix_fmt rgb24 \
    -vf 'crop=trunc(iw/2)*2:trunc(ih/2)*2:0:0' \
    -y \
    "$out_file"

Note that we took out the noglob, and instead quoted all expansions; this not only prevents globbing, but also prevents string-splitting -- so a pattern like File *.png wouldn't be split into one word File and a second word *.png even in the absence of globbing.

Upvotes: 2

Related Questions