Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

fix bugs for windows. thanks John Gilik!

  • Loading branch information...
commit d04b2a6653c71d5f87a88df8d7e9b5203d84f22e 1 parent 020d0bd
@jiaaro authored
Showing with 22 additions and 6 deletions.
  1. +22 −6 pydub/audio_segment.py
View
28 pydub/audio_segment.py
@@ -179,16 +179,18 @@ def from_file(cls, file, format=None):
if not format:
format = os.path.splitext(file.name)[1]
+ format = format.strip(".")
+
format = AUDIO_FILE_EXT_ALIASES.get(format, format)
if format == 'wav':
return cls.from_wav(file)
- input = NamedTemporaryFile(mode='wb')
+ input = NamedTemporaryFile(mode='wb', delete=False)
input.write(file.read())
input.flush()
- output = NamedTemporaryFile(mode="rb")
+ output = NamedTemporaryFile(mode="rb", delete=False)
ffmpeg_call = [cls.ffmpeg,
'-y', # always overwrite existing files
@@ -206,8 +208,17 @@ def from_file(cls, file, format=None):
subprocess.call(ffmpeg_call,
stderr=open(os.devnull)
)
+
+ obj = cls.from_wav(output)
+
input.close()
- return cls.from_wav(output)
+ output.close()
+ os.unlink(input.name)
+ os.unlink(output.name)
+
+ return obj
+
+
@classmethod
def from_mp3(cls, file):
@@ -248,7 +259,7 @@ def export(self, out_f=None, format='mp3', codec=None):
if format == 'wav':
return out_f
- output = NamedTemporaryFile(mode="w+")
+ output = NamedTemporaryFile(mode="w+", delete=False)
# build call args
args =[self.ffmpeg,
@@ -269,8 +280,13 @@ def export(self, out_f=None, format='mp3', codec=None):
output.seek(0)
out_f.write(output.read())
-
- data.unlink(data.name)
+
+ data.close()
+ output.close()
+
+ os.unlink(data.name)
+ os.unlink(output.name)
+
out_f.seek(0)
return out_f

1 comment on commit d04b2a6

@jiaaro
Owner

Bug report and Fix came via email:

Hi James,

I'm still learning how to deal with GitHub, so please accept my apologies for this email not being a pull request.

pydub has two issues running on Windows 7 x64 SP1 (and likely other variants):

  1. from_file() yields '.mp3' as the extension for an MP3 file instead of 'mp3', causing it to pass '.mp3' to ffmpeg. This causes ffmpeg to immediately fail with return code 1--stripping the dots fixes this. I changed this section in AudioSegment.py::

    if not format:
        format = os.path.splitext(file.name)[1]
    

by adding::

    while format[0] == '.':
        format = format[1:]
  1. Use of NamedTemporaryFile to generate names for the input and output of ffmpeg is problematic. Note that you're starting a subprocess to play with these files, while the API documentation ( http://docs.python.org/2/library/tempfile.html ) states: "Whether the name can be used to open the file a second time, while the named temporary file is still open, varies across platforms (it can be so used on Unix; it cannot on Windows NT or later)". The fix from the page I got this quote from ( https://github.com/MostAwesomeDude/bravo/issues/111 ) seems to work, though:

I changed the two NamedTemporaryFile calls to include delete=False::

    input = NamedTemporaryFile(mode='wb', delete=False)
    input.write(file.read())
    input.flush()

    output = NamedTemporaryFile(mode="rb", delete=False)

I closed and unlinked the temporary files manually after reading output::

    obj = cls.from_wav(output)
    input.close()
    os.unlink(input.name)
    output.close()
    os.unlink(output.name)
    return obj

Thus, my modified AudioSegment::from_file() function reads as follows:

@classmethod
def from_file(cls, file, format=None):
    file = _fd_or_path_or_tempfile(file, 'rb', tempfile=False)

    if not format:
        format = os.path.splitext(file.name)[1]
    while format[0] == '.':
        format = format[1:]
    format = AUDIO_FILE_EXT_ALIASES.get(format, format)

    if format == 'wav':
        return cls.from_wav(file)

    input = NamedTemporaryFile(mode='wb', delete=False)
    input.write(file.read())
    input.flush()

    output = NamedTemporaryFile(mode="rb", delete=False)

    ffmpeg_call = [cls.ffmpeg,
                   '-y',  # always overwrite existing files
                   ]
    if format:
        ffmpeg_call += ["-f", format]
    ffmpeg_call += [
                    "-i", input.name,  # input options (filename last)
                    "-vn",  # Drop any video streams if there are any

                    "-f", "wav",  # output options (filename last)
                    output.name
                    ]

    subprocess.call(ffmpeg_call,
                    stderr=open(os.devnull)
                    )
    obj = cls.from_wav(output)
    input.close()
    os.unlink(input.name)
    output.close()
    os.unlink(output.name)
    return obj

Again, sorry for the lack of Git pull request. I'll find time to learn soon, I hope.

Regards,
John

Please sign in to comment.
Something went wrong with that request. Please try again.