Closed ssssam closed 5 years ago
I've worked around the problem locally by adding an AUDIOREAD_BACKEND
env var which I can set to 'ffmpeg' to avoid steps 1-4. This is making my Beets experience a lot more enjoyable. However, it's a bit of an ugly workaround. I've opened this issue to see if someone can think of a cleaner way of avoiding the above issue.
look for coreaudio, which involves the 'ctypes' module invoking gcc -lAudioToolbox
That's alarming! I didn't know ctypes could invoke the C compiler. :flushed:
Anyway, it would definitely be nice to allow some (optional) visibility into and control over the backends that are used. In spirit, the main thing that would be useful would be to create an API that lets clients use the library in two stages: one to check which backends are "available" on the current platform (and perhaps to prioritize among the ones that are available), and a second one to actually process a file. This would let beets, for example, eliminate the Core Audio backend on non-Mac platforms once in a given invocation rather than trying it many times. It could also enable a beets config option to put ffmpeg first in the priority list.
Here's how this could work: the API could expose an AudioReader
class that does the first step of the work. When we construct an AudioReader
, we choose the available backends and the order they should be tried in. Invoked with no parameters, as in AudioReader()
, the reader should contain all of the available backends in a default order. Then, there's a method on this class called audioread.audio_read
that tries all the backends indicated by the object.
Then, our current main API, the audioread.audio_open
function, would become something like this:
def audio_open(filename):
reader = AudioReader()
return reader.audio_open(filename)
That is, it would create a new reader object every time and try all the backends every time—exactly like the current behavior.
How does that sound?
Sounds good to me. If I get time I will do a patch for audioread and a corresponding patch for beets.
The good news is, I implemented this change and I saw a 5x speed up in time taken to read MP3 files with the new API.
The bad news is that it seems very hard to use this new API from Beets. The 'acoustid' Python library, which consumes 'audioread', doesn't have a way to store an AudioReader instance (other than a module-level variable, which would have to be initialized during import acoustid
). The Beets 'chroma' plugin does have a place to store an AudioReader instance, but it doesn't have a hard dependency on the 'audioread' module. So to use the new feature, we'd need to add code that detects if the library is available or not, and code which detects if the AudioReader object is available in this version of the library.
To work around this issue, I have instead added a global _backends
variable in the audioread module, which is set the first time audio_open()
is called. This means Beets can benefit from the fix without having solve the problems mentioned above.
Hello all, In Windows 10 I am getting this:
y, sr = librosa.load(librosa.util.example_audio_file(), duration=5.0) Traceback (most recent call last): File "
", line 1, in File "C:\Users\Yelje\AppData\Local\Programs\Python\Python36\lib\site-packages\librosa\core\audio.py", line 112, in load with audioread.audio_open(os.path.realpath(path)) as input_file: File "C:\Users\Yelje\AppData\Local\Programs\Python\Python36\lib\site-packages\audioread__init__.py", line 116, in audio_open raise NoBackendError() audioread.NoBackendError
I'm using Beets with the 'chroma' plugin to import a large music collection, and I've been having performance issues.
One issue I spotted is that audioread is trying every backend, each time it tries to read a file. The process on my machine appears to be:
gcc -lAudioToolbox
ffmpeg
and read the data from that.This is burning a lot of CPU cycles unnecessarily. I haven't measured it scientifically, but from watching the output of
pstree -a -t
there seems to be a lot of time spent on steps 2 and 3.