Opened 3 years ago

Closed 3 years ago

#5240 closed defect (wontfix)

opus encoded audio loses information about the original sample rate (unlike opusenc)

Reported by: redneb Owned by:
Priority: normal Component: avcodec
Version: git-master Keywords: libopus
Cc: Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no

Description

Opus uses 48 kHz for all files. So when a file with a different sample rate is encoded, it has to be resampled to 48 kHz. But the resulting file contains information about the original sample rate. This way, when the file is decoded, it will be resampled to the original sample rate if necessary. Unfortunately, this doesn't happen with ffmpeg; an encode/decode cycle with ffmpeg will always result in a 48 kHz file.

Here's an example.
Let's create a 44.1 kHz file:

$ ffmpeg -filter_complex 'sine=d=30' sine.wav

Then let's encode it to opus using opusenc:

$ opusenc sine.wav sine1.opus

If we decode that file with opusdec we'll get a 44.1 kHz file:

$ opusdec sine1.opus sine1.wav
Decoding to 44100 Hz (1 channel)
[...]

This works because the opusenc stores the original sample rate in the resulting file:

$ opusinfo sine1.opus | grep 'Original sample rate'
	Original sample rate: 44100Hz

On the other hand, if we encode using ffmpeg this doesn't work:

$ ffmpeg -i sine.wav -c:a libopus sine2.opus
ffmpeg version N-46907-g80580bb Copyright (c) 2000-2015 the FFmpeg developers
[...]
$ opusinfo sine2.opus | grep 'Original sample rate'
	Original sample rate: 48000Hz

Change History (12)

comment:1 Changed 3 years ago by redneb

Interesting side note: opusdec only restores the original sample rate when outputing to a file and not for playback, e.g.:

$ opusdec sine1.opus 
Decoding to 48000 Hz (1 channel)
[...]
$ opusdec sine1.opus sine1.wav
Decoding to 44100 Hz (1 channel)
[...]

So in other words, opusdec makes a distinction between decoding for playback and decoding for other purposes.

comment:2 follow-up: Changed 3 years ago by heleppkes

Personally I believe that an extra resampling step after decoding is an extra processing step thats definitely not going to improve the quality. However adding an option to somehow do this might be acceptable, if its not default.

comment:3 in reply to: ↑ 2 Changed 3 years ago by redneb

@heleppkes: I agree, but I think decoding is separate issue. What I suggest is to change the encoding process so that it preserves the information about the original sample rate. Then we can discuss whether it is a good idea for the decoder to resample to the original rate or not (and I agree that it's probably not a good idea to do that, at least by default).

comment:4 Changed 3 years ago by cehoyos

  • Keywords libopus added
  • Resolution set to invalid
  • Status changed from new to closed

The problem is that libopus only accepts the following sample rates: 8kHz, 12kHz, 16kHz, 24kHz and 48kHz. These are all saved in the output file and are shown by opusinfo. Other sample rates (like 44100Hz) cannot be used to encode (libopus returns an error) and are (therefore) not saved in the file.
I don't see how this could be fixed within FFmpeg and will close this ticket.

comment:5 Changed 3 years ago by redneb

  • Resolution invalid deleted
  • Status changed from closed to reopened

Sorry, but I think you misunderstood my report. I fully understand how opus works vis-à-vis the limited number of sample rates that it supports. My report is not about that. It's merely about storing the original sample rate as metadata in the resulting file. It seems that it's possible, opusenc does it. Please reread my initial post.

comment:6 Changed 3 years ago by heleppkes

The FFmpeg infrastructure does not support doing this automatically. The encoder never knows the original sample rate, because the audio is resampled to a compatible rate long before it reaches the encoder.

The only way this could potentially be done right now is adding a metadata option to the encoder so you can manually specify the original sample rate, which is hardly convenient.

comment:7 Changed 3 years ago by cehoyos

I don't understand: opusenc does not have to resample the input audio before sending it to the library to encode it? My suspicion is that you found a bug in opusenc.

comment:8 Changed 3 years ago by TD-Linux

Opusenc does have to resample the audio - the original sample rate is stored as metadata in the Ogg container, not part of the Opus stream itself.

comment:9 Changed 3 years ago by cehoyos

But shouldn't it store the sample rate that was actually used for encoding?

comment:10 Changed 3 years ago by TD-Linux

Opus doesn't need a sample rate to decode - generally you just decode to 48khz. Comment #4 is not quite correct - those are the sample rates that libopus can operate on, but none of them are stored in the file. The original sample rate is purely cosmetic metadata, stored by opusenc. Opusenc/dec uses it to resample back to the original rate for convenience, so people aren't surprised when the output .wav is bigger than the input. In addition, some ABX tools only work with matched sample rates.

comment:11 Changed 3 years ago by redneb

Here's where the sample rate is written to the output opus stream in ffmpeg. Notice that the comment says "Original sample rate". Also, here's the equivalent line from opusenc. The input_sample_rate field gets its data here and the value written to it is the original sample rate.

comment:12 Changed 3 years ago by cehoyos

  • Resolution set to wontfix
  • Status changed from reopened to closed

This cannot be fixed, if you believe there is a bug (I am less convinced), consider it as won't-fix.

Note: See TracTickets for help on using tickets.