2

I'm trying to validate certain parameters of a media file before the file gets saved in Django. So I validate the file using ffprobe (from the ffmpeg pip package).

with NamedTemporaryFile(suffix=f'.{self.audio.name.split(".")[-1]}') as fp:
    fp.write(self.audio.read())
    try:
        # Get duration with ffprobe
        info = probe(fp.name)
        self.duration = info['format']['duration']
        fp.close()
    except ffmpeg.Error as e:
        print('stderr:', e.stderr.decode('utf8'))
        raise NotAudioFile
    except:
        traceback.print_exc()
        raise NotAudioFile

This is the snippet that validates the file. self.audio is a Django FileField. It creates a named temporary file, writes the file from the django file, and then validates it using ffprobe.

However, when it runs, ffprobe gives me a Permission Denied error, which is weird, since I checked the file and I have full permission to write that directory/file.

stderr: ffprobe version 4.3.2-2021-02-20-essentials_build-www.gyan.dev Copyright (c) 2007-2021 the FFmpeg developers
  built with gcc 10.2.0 (Rev6, Built by MSYS2 project)
  configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-lzma --enable-zlib --enable-libsr
t --enable-libssh --enable-libzmq --enable-avisynth --enable-sdl2 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-libaom --enable-libopenjpeg --enable-libvpx --enable-libass --enable-libfreetype --ena
ble-libfribidi --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-d3d11va --enable-dxva2 --enable-libmfx --enable-libgme
--enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libtheora --enable-libvo-amrwbenc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-librubberband
  libavutil      56. 51.100 / 56. 51.100
  libavcodec     58. 91.100 / 58. 91.100
  libavformat    58. 45.100 / 58. 45.100
  libavdevice    58. 10.100 / 58. 10.100
  libavfilter     7. 85.100 /  7. 85.100
  libswscale      5.  7.100 /  5.  7.100
  libswresample   3.  7.100 /  3.  7.100
  libpostproc    55.  7.100 / 55.  7.100
C:\Users\cclloyd\AppData\Local\Temp\tmp9lhjsl9n.mp3: Permission denied

So why is it giving me that error?

cclloyd
  • 8,171
  • 16
  • 57
  • 104

1 Answers1

3

As per the documentation:

...name can be retrieved from the name attribute of the returned file-like object. 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). If delete is true (the default), the file is deleted as soon as it is closed.

When you pass fp.name to probe() function, the ffprobe process attempts to access/open the file, but - as described above and here - Windows does not allow processes other than the one used to create the NamedTemporaryFile to access the file when the delete is set to True. Thus, you should set delete to False when creating a new instance of a NamedTemporaryFile, and delete the file once you are done with it using the os.remove() or os.unlink() method. Example below:

f = NamedTemporaryFile(delete=False, suffix=f'.{self.audio.name.split(".")[-1]}')
try:
    f.write(self.audio.read())
    try:
        # Get duration with ffprobe
        info = probe(f.name)
        self.duration = info['format']['duration']
    except ffmpeg.Error as e:
        print('stderr:', e.stderr.decode('utf8'))
        raise NotAudioFile
    except:
        traceback.print_exc()
        raise NotAudioFile
finally:
    f.close()
    os.remove(f.name)  # delete the file
Chris
  • 18,724
  • 6
  • 46
  • 80