Skip to content
Advertisement

How can I run an ffmpeg command in a python script?

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'))
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement