subprocess call ffmpeg (command line)

33,659

Solution 1

I found this alternative, simple, answer to also work.

subprocess.call('ffmpeg -r 10 -i frame%03d.png -r ntsc '+str(out_movie), shell=True)

Solution 2

When you use subprocess, your command must either be a string that looks exactly like what you would type on the command line (and you set shell=True), or a list where each command is an item in the list (and you take the default shell=False). In either case, you have to deal with the variable part of the string. For instance, the operating system has no idea what "%03d" is, you have to fill it in.

I can't tell from your question exactly what the parameters are, but lets assume you want to convert frame 3, it would look something like this in a string:

my_frame = 3
subprocess.call(
    'ffmpeg -r 10 -i frame%03d.png -r ntsc movie%03d.mpg' % (my_frame, my_frame),
    shell=True)

Its kinda subtle in this example, but that's risky. Suppose these things were in a directory whose name name had spaces (e.g., ./My Movies/Scary Movie). The shell would be confused by those spaces.

So, you can put it into a list and avoid the problem

my_frame = 3
subprocess.call([
    'ffmpeg',
    '-r', '10',
    '-i', 'frame%03d.png' % my_frame,
    '-r', 'ntsc',
    'movie%03d.mpg' % my_frame,
])

More typing, but safer.

Solution 3

import shlex
import pipes
from subprocess import check_call

command = 'ffmpeg -r 10 -i frame%03d.png -r ntsc ' + pipes.quote(out_movie)
check_call(shlex.split(command))
Share:
33,659
user3295674
Author by

user3295674

Opera singer & Programmer

Updated on July 23, 2021

Comments

  • user3295674
    user3295674 almost 3 years

    I have been incorporating subprocess calls in my program. I have had no issues with subprocess calls for other commands, but I am having trouble getting the command line input

    ffmpeg -r 10 -i frame%03d.png -r ntsc movie.mpg
    

    To work inside a subprocess.call()

    I tried the following with no success:

    subprocess.call('ffmpeg -r 10 -i %s frame%03.d.png - r ntsc movie.mpg')
    

    Any thoughts? Do I separate out different commands, do I specify string, integer etc. with %s, %d?

    • sberry
      sberry over 9 years
      Run your command, but with each argument split out in a list. If you do it as a single string then you will have to specify shell=True which you likely don't want to do anyway. So, assuming your command is built up as variable cmd, run subprocess.call(cmd.split()) and wait for the magic.
    • tdelaney
      tdelaney over 9 years
      What is the error? shell=True may solve it.
    • user3295674
      user3295674 over 9 years
      Thanks, yes, shell=True lets me run the commands as one big string, but I was also curious to see the syntax for it if I replace 'movie.mpg' with a variable name.
    • abarnert
      abarnert over 9 years
      The command you want to run has frame%03d.png. The command you're running with subprocess has frame%03.d.png . It also has an extra %s that doesn't correspond to anything in your command. So… what exactly are you trying to do? What's the actual command line you want to execute?
    • llogan
      llogan over 9 years
      Unrelated, but you should use -framerate instead of -r when using the image2 demuxer since, IIRC, it is less picky if the inputs vary by frame size or pixel format.
  • user3295674
    user3295674 over 9 years
    Thank you. I have a question, for the 'frame' part I want it to take all the files in the directory in the format frame###.png to stitch them together, not just one frame. Should I create a variable for a string called 'frame*.png' or something of the sort?
  • PM 2Ring
    PM 2Ring over 9 years
    Note that ffmpeg itself can interpret %03d syntax in filename specs.
  • user3295674
    user3295674 over 9 years
    @PM2Ring that's what I thought, but it tells me 'no such file as frame%03d.png' Thoughts?
  • PM 2Ring
    PM 2Ring over 9 years
    @user3295674 : That's weird. I haven't used ffmpeg (or avconv) for a few months, so I might be a bit rusty... Does putting the filename in quotes help? Try " double-quotes first and then single quotes '. I'd do some experiments myself, but it's getting late & I really should go. If you're sending this from Python, then if the whole command string is quoted with ' then you'll either need to escape any ' in the command string with a backslash, or use triple-quoting (like Python docstrings use) around the whole command string.
  • tdelaney
    tdelaney over 9 years
    I don't know the ffmpeg command line but if you can get it to select the frames, especially if you want many frames to go to one movie, is the best. You can get a list of files from os.listdir and search them for patterns you like, or use the glob module to do shell-like listings such as frame*.pgn.
  • PM 2Ring
    PM 2Ring over 9 years
    Oh good. But why str(out_movie)? Isn't out_movie already a string?
  • jfs
    jfs over 9 years
    There can't be any whitespace issues with frame%03d.png. Using quotes is useless here. Use pipes.quote(moviename) instead of "%s".
  • PM 2Ring
    PM 2Ring over 9 years
    @J.F.Sebastian : True, there's no whitespace issue here, I just put those quotes in as a general example for future reference. OTOH, I agree that the stuff I said about quoting in my last comment to tdelaney's post were not helpful; I should know better than to post at 5AM. :) But I didn't know about pipes.quote, so thanks for that (although I see in the docs that it's been deprecated in Python 3).
  • jfs
    jfs over 9 years
    there is no python-3.x tag, therefore I've used pipes.quote instead of shlex.quote name (it is the same function).
  • user3295674
    user3295674 over 9 years
    Correct, that's redundant. :) But this method gives a clean answer.
  • tiktak
    tiktak about 6 years
    If out_movie comes from an API or user input, this is unsafe. @jfs answer would be better.
  • Fabien Snauwaert
    Fabien Snauwaert over 3 years
    Splitting out arguments in a list is the way to go (when shell=False.) This helped me fix Error splitting the argument list: Option not found issues.