shardulc
shardulc

Reputation: 301

Executing ffmpeg from Python

I'm trying to run ffmpeg on all the WAV files in a directory to convert them to mp3. This command works fine when I run it from the command-line, on my Fedora Linux machine:

/usr/bin/ffmpeg -i "Name With Spaces.wav" Name_With_Spaces.mp3

where Name With Spaces.wav is a file in the current directory. However, in Python 3.2 running in the same directory:

import os
files = os.listdir()
os.execl('/usr/bin/ffmpeg', '-i \"' + files[0] + '\"', files[0][:-4].replace(' ', '_') + '.mp3')

gives me the error (from ffmpeg): At least one input file must be specified. I don't see why this isn't working, because '-i \"' + files[0] + '\"' evaluates to -i "Name With Spaces.wav" and files[0][:-4].replace(' ', '_') + '.mp3' evaluates to Name_With_Spaces.mp3.

I've tried escaping spaces, using different quotation marks, using the full path (like /home/.../music/Name\ With\ Spaces.wav), and actually replacing the arguments with the real text, but nothing works. How can I get this to work?

Upvotes: 1

Views: 1311

Answers (2)

mprat
mprat

Reputation: 2481

I think it has something to do with how os.execl is reading the input that you are sending it. From the docs, it is interpreting each argument it gets as a separate argument, rather than a group of arguments. So it is internally doing something more clever than " ".join() the arguments you are giving to it. It is probably escaping any spaces you have outside quotation marks in each of the arguments you are sending.

One way to fix it would be to split up the "-i" part of the argument from the rest of the parameter:

os.execl('/usr/bin/ffmpeg', '-i', \"' + files[0] + '\", files[0][:-4].replace(' ', '_') + '.mp3')

For sanity, if you do the same code using os.system, it should work:

os.system(" ".join(['/usr/bin/ffmpeg', '-i \"' + files[0] + '\"', files[0][:-4].replace(' ', '_') + '.mp3']))

Alternatively, you can use subprocess:

import subprocess
subprocess.call(['/usr/bin/ffmpeg', '-i', \"' + files[0] + '\", files[0][:-4].replace(' ', '_') + '.mp3'])

Upvotes: -1

lapinkoira
lapinkoira

Reputation: 9008

If you want to use the os.execl method you have to modify your syntax a bit and -i must go as a different item in the list

import os
files = os.listdir()
# Separated the args to make it clear
args = '/usr/bin/ffmpeg', '-i', files[0], files[0][:-4].replace(' ', '_') + '.mp3'
# Yes, the binary appears twice
os.execl('/usr/bin/ffmpeg', *args)

The various exec* functions take a list of arguments for the new program loaded into the process. In each case, the first of these arguments is passed to the new program as its own name rather than as an argument a user may have typed on a command line. For the C programmer, this is the argv[0] passed to a program’s main(). For example, os.execv('/bin/echo', ['foo', 'bar']) will only print bar on standard output; foo will seem to be ignored.

Source https://docs.python.org/2/library/os.html#process-management

Upvotes: 2

Related Questions