How do I send EOF to a av.filter.Graph?
Overview
I'm trying to use the FFMPEG filter palettegen
to compute a color pallette for a video (and then turn it into a GIF later on). However, the filter expects to read a full video and wishes to receive an EOF error (relevant line inside FFmpeg source) before it outputs a single 256 color pallette.
When using the binary, this can be achieved as: ffmpeg -i testsrc.mp4 -vf palettegen pallette.png
(To generate a test video: ffmpeg -f lavfi -i testsrc -t 10 -pix_fmt yuv444p testsrc.mp4
)
However, writing the same in pyAV the filter never produces an output, because it waits for the EOF signal. I don't know how to send it, nor have I been able to work it out from the source code. A pointer would be highly appreciated :)
Here is the code as far as I got:
import av
import av.filter
graph = av.filter.Graph()
with av.open("testsrc.mp4", "r") as container:
video_stream = container.streams.video[0]
# setup filter graph
video_in = graph.add_buffer(template=video_stream)
palette_gen_filter = graph.add("palettegen")
video_out = graph.add("buffersink")
video_in.link_to(palette_gen_filter)
palette_gen_filter.link_to(video_out)
graph.configure()
for frame in container.decode(video=0):
graph.push(frame)
# TODO: Send EOF ... but how?
palette_frame = graph.pull() # this currently fails
The above currently fails with the following exception:
Traceback (most recent call last):
File "delete_me.py", line 22, in <module>
palette_frame = graph.pull() # this currently fails
File "av/filter/graph.pyx", line 212, in av.filter.graph.Graph.pull
File "av/filter/context.pyx", line 107, in av.filter.context.FilterContext.pull
File "av/error.pyx", line 336, in av.error.err_check
av.error.BlockingIOError: [Errno 11] Resource temporarily unavailable