Ffmpeg-python: Support filters without input

Created on 19 Aug 2018  路  5Comments  路  Source: kkroening/ffmpeg-python

I have a video file (with audio) and I want to prepend a few seconds of still background (i.e. black) image without sound. I'm trying to do this with ffmpeg-python, but no success yet.

First thing I stumbled upon is the missing support for the color input file (see my remark here), however, I can work around that by creating a black PNG image and loading that in, e.g. using ffmpeg.input("black.png", t=10).

However, now I need to concatenate the background video with the original video, but I can't because the background video doesn't have audio, and concat requires a matching number of audio/video streams. So then I found the aevalsrc filter in ffmpeg, which generates a (silent) audio stream, but I can't make it work with ffmpeg-python, since it is a filter that doesn't require input. E.g. this doesn't work:

stream = ffmpeg.input("black.png", t=10)
stream.filter("aevalsrc", exprs="0", duration=10)

Is there any way to achieve such a thing?

enhancement

Most helpful comment

Any updates on this?

All 5 comments

Not yet. #62 is indeed the feature that addresses this but it's not quite ready for production yet. I haven't had time to work on it but will make a mental note to bump priority.

Ok, good to hear. Let me know if I can help somehow.

For those also wanting this feature, I have worked around it by creating a simple black .png file and an small .mp3 file with no sound. Then I load them in with ffmpeg.input(filename, ...) and a certain duration. Of course a bit hacky, but this way at least it is possible with ffmpeg-python.

Any updates on this?

... I found another workaround.

ffmpeg-python creates a list of arguments and calls ffmpeg with that list in the end. The simple idea is to patch this list before it gets executed:

stream = ffmpeg.input("black.mp4") # this file does not need to exist
# ... do your fades and overlays...
ffmpegargs = patch(ffmpeg.compile(stream, overwrite_output=True))
out = subprocess.run(ffmpegargs, capture_output=True)
# done!

def patch(args): # replaces placeholder file with 
    for i, arg in enumerate(arglist):
        if arg == 'black.mp4':
            arglist[i] = 'color=black:size={0:d}x{1:d}:duration={2:.3f}:rate={3:.3f}'.format(...'
            return arglist[:i-1] + ['-f', 'lavfi'] + arglist[i-1:]
    return arglist

This trick also works nicely in other cases.

Best,
Bid

Was this page helpful?
0 / 5 - 0 ratings