yPhil
yPhil

Reputation: 8357

Python: Passing complex (ffmpeg) arguments to Popen

This ffmpeg Popen invocation works :

command = ['ffmpeg', '-y',
           '-i', filename,
           '-filter_complex', 'showwavespic',
           '-colorkey', 'red',
           '-frames:v', '1',
           '-s', '800:30',
           '-vsync', '2',
           '/tmp/waveform.png']
process = sp.Popen( command, stdin=sp.PIPE, stderr=sp.PIPE)
process.wait()

But I need to use 'compand, showwavespic' and this comma seems to be blocking the execution. I also need to pass all sorts of strange characters, like columns and, well, all that you can find in a CLI invocation.

How can I pass complex arguments?

Upvotes: 1

Views: 946

Answers (1)

Dietrich Epp
Dietrich Epp

Reputation: 213258

These are just regular Python strings. The string value is passed directly to FFmpeg, without any interpretation by the shell.

So when you see a command-line example like this,

ffmpeg -i input -filter_complex "showwavespic=s=640x120" -frames:v 1 output.png

First, since the examples are passed to the shell, we have to "undo" the shell quoting.

ffmpeg
-i
input
-filter_complex
showwavespic=s=640x120
-frames:v
1
output.png

Then, we put it into a Python list.

command = [
    'ffmpeg',
    '-i',
    'input',
    '-filter_complex',
    'showwavespic=s=640x120',
    '-frames:v',
    '1',
    'output.png',
]

As you can see, commas, spaces, and most other characters are not treated any differently, so there is nothing you need to do to quote them. The main special characters are \ and ' which must be quoted, control characters which must be quoted as well, and the NUL character which cannot be used at all.

More complicated example

In shell:

  ffmpeg -i in.mp4 -ac 2 -filter_complex:a '[0:a]aresample=8000,asplit[l][r]' \
    -map '[l]' -c:a pcm_s16le -f data /tmp/plot-waveform-ac1 \
    -map '[r]' -c:a pcm_s16le -f data /tmp/plot-waveform-ac2

In Python:

command = [
    'ffmpeg',
    '-i', 'in.mp4',
    '-ac', '2',
    '-filter_complex:a', '[0:a]aresample=8000,asplit[l][r]',
    '-map', '[l]',
    '-c:a', 'pcm_s16le',
    '-f', 'data',
    '/tmp/plot-waveform-ac1',
    '-map', '[r]',
    '-c:a', 'pcm_s16le',
    '-f', 'data',
    '/tmp/plot-waveform-ac2',
]

As you can see, fairly straightforward. Python is just a little more verbose, but more regular.

Upvotes: 3

Related Questions