Open bastibe opened 2 years ago
I opened an issue at libsndfile to investigate the latter issue: https://github.com/libsndfile/libsndfile/issues/837
(Or is this a soundfile-problem? It doesn't seem to originate from the Python code, though)
Trying renaming to .mpeg
gives a similar error:
---------------------------------------------------------------------------
LibsndfileError Traceback (most recent call last)
Input In [4], in <cell line: 1>()
----> 1 sf.read("sine.mpeg")
File ~/miniforge/lib/python3.9/site-packages/soundfile.py:282, in read(file, frames, start, stop, dtype, always_2d, fill_value, out, samplerate, channels, format, subtype, endian, closefd)
196 def read(file, frames=-1, start=0, stop=None, dtype='float64', always_2d=False,
197 fill_value=None, out=None, samplerate=None, channels=None,
198 format=None, subtype=None, endian=None, closefd=True):
199 """Provide audio data from a sound file as NumPy array.
200
201 By default, the whole file is read from the beginning, but the
(...)
280
281 """
--> 282 with SoundFile(file, 'r', samplerate, channels,
283 subtype, endian, format, closefd) as f:
284 frames = f._prepare_read(start, stop, frames)
285 data = f.read(frames, dtype, always_2d, fill_value, out)
File ~/miniforge/lib/python3.9/site-packages/soundfile.py:655, in SoundFile.__init__(self, file, mode, samplerate, channels, subtype, endian, format, closefd)
652 self._mode = mode
653 self._info = _create_info_struct(file, mode, samplerate, channels,
654 format, subtype, endian)
--> 655 self._file = self._open(file, mode_int, closefd)
656 if set(mode).issuperset('r+') and self.seekable():
657 # Move write position to 0 (like in Python file objects)
658 self.seek(0)
File ~/miniforge/lib/python3.9/site-packages/soundfile.py:1213, in SoundFile._open(self, file, mode_int, closefd)
1210 if file_ptr == _ffi.NULL:
1211 # get the actual error code
1212 err = _snd.sf_error(file_ptr)
-> 1213 raise LibsndfileError(err, prefix="Error opening {0!r}: ".format(self.name))
1214 if mode_int == _snd.SFM_WRITE:
1215 # Due to a bug in libsndfile version <= 1.0.25, frames != 0
1216 # when opening a named pipe in SFM_WRITE mode.
1217 # See http://github.com/erikd/libsndfile/issues/77.
1218 self._info.frames = 0
LibsndfileError: Error opening 'sine.mpeg': Format not recognised.
Forcing the format (format='MPEG', subtype='MPEG_LAYER_III'
) does not work either
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Input In [14], in <cell line: 1>()
----> 1 sf.read("sine.mp3", format="MPEG", subtype="MPEG_LAYER_III")
File ~/miniforge/lib/python3.9/site-packages/soundfile.py:282, in read(file, frames, start, stop, dtype, always_2d, fill_value, out, samplerate, channels, format, subtype, endian, closefd)
196 def read(file, frames=-1, start=0, stop=None, dtype='float64', always_2d=False,
197 fill_value=None, out=None, samplerate=None, channels=None,
198 format=None, subtype=None, endian=None, closefd=True):
199 """Provide audio data from a sound file as NumPy array.
200
201 By default, the whole file is read from the beginning, but the
(...)
280
281 """
--> 282 with SoundFile(file, 'r', samplerate, channels,
283 subtype, endian, format, closefd) as f:
284 frames = f._prepare_read(start, stop, frames)
285 data = f.read(frames, dtype, always_2d, fill_value, out)
File ~/miniforge/lib/python3.9/site-packages/soundfile.py:653, in SoundFile.__init__(self, file, mode, samplerate, channels, subtype, endian, format, closefd)
651 mode_int = _check_mode(mode)
652 self._mode = mode
--> 653 self._info = _create_info_struct(file, mode, samplerate, channels,
654 format, subtype, endian)
655 self._file = self._open(file, mode_int, closefd)
656 if set(mode).issuperset('r+') and self.seekable():
657 # Move write position to 0 (like in Python file objects)
File ~/miniforge/lib/python3.9/site-packages/soundfile.py:1480, in _create_info_struct(file, mode, samplerate, channels, format, subtype, endian)
1477 else:
1478 if any(arg is not None for arg in (
1479 samplerate, channels, original_format, subtype, endian)):
-> 1480 raise TypeError("Not allowed for existing files (except 'RAW'): "
1481 "samplerate, channels, format, subtype, endian")
1482 return info
TypeError: Not allowed for existing files (except 'RAW'): samplerate, channels, format, subtype, endian
I created a new environment to play with. Looks like a correct library is being loaded:
>>> sf._snd
<Lib object for '[...]/miniforge/envs/test/lib/python3.9/site-packages/_soundfile_data/libsndfile_arm64.dylib'>
Version is also correct:
>>> sf.__libsndfile_version__
'1.1.0'
@bastibe Some more debugging. I discovered that the standard version of libsndfile installed on M1 mac via brew does not have mp3 support enabled.
I edited the formula (brew edit libsndfile
) by adding depends_on "mpg123"
. Upon re-building (brew reinstall --build-from-source libsndfile
) I was finally able to use the in-built command (sndfile-info sine.mp3
) which gave me the correct info. Before I would get something along the lines of "This version was built without mp3 support".
========================================
File : sine.mp3
Length : 80256
MPEG-1/2 Audio
----------------------------------------
MPEG version : MPEG 1.0
layer : 3
rate : 48000
mode : mono
mode ext : 0
framesize : 192
crc : 0
copyright flag : 0
private flag : 0
original flag : 1
emphasis : 0
bitrate mode : constant
bitrate : 64 kbps
----------------------------------------
Sample Rate : 48000
Frames : 481536
Channels : 1
Format : 0x00230082
Sections : 1
Seekable : TRUE
Duration : 00:00:10.032
Signal Max : 31688.3 (-0.29 dB)
Next, I removed the the libsndfile_arm64.dylib
which was bundled with pysoundfile, in order to force pysoundfile to look for homebrew version of libsndfile - it got it.
sf._snd
<Lib object for '/opt/homebrew/lib/libsndfile.dylib'>
And now, finally, it reads the mp3 file and MPEG*_ appears in the list of available subtypes.
sf.read("/Users/as2/sine.mp3")
(array([ 0.00000000e+00, 2.81360957e-09, 3.50615470e-09, ...,
4.67424543e-05, 2.53865019e-05, -9.59571480e-07]),
48000)
I am just wondering whether the bundled libsndfile was compiled with mp3 support?
I am just wondering whether the bundled libsndfile was compiled with mp3 support?
I actually don't know, and have no way of checking: It was provided by another user, as I don't have an M1 mac myself.
Thus, I'll have to ask for help once again: If you have an M1 mac, could you run the version of mac_build.sh from the 1.1.0 branch of libsndfile-binaries to produce an M1 build of libsndfile with MP3 support?
could you build a new version for linux platform? thank you very much.
The
none-any
wheel should work on Linux. But you'll have to provide your own libsndfile with MP3 support.
I have installed libsndfile 1.1.0 and the none-any
wheel in the centos server. I used the code to check:
sf.__libsndfile_version__
it is 1.1.0. used bellow:
audio = BytesIO(request.body)
audio.name = request.headers.get("filename")
y, r = sf.read(data)
read the audio. when It read a wav, It worked fine. But if read a mp3 audio. have follow error:
y, r = sf.read(data)
File "/opt/rh/rh-python36/root/usr/lib/python3.6/site-packages/soundfile.py", line 283, in read
subtype, endian, format, closefd) as f:
File "/opt/rh/rh-python36/root/usr/lib/python3.6/site-packages/soundfile.py", line 655, in __init__
self._file = self._open(file, mode_int, closefd)
File "/opt/rh/rh-python36/root/usr/lib/python3.6/site-packages/soundfile.py", line 1213, in _open
raise LibsndfileError(err, prefix="Error opening {0!r}: ".format(self.name))
soundfile.LibsndfileError: Error opening <_io.BytesIO object at 0x7fc592257a40>: File contains data in an unimplemented format.
Could you give some help, Thank you very much!
@BobCN2017 this is known. Mp3 support isn't compiled in right now.
@bastibe Maybe it's better to remove the beta before we confuse more people. I will try more things this weekend
Follow this.
Could anyone else try to compile a version of libsndfile with MP3 support on an M1 Mac? Without your help, I won't be able to ship a soundfile wheel for M1.
Thank you, @faroit, for providing updated binaries for M1!
There's a new beta release at https://github.com/bastibe/python-soundfile/releases/tag/0.11.0b5 for you to try!
This time, .mp3 files should open correctly by default (no more shenanigans necessary such as renaming to .mpeg, or supplying a format and subtype manually), and we should have MP3 support on M1!
I'd be grateful if you could, once again, test the wheels and see if they finally work on all platforms.
@bastibe success 💪
Python 3.9.13 | packaged by conda-forge | (main, May 27 2022, 17:01:00)
[Clang 13.0.1 ] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import soundfile as sf
>>> sf.info("testcase.mp3")
testcase.mp3
samplerate: 44100 Hz
channels: 2
duration: 25000 samples
format: MPEG-1/2 Audio [MP3]
subtype: MPEG Layer III [MPEG_LAYER_III]
>>> sf.read("testcase.mp3")
(array([[-0.02847968, -0.02057419],
[-0.02475205, -0.02332359],
[ 0.00175894, -0.01752098],
...,
[-0.04847291, -0.07572973],
[-0.07998063, -0.0545641 ],
[-0.06100846, -0.04042743]]), 44100)
>>> sf.
sf.LibsndfileError( sf.SEEK_SET sf.SoundFileRuntimeError( sf.blocks( sf.info(
sf.SEEK_CUR sf.SoundFile( sf.available_formats( sf.check_format( sf.read(
sf.SEEK_END sf.SoundFileError( sf.available_subtypes( sf.default_subtype( sf.write(
>>> sf.__version__
'0.11.0'
Thanks for your work and I'm looking forward to the new release!
Just a quick note: it looks like the 0.11.0b5 release sets the name of the package in setup.py
to soundfile
(whereas it was SoundFile
in 0.10.3.)
I'm not certain, but it looks as though changing the capitalization of the package name might cause some headaches for other tools, such as poetry
- would you please consider changing it back?
I'm not certain, but it looks as though changing the capitalization of the package name might cause some headaches for other tools, such as
poetry
- would you please consider changing it back?
Yes, we changed the name from the nonstandard "SoundFile" to a more common "python-soundfile", and the package name from "SoundFile" to "soundfile".
Is this actually causing problems, or is this just a worry at this point? As far as I know, pip does not care about capitalization.
Currently I can't help with testing M1. But Wheel for macOS x86_64 can't read MP3 files. Wheel for Windows x64 is OK.
Hi @bastibe. Any updates on this? We are looking forward to use this new version. Thanks.
It seems that the macOS x64 wheel somehow links to some system-installed /usr/local/opt/lame/lib/libmp3lame.0.dylib, instead of our own libmp3lame.la.
I've tried a fix in libsndfile-binaries#14, but apparently that didn't work as intended and still links against /usr/local/opt/lame. Does anyone understand what's going on here?
As far as I'm aware that's the last blocker for the release.
I can help test on either Darwin arch if that's useful
Thank you for the offer!
The build issue on macOS/Intel is still blocking, and I haven't had time to work on it. Currently, libsndfile-binaries@11 links against /usr/local/opt/lame instead of the self-compiled liblame from build_mac.sh.
If anyone wants to try to fix this issue in the build script, or contribute a self-contained libsndfile with full MP3-support for macOS/Intel, we could get this ready for release.
This issue may be related and one to watch: https://github.com/libsndfile/libsndfile/issues/852
Thanks to the outstanding work of @joetoddsonos in libsndfile-binaries@15, we should now have working macOS/Intel binaries with statically-linked MP3 support.
As far as I know, this was the last blocking problem for the 0.11 release 🤞.
Once again, I ask for your help, and try out the new wheels of python-soundfile-0.11.0b6. If these finally work on all supported platforms, we can publish the next release of soundfile with MP3 support!
Thank you all so much for your help and patience! This release wouldn't have been possible without your invaluable help!
I just uploaded the wheels to Pypi, finally! We should have working MP3 support in soundfile, now!
@bastibe success 💪
Python 3.9.13 | packaged by conda-forge | (main, May 27 2022, 17:01:00) [Clang 13.0.1 ] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import soundfile as sf >>> sf.info("testcase.mp3") testcase.mp3 samplerate: 44100 Hz channels: 2 duration: 25000 samples format: MPEG-1/2 Audio [MP3] subtype: MPEG Layer III [MPEG_LAYER_III] >>> sf.read("testcase.mp3") (array([[-0.02847968, -0.02057419], [-0.02475205, -0.02332359], [ 0.00175894, -0.01752098], ..., [-0.04847291, -0.07572973], [-0.07998063, -0.0545641 ], [-0.06100846, -0.04042743]]), 44100) >>> sf. sf.LibsndfileError( sf.SEEK_SET sf.SoundFileRuntimeError( sf.blocks( sf.info( sf.SEEK_CUR sf.SoundFile( sf.available_formats( sf.check_format( sf.read( sf.SEEK_END sf.SoundFileError( sf.available_subtypes( sf.default_subtype( sf.write( >>> sf.__version__ '0.11.0'
It's still failing for me :( Status: Fixed (working on python 3.85)
Python 3.10.4 [conda env.] MacOS M1 Using latest pull from master branch
Case 1
import io
import soundfile as sf
from urllib.request import urlopen
url = "https://dl.espressif.com/dl/audio/ff-16b-1c-16000hz.mp3"
data, samplerate = sf.read(io.BytesIO(urlopen(url).read()))
Output
Traceback (most recent call last):
File "/Users/apple/PycharmProjects/Outplay/Test/api.py", line 8, in <module>
data, samplerate = sf.read(io.BytesIO(urlopen(url).read()))
File "/Users/apple/PycharmProjects/Outplay/Test/python_soundfile/soundfile.py", line 282, in read
with SoundFile(file, 'r', samplerate, channels,
File "/Users/apple/PycharmProjects/Outplay/Test/python_soundfile/soundfile.py", line 655, in __init__
self._file = self._open(file, mode_int, closefd)
File "/Users/apple/PycharmProjects/Outplay/Test/python_soundfile/soundfile.py", line 1213, in _open
raise LibsndfileError(err, prefix="Error opening {0!r}: ".format(self.name))
python_soundfile.soundfile.LibsndfileError: Error opening <_io.BytesIO object at 0x102ff4680>: Format not recognised.
Case 2
import soundfile as sf
sf.read("/Users/apple/PycharmProjects/Outplay/Test/test.mp3")
Output
Traceback (most recent call last):
File "/Users/apple/PycharmProjects/Outplay/Test/api.py", line 13, in <module>
sf.read("/Users/apple/PycharmProjects/Outplay/Test/test.mp3")
File "/Users/apple/PycharmProjects/Outplay/Test/python_soundfile/soundfile.py", line 282, in read
with SoundFile(file, 'r', samplerate, channels,
File "/Users/apple/PycharmProjects/Outplay/Test/python_soundfile/soundfile.py", line 655, in __init__
self._file = self._open(file, mode_int, closefd)
File "/Users/apple/PycharmProjects/Outplay/Test/python_soundfile/soundfile.py", line 1213, in _open
raise LibsndfileError(err, prefix="Error opening {0!r}: ".format(self.name))
python_soundfile.soundfile.LibsndfileError: Error opening '/Users/apple/PycharmProjects/Outplay/Test/test.mp3': Format not recognised.
CC: @bastibe
How did you install soundfile? You will need both soundfile 0.11.0, and a version of libsndfile that supports MP3. The wheels from Pypi do contain such a libsndfile, but your system's libraries or conda's might not.
How did you install soundfile? You will need both soundfile 0.11.0, and a version of libsndfile that supports MP3. The wheels from Pypi do contain such a libsndfile, but your system's libraries or conda's might not.
soundfile version: 0.11.0 libsndfile version: 1.1.0_1
I tried 3 ways to install:-
It's working for python 3.85 :). I can settle with this.
Please manually download soundfile-0.11.0-py2.py3-none-macosx_10_9_arm64.macosx_11_0_arm64.whl from https://pypi.org/project/soundfile/#files. Then install the wheel using python -m pip install $filename.whl
(use python -m pip
instead of pip
to make sure you're installing into the correct interpreter). Within that python
, it should then work.
Otherwise, check if soundfile is picking up your system's libsndfile instead of the wheel-provided one. Library load order is a bit of a fickle beast sometimes.
Thanks @bastibe & co for this update! I was looking at opening a PR to update the conda-forge recipe, and for that, it would be most helpful if there was also a source dist (tar.gz) on pypi. Would it be possible to include that in a post-release?
Dear @bmcfee, thank you for alerting me to that. I simply forgot to upload the source dist. It's available now.
Excellent, thank you!
Please manually download soundfile-0.11.0-py2.py3-none-macosx_10_9_arm64.macosx_11_0_arm64.whl from https://pypi.org/project/soundfile/#files. Then install the wheel using
python -m pip install $filename.whl
(usepython -m pip
instead ofpip
to make sure you're installing into the correct interpreter). Within thatpython
, it should then work.Otherwise, check if soundfile is picking up your system's libsndfile instead of the wheel-provided one. Library load order is a bit of a fickle beast sometimes.
I've tried everything else and still can't load mp3 files. I've downloaded a version of libsndfile that supports mp3 but how do I check if soundfile is picking up the right libsndfile version and not a system one? Update: I've checked the libsndfile version using sf.__libsndfile_version__ - it's 1.1.0, which has mp3 support, still not loading
Was using soundfile as the audio backend for torchaudio, but even when I use soundfile.read it gives the same error
System error almost always means your file name is incorrect. It seems you are missing the backslash after C:
.
System error almost always means your file name is incorrect. It seems you are missing the backslash after
C:
.
Omg thanks, didn't see that. torchaudio.load is working now, but it's returning an empty tensor as waveform when it's called on mp3 files, although working fine with flac files. Any idea why that might be happening?
Try opening the file with straight soundfile instead of going through torch. Who knows what torch is doing in the background.
I'm facing the same issue: Here is my code:
# iterate over the XML files in the folder
for xml_file in os.listdir(folder_path):
if xml_file.endswith(".xml"):
# parse the XML file
tree = ET.parse(os.path.join(folder_path,xml_file))
root = tree.getroot()
# get the filename of the wav file
filename = './wav/'+root.find('./head/recording').attrib['filename']
audio_file = AudioSegment.from_file(f'{filename}.wav')
# iterate over the segments
for segment in root.findall('./body/segments/segment'):
start = float(segment.attrib['starttime']) * 1000 # convert to milliseconds
end = float(segment.attrib['endtime']) * 1000 # convert to milliseconds
snippet = audio_file[start:end]
snippet.export(f'./snippets/{segment.attrib["id"]}.mp3', format='mp3')
# extract the text from the element tags
text = ' '.join([element.text for element in segment.findall('./element')])
# create a unique filename
new_filename = f'./snippets/{segment.attrib["id"]}.mp3'
audio, sr = sf.read(new_filename)
This works perfectly on OSX but not on ubuntu 22.04, any idea why?
@asennoussi Ubuntu 22.04 still packages libsndfile version 1.0.31, which, AFAIK, does not have MP3 support yet.
Also note that, due to errors in the CMake build files, the pen-ultimate release of libsndfile (1.1.0) does not have MP3 support in most Linux distribution packages either, even though this version does support MP3 in theory, but due to said errors it will not be compiled in. The latest version (1.2.0) fixes that, but this still has to arrive in Ubuntu.
Makes sense?
I just used pydub
's AudioSegment.from_file
method and then
# get the raw audio data as a one-dimensional array
data = audio.get_array_of_samples()
# get the sample rate
sample_rate = audio.frame_rate
Instead. I hope this helps out someone else.
I have compiled a preliminary binary wheel for Ubuntu recently, that I'll try to release for testing soon. This should allow MP3 support on Ubuntu if installed with pip, and if no system-libsndfile is present.
Please check out https://github.com/bastibe/python-soundfile/pull/364 for a beta-release of a binary wheel for Linux.
@bastibe hello, I am so fraisated keep got this error:
soundfile.py", line 1226, in _init_virtual_io def vio_get_filelen(user_data): MemoryError: Cannot allocate write+execute memory for ffi.callback(). You might be running on a system that prevents this. For more information, see https://cffi.readthedocs.io/en/latest/using.html#callbacks
I installed from pypi, tried your M1 arm wheel, all fails.
Why? I also tried unsintall previous just keep error
I am still getting the same error even with version 0.12.1. Is there a solution to this issue?
This is a continuation of the discussion in #310, where I'm working on packaging a new version of soundfile.
It appears that the packaging problem is more complicated than anticipated. Our existing build system will probably need to be replaced, which will take some time.
If anyone would like to help me package soundfile, I'd be grateful!
The problem is, we need to package four wheels for
each containing their own libsndfile{.dll,.dylib}, and making sure that the right version gets installed on the right platform.
We have a build script in place for building packages for 1-3, but I don't yet know how to build wheels specifically for macOS Arm, and it seems that we should convert our build system to use PEP 517 (pyproject.toml/build et al).
I only had an hour or so today to work on this, so there wasn't much progress. I'll keep you updated.