subprocess call ffmpeg (command line)
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))
Comments
-
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 over 9 yearsRun 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 variablecmd
, runsubprocess.call(cmd.split())
and wait for the magic. -
tdelaney over 9 yearsWhat is the error? shell=True may solve it.
-
user3295674 over 9 yearsThanks, 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 over 9 yearsThe command you want to run has
frame%03d.png
. The command you're running withsubprocess
hasframe%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 over 9 yearsUnrelated, 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 over 9 yearsThank 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 over 9 yearsNote that ffmpeg itself can interpret
%03d
syntax in filename specs. -
user3295674 over 9 years@PM2Ring that's what I thought, but it tells me 'no such file as frame%03d.png' Thoughts?
-
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 over 9 yearsI 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 over 9 yearsOh good. But why
str(out_movie)
? Isn'tout_movie
already a string? -
jfs over 9 yearsThere can't be any whitespace issues with
frame%03d.png
. Using quotes is useless here. Usepipes.quote(moviename)
instead of"%s"
. -
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 over 9 yearsthere is no python-3.x tag, therefore I've used
pipes.quote
instead ofshlex.quote
name (it is the same function). -
user3295674 over 9 yearsCorrect, that's redundant. :) But this method gives a clean answer.
-
tiktak about 6 yearsIf
out_movie
comes from an API or user input, this is unsafe. @jfs answer would be better. -
Fabien Snauwaert over 3 yearsSplitting 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.