Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OPUS support problems #252

Open
Islanna opened this issue Jan 15, 2020 · 18 comments
Open

OPUS support problems #252

Islanna opened this issue Jan 15, 2020 · 18 comments

Comments

@Islanna
Copy link

Islanna commented Jan 15, 2020

Hi, I've been using pysoundfile for a long time for reading/writing Vorbis .ogg files, it's working great, but it definitely lacks Opus support.

As I've discovered, libsndfile has already added support for opus, check out approved PR here: libsndfile/libsndfile#406 . It's not in an official release yet, but you can build a working version from source easily enough following CMake guide in readme.

Building libsndfile

I've managed to successfully build the library running these commands(some of them are redundant):

apt-get update
apt-get install cmake autoconf autogen automake build-essential libasound2-dev \
libflac-dev libogg-dev libtool libvorbis-dev libopus-dev pkg-config -y

cd /usr/local/lib
git clone https://github.com/erikd/libsndfile.git
cd libsndfile
mkdir -p build && cd build

cmake .. -DBUILD_SHARED_LIBS=ON
make && make install
cmake --build .

Linking is added for ctypes to help find the new version of libsoundfile

All native libsndfile examples are working fine from the command line: it reads/writes/etc .opus files without any errors/exceptions.

Changing source code to support Opus

Next is the interesting part. I've examined pysoundfile source code and it looks like just adding of an OPUS key to subtypes dictionary is enough to support .opus format.

Write

And yes, it's working perfectly for write function. I've checked the generated audio by several different programs. It's just fine.

import soundfile as sf
sf._subtypes['OPUS']=0x0064

data, sr = sf.read('example.wav')

sf.write('example.opus', data, sr, format='OGG', subtype='OPUS')

Read

Problems are starting with read function.
Calling

sf.read('test.opus')

raises RuntimeError: Supported file format but file is malformed. It looks like a libsndfile bug, but as I mentioned above, clean libsndfile script reads .opus files without any exceptions.

I've solved this problem by installing pysoundfile from source with the following changes:

  1. Add
if format == 'opus':
    return 'OGG'

to get_format_from_file;

  1. Comment _error_check in seek and _cdata_io

Now, read is also working, but the commenting of _error_check doesn't seem the proper way to fix this bug.

Do you know how to fix this error? Or maybe what exactly can be the problem?

In any case, thank you for the great work!

@bastibe
Copy link
Owner

bastibe commented Jan 15, 2020

Thank you for your analysis!

I'd be grateful for a pull request, which we can merge once the new version of libsndfile has been released.

I believe the reading issue would be addressed once we added the appropriate code to _subtype (and possibly _format and _default_subtypes).

@Islanna
Copy link
Author

Islanna commented Jan 16, 2020

Hi, @bastibe, thanks for you answer!

I believe the reading issue would be addressed once we added the appropriate code to _subtype (and possibly _format and _default_subtypes).

If I got it right, you are planning to work on the code update. Where can I follow the progress just to stay in tune?

@bastibe
Copy link
Owner

bastibe commented Jan 16, 2020

Actually, I was asking you whether you would like to try to implement it!

@Islanna
Copy link
Author

Islanna commented Jan 16, 2020

Oh, ok, I got it!
Then I'll make a PR as soon as I check the remaining assumptions about the problem with the read function.

@Some1Somewhere
Copy link

Any progress on this? @bastibe @Islanna . Looking forward to be able to support OPUS files as well.
If it is already supported, is there anything else that I need to add?

@bastibe
Copy link
Owner

bastibe commented Jun 6, 2021

No progress that I know of. But I know libsndfile is working on MP3 support. Once that is released, I will prepare a new release of soundfile with OPUS support and MP3 support.

Until then, pull requests are welcome.

@GnomedDev
Copy link

Any ETA? It has been a month...

@bastibe
Copy link
Owner

bastibe commented Jul 5, 2021

That's entirely up to https://github.com/libsndfile/libsndfile.

@veelion
Copy link

veelion commented Dec 23, 2021

That's entirely up to https://github.com/libsndfile/libsndfile.

libsndfile has supported MP3 and OPUS, any plan to python-soundfile?
I tried to use soundfile with libsndfile(1.0.31) to read MP3 file successfully, but failed to open OPUS.

@bastibe
Copy link
Owner

bastibe commented Dec 23, 2021

According to the documentation, libsndfile will support MP3 in 1.1.0, but that has not yet been released. As soon as it is, I'll update soundfile to support it as well. Opus should be available in 1.0.29.

@zh794390558
Copy link

can we read opus now?

@bastibe
Copy link
Owner

bastibe commented Apr 12, 2022

Now that libsndfile has added support for MP3, I am working on a new release. You can check my progress at #325

@vadimkantorov
Copy link

Should we add to _formats 'OPUS': 0x200000 (*.opus file extension is typically reserved for Ogg container with Opus codec stream). There is already a _formats entry for 'OGG': 0x200000, so should opus format just reuse the same hex value. _subtypes should probably add OPUS: 0x0090and to _default_subtypes:'OPUS' : 'OPUS'`?

@bastibe
Copy link
Owner

bastibe commented Oct 21, 2022

In general, Opus support should already be working. Ogg containers with Opus contents should already work. But you're right, I think we don't have the file extension registered yet. I think _formats['OPUS'] = 0x200000 should be correct. But just try it out and see if it does the right thing. The default subtype is correct, too, I think.

@tcwalther
Copy link

I've also just run into an issue reading opus files. It seems that reading the last block fails, but the first blocks work fine.

Here's an audio file where reading works fine until you hit the last block:
Opus_long.opus.zip

Here's a short audio file that is short enough that also the first block fails.
Opus_file.opus.zip

@bastibe
Copy link
Owner

bastibe commented Nov 7, 2022

@tcwalther please forward this issue to https://github.com/libsndfile/libsndfile.

@TheoOliveira
Copy link

Hello guys, people said about reading opus but i am in doubt if it can write ogg based on opus codec, is it possible?

@sammlapp
Copy link
Contributor

This works fine for me:

import soundfile as sf
samples, sr = sf.read('./test_24khz.wav')
# note that Opus only supports sample rates of 8000, 12000, 16000, 24000, and 48000.
sf.write('example.opus', data, sr, format='OGG', subtype='OPUS')
samples, sr = sf.read('example.opus')

However, there doesn't appear to be a way to control the Opus bitrate used. This is similar to the issue of being able to choose mp3 bitrate (#390 ), and I have opened an issue asking about how to do it in libsndfile here:
libsndfile/libsndfile#1043

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants