1

I have a huge command to run an executable with multiple parameters. It goes like this:

ffmpeg.exe -f dshow -y -video_size 1920x1080 -rtbufsize 1404000k -r 30 -i video="HD Video 2 (TC-2000HDMI Card)" -threads 2 -vcodec copy -ar 48000 -ac 1 -acodec pcm_s16le -t 60 c:/output.avi

I am using subprocess.Popen for this but not sure how to pass so many arguments using python 2.7

I have gone through many posts, one of them being this. I could not make it work for multiple arguments.

Need help regarding this.

Community
  • 1
  • 1
Sid
  • 45
  • 2
  • 9

2 Answers2

1

The example from subprocess.Popen shows an example of parsing a complex command line correctly for passing to Popen:

>>> import shlex, subprocess
>>> command_line = raw_input()
/bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo '$MONEY'"
>>> args = shlex.split(command_line)
>>> print args
['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"]
>>> p = subprocess.Popen(args) # Success!

Combining that with Python's triple quoting to allow for most quote varieties would give you something like this (haven't run it, sorry for the long command line):

import shlex, subprocess
p = subprocess.Popen(slex.split("""ffmpeg.exe -f dshow -y -video_size 1920x1080 -rtbufsize 1404000k -r 30 -i video="HD Video 2 (TC-2000HDMI Card)" -threads 2 -vcodec copy -ar 48000 -ac 1 -acodec pcm_s16le -t 60 c:/output.avi"""))
Alex Taylor
  • 8,343
  • 4
  • 25
  • 40
  • Thanks for the reply @Alex. Is there a way I can mention the path to my exe in the above command – Sid Oct 26 '15 at 10:43
  • You should be able to the path after the first triple quote and before `ffmpeg.exe`. It may need double-quotes around the path+executable if there are spaces in it (and there probably will be on Windows). – Alex Taylor Oct 26 '15 at 22:04
  • BTW, I think @J.F. Sebastian's answer is the better one. – Alex Taylor Oct 26 '15 at 22:06
  • This answer suits my needs, thus accepting it as correct. However both the approaches can be considered. – Sid Oct 28 '15 at 06:26
1

.exe suggests that you are on Windows where the native interface to specify a command to run is a string i.e., paste the string as is:

#!/usr/bin/env python
import subprocess

subprocess.check_call('ffmpeg.exe -f dshow -y -video_size 1920x1080 '
                      '-rtbufsize 1404000k -r 30 '
                      '-i video="HD Video 2 (TC-2000HDMI Card)" '
                      '-threads 2 -vcodec copy -ar 48000 -ac 1 -acodec pcm_s16le '
                      r'-t 60 c:\output.avi')

Note: the command is split into several literals only to spread it over multiple lines for readability. 'a' 'b' literals coalesce into 'ab' in Python.

If the command is not a literal string then it might be more convient to use a list, to specify the command:

#!/usr/bin/env python
import subprocess

nthreads = 2
width, height = 1920, 1080
filename = r'c:\output.avi'
subprocess.check_call([
        'ffmpeg', '-f', 'dshow', '-y',
        '-video_size', '%dx%d' % (width, height),
        '-rtbufsize', '1404000k', '-r', '30', 
        '-i', 'video=HD Video 2 (TC-2000HDMI Card)',
        '-threads', str(nthreads), '-vcodec', 'copy', '-ar', '48000', '-ac', '1',
        '-acodec', 'pcm_s16le', '-t', '60', 
        filename])

Note: if only a name without a path and file extension is given then .exe is appended automatically. This also makes the second form more portable.

To avoid escaping backslash in Windows paths, raw string literals could be used i.e., you could write r'C:\User\...' instead of 'C:\\User\\...'.

jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • Thanks for the reply @Sebastian. I have 2 queries regarding this, - what if I dont want to hard-code the path to exe and output file. I want to store the output in my current working directory. - how do i give the path to my exe in the above example if the exe is placed in a subfolder in my cwd – Sid Oct 26 '15 at 12:04
  • 1
    @Sid: there is no path in the code. If ffmpeg's folder is in `%PATH%`; the exe will be found. It is better to add the corresponding folder to the PATH envvar if it is not there already but if you want to specify the path relative to the current working directly then it is simple `r'relative\path'` (i.e., the current directory has `'relative'` subfolder that in turn has `'path'` subfolder). – jfs Oct 26 '15 at 12:44
  • @Sebastian Here is what I am doing: `mydir = os.getcwd()` and I am appending it to the exe location `exename = mydir + r'\3rdparty\ffmpeg-20150907-git-b480f0e-win64-static\bin\ffmpeg.exe'` And I am passing this `exename` to `subprocess.check_call()`, I want this path to be processed as a raw but it is not happening – Sid Oct 27 '15 at 05:12
  • @Sid: do you see `os.getcwd()` in my previous comment? If you don't want to add the corresponding folder to PATH environment variable and you do not understand what `r'relative\path'` mean in the comment then ask a separate question (e.g., "how to run `ffmpeg.exe` using a relative path"). You could use `ffmpeg --help` command for testing. *"it is not happening"* is not very informative, describe in a new question what you expect to happen and what happens instead. – jfs Oct 27 '15 at 05:17
  • Also if I use the exe name directly, its still not working: I am getting a `CalledProcessError` – Sid Oct 27 '15 at 05:21
  • @Sid: `CalledProcessError` means that `subprocess` have found `ffmpeg` executable successfully but `ffmpeg` has finished with non-zero exit status. It means that you don't have issue with the ffmpeg's path: it may indicate invalid command-line options, invalid input files, any other ffmpeg's specific error. If you run **the exact same** command in Windows console; it should also produce non-zero status (`echo %errorlevel%`) – jfs Oct 27 '15 at 05:33