I want to overlay a transparent video over top of an image using ffmpeg and python
I am able to do this successfully through terminal, but I cannot get ffmpeg commands to work in python. The following command produces the result that I want in terminal when I am in the directory with the files there.
ffmpeg -i head1.png -i hdmiSpitting.mov -filter_complex "[0:v][1:v] overlay=0:0" -pix_fmt yuv420p -:a copy output3.mov
In python, my code is simple:
import os import subprocess command = "ffmpeg -i head1.png -i hdmiSpitting.mov -filter_complex "[0:v][1:v] overlay=0:0" -pix_fmt yuv420p -c:a copy output3.mov" subprocess.call(command,shell=True)
The code runs, there is no indication of an error, but no output is produced.
What am I missing here?
Advertisement
Answer
In Windows one line with spaces should work, but in Linux we have to pass the arguments as list.
We can build the command as a list:
command = ['ffmpeg', '-i', 'head1.png', '-i', 'hdmiSpitting.mov', '-filter_complex', '[0:v][1:v]overlay=0:0', '-pix_fmt', 'yuv420p', '-c:a', 'copy', 'output3.mov']
We may also use
shlex.split
:import shlex command = shlex.split('ffmpeg -i head1.png -i hdmiSpitting.mov -filter_complex "[0:v][1:v] overlay=0:0" -pix_fmt yuv420p -c:a copy output3.mov')
Adding -y
argument:
If the output file output3.mov
already exists, FFmpeg prints a message:
File 'output3.mov' already exists. Overwrite? [y/N]
And waits for the user to press y
.
In some development environments we can’t see the message.
Add -y
for overwriting the output if already exists (without asking):
command = shlex.split('ffmpeg -y -i head1.png -i hdmiSpitting.mov -filter_complex "[0:v][1:v] overlay=0:0" -pix_fmt yuv420p -c:a copy output3.mov')
Path issues:
There are cases when ffmpeg
executable is not in the execution path.
Using full path may be necessary.
Example for Windows (assuming ffmpeg.exe is in c:FFmpegbin
):
command = shlex.split('c:\FFmpeg\bin\ffmpeg.exe -y -i head1.png -i hdmiSpitting.mov -filter_complex "[0:v][1:v] overlay=0:0" -pix_fmt yuv420p -c:a copy output3.mov')
In Linux, the default path is /usr/bin/ffmpeg
.
Using shell=True
is not recommended and considered “unsafe”.
For details see Security Considerations.
The default is False
, so we may use subprocess.call(command)
.
Note: subprocess.run
supposes to replace subprocess.call
.
See this post for details.
Creating log file by adding -report
argument:
In some development environments we can’t see FFmpeg messages, which are printed to the console (written to stderr
).
Adding -report
argument creates a log file with name like ffmpeg-20220624-114156.log
.
The log file may tell us what went wrong when we can’t see the console.
Example:
import subprocess import shlex subprocess.run(shlex.split('ffmpeg -y -i head1.png -i hdmiSpitting.mov -filter_complex "[0:v][1:v] overlay=0:0" -pix_fmt yuv420p -c:a copy output3.mov -report'))