Reputation: 89
I have found a couple answers that solve the problem of passing wildcards through Popen, but I can't seem to get those solutions to work for my particular case.
I have a project that will merge an audio and video file when a button is pressed, and I need to use subprocess.Popen to execute the command I want:
mergeFile = "ffmpeg -i /home/pi/Video/* -i /home/pi/Audio/test.wav -acodec copy -vcodec copymap 0:v -map 1:a /home/pi/Test/output.mkv"
proc= subprocess.Popen(shlex.split(mergeFiles), shell=True)
I basically want to take whatever file is in my Video folder (my project downloads videos from a camera and the name of the file changes every time a new video is saved) and merge the audio from a separate "Audio" folder and then save that file to yet another folder.
I have tried setting the shell to true, and nothing works.
I also don't know how the glob module would help me in this scenario.
Upvotes: 0
Views: 1348
Reputation: 295687
The problem here is the shlex.split()
. When used in conjunction with shell=True
, it means that only the string ffmpeg
is treated as a script, and that the other components of your command line are passed as arguments to that script (which it never looks at / reads).
mergeFile = "ffmpeg -i /home/pi/Video/* -i /home/pi/Audio/test.wav -acodec copy -vcodec copymap 0:v -map 1:a /home/pi/Test/output.mkv"
proc = subprocess.Popen(mergeFile, shell=True)
A better-practice alternative that still uses shell=True
(if you're actually parameterizing the directory names and filenames) might be:
mergeFile=[
'ffmpeg -i "$1"/* -i "$2" -acodec copy -vcodec copymap 0:v -map 1:a "$3"',
'_', # placeholder for $0
"/home/pi/Video", # directory for $1 -- can use a variable here
"/home/pi/Audio/test.wav",
"/home/pi/Test/output.mkv",
]
subprocess.Popen(mergeFile, shell=True)
...in which case the script itself is constant (and can't have its meaning changed by values injected via filenames or other parameters), but out-of-band data can be provided.
Even better than that is to stop using shell=True
altogether. Consider:
import subprocess, glob
mergeFile=[
'ffmpeg', '-i',
] + (glob.glob('/home/pi/Video/*') or ['/home/pi/Video/*']) + [
'-i', '/home/pi/Audio/test.wav',
'-acodec', 'copy',
'-vcodec', 'copymap', '0:v',
'-map', '1:a1',
'/home/pi/Test/output.mkv'
]
subprocess.Popen(mergefile)
The or ['/home/pi/Video/*']
exists to cause the same error message you'd get with a shell if no files matching the glob exist. Obviously, you could just abort in that case as well.
Upvotes: 1