Ffmpeg-python: How can I Use a palette to encode a GIF using ffmpeg?

Created on 18 Apr 2019  路  7Comments  路  Source: kkroening/ffmpeg-python

Like this : ffmpeg -i input.mkv -i palette.png -lavfi paletteuse output.gif

import ffmpeg
in_filename='C:\Users\Administrator\Desktop\py\img\'
(
ffmpeg
.input(in_filename+'girl.gif')
# .filter('palettegen', stats_mode='full')
# .output(in_filename+'palettegen_full.png')
.filter(filter_name='paletteuse', dither='bayer')
.output(in_filename+'paletteuse_bayer.gif')# , vframes=1, format='image2', vcodec='mjpeg'
.run(input=b'y')
)

Error:

Cannot find a matching stream for unlabeled input pad 1 on filter Parsed_paletteuse_0
Traceback (most recent call last):
File ".../test_little.py", line 116, in 
.run(input=b'y')
File "...\venv\lib\site-packages\ffmpeg_run.py", line 305, in run
raise Error('ffmpeg', out, err)
ffmpeg._run.Error: ffmpeg error (see stderr output for detail)
question

Most helpful comment

Instead of using ffmpeg.concat, use the multi-input form of ffmpeg.filter.
e.g.:

(
    ffmpeg.filter(
        [
            ffmpeg.input(in_filename+'girl.gif'),
            ffmpeg.input(in_filename+'palettegen-1.png'),
        ],
        filter_name='paletteuse',
        dither='heckbert',
        new='False',
    )
    .output(in_filename+'output.gif')
    .run(overwrite_output=True)
)

All 7 comments

I think that the problem is in the keyword you pass to the .run() method. Have you tried without input=b'y'?

Instead of .run() you can try using ffmpeg.get_args([insert your input/filter/output]) to see what ffmpeg command would be used.

In fact,It's still the same mistake without input=b'y'.
input=b'y' is skipping the print step in the console, because every time the program is executed with promptsFile '...\test.gif' already exists. Overwrite ? [y/N].
You mean like this?

ffmpeg.get_args(stream_spec='ffmpeg -i input.mp4 -i palette.png -lavfi paletteuse output.gif',overwrite_output=True)

Please forgive my foolishness. I don't quite understand the use of this.Can you give me an example?

I would suggest you use .run(overwrite_output=True) instead of .run(inputb'y'). that is clearer and should have the same effect.

Ah sorry, I was not clear enough, I meant:

ffmpeg
.input(in_filename+'girl.gif')
.filter(filter_name='paletteuse', dither='bayer')
.output(in_filename+'paletteuse_bayer.gif')
.get_args()

So replace the 'run' by 'get_args'.

Hmmm,I just want to know how to let an input file output according to the palette.
It means I need to change the default palette (GIF is limited to a palette of 256 colors) to my later generated palette (generally saved into a PNG file).

Input.mp4->palette.png: palettegen
palette.png->output.gif:paletteuse
Input.mp4->output.gif: paletteuse

I need to input two filters,one is input.mp4,the other is palette.png

palette="/tmp/palette.png"
filters="fps=15,scale=320:-1:flags=lanczos"
ffmpeg -i $1 -vf "$filters,palettegen" -y $palette
ffmpeg -i $1 -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y $2

Train of thought source: ###### High quality GIF with FFmpeg
I don't know how to express -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" in ffmpeg-python.
This is my test code:

import ffmpeg
in_filename = 'C:\\Users\\Administrator\\Desktop\\emo\\pyXCX\\img\\'
(
    ffmpeg
    .input(in_filename+'girl.gif')
    .filter(filter_name='palettegen')
    .output(in_filename+'palettegen-1.png',pix_fmt='pal8')
    .run(overwrite_output=True)
)
# Finish:[Parsed_palettegen_0 @ 000000000044d840] 255(+1) colors generated out of 255 colors; ratio=1.000000
print('------------------------------------------------------------------------------------')
(
    ffmpeg
    .input(in_filename+'girl.gif')
    .concat(
        ffmpeg.input(in_filename+'palettegen-1.png')
              .filter(filter_name='paletteuse', dither='heckbert', new='False')
    )
    .output(in_filename+'output.gif')
    .run(overwrite_output=True)
)
# Erorr:Palette input must contain exactly 256 pixels.
#       Failed to configure input pad on Parsed_paletteuse_0
#       Error reinitializing filters!
#       Failed to inject frame into filter network: Invalid argument
#       Error while processing the decoded data for stream #0:0

Instead of using ffmpeg.concat, use the multi-input form of ffmpeg.filter.
e.g.:

(
    ffmpeg.filter(
        [
            ffmpeg.input(in_filename+'girl.gif'),
            ffmpeg.input(in_filename+'palettegen-1.png'),
        ],
        filter_name='paletteuse',
        dither='heckbert',
        new='False',
    )
    .output(in_filename+'output.gif')
    .run(overwrite_output=True)
)

Aha,I got it.Although the output image is not the clarity I want, perhaps it is not appropriate for me to generate a palette.
Thank you.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cbitterfield picture cbitterfield  路  4Comments

tossorrow picture tossorrow  路  6Comments

znorris picture znorris  路  4Comments

reformstudios picture reformstudios  路  3Comments

Matttman picture Matttman  路  6Comments