Is there way to limit the sample rate used by the Opus codec? I’ve tried to configure codecs.conf, but Asterisk keeps upsampling everything to 48kHz. For example a call from a webrtc endpoint to an Asterisk extension playback with 16kHz audio file:
core show channel PJSIP/kamailio-webrtc-00000003
– General –
Name: PJSIP/kamailio-webrtc-00000003
Type: PJSIP
State: Up (6)
NativeFormats: (opus16)
WriteFormat: slin16
ReadFormat: opus16
WriteTranscode: Yes (slin@16000)->(slin@48000)->(opus@48000)
ReadTranscode: No
Bridge ID: (Not bridged)
Application: Playback
Data: /var/lib/asterisk/moh/a-prospector-theme
Similarly with a transcoded call where Opus is used on the outbound side Asterisk upsamples to 48kHz:
core show channel PJSIP/kamailio-webrtc-00000005
– General –
Name: PJSIP/kamailio-webrtc-00000005
NativeFormats: (opus16)
WriteFormat: slin48
ReadFormat: slin48
WriteTranscode: Yes (slin@48000)->(opus@48000)
ReadTranscode: Yes (opus@48000)->(slin@48000)
Bridge ID: f706fa22-a806-45ea-9c45-a97ce6c9f423
Application: AppDial
Data: (Outgoing Line)
No. So the input/output of opus is 48kHz, but internally inside the codec implementation and on the wire inside the opus packets it can be different bit rates and sample rates. Technically the codec allows that to change after negotiation even.
Do I understand this correctly: first Asterisk takes the slin 16kHz audio and upsamples it to 48kHz slin (the slin@16000 → slin@48000 step) and then passes the upsampled audio to the Opus codec, which then internally downsamples 48kHz audio back down to a lower sample rate? Or is the codec just always encoding with 48kHz samplerate, but with the upper spectrum empty?
It strikes me a bit inefficient to do the slin resampling steps, if the codec ends up using a different sample rate internally anyway, but maybe I’m missing something.
I understand that the RTP timestamps are always with 48 kHz resolution, but that shouldn’t prevent from using different sample rates for the actual codec.
Probably separate issue, but my config above results in the format line: a=fmtp:107 maxaveragebitrate=40000;useinbandfec=1
So I’m wondering why isn’t the max_playback_rate included? At least it would tell the other side to not waste bits encoding the upper frequencies that are going to be discarded anyway.
From an Asterisk codec_opus as we ship it binary that’s how it works. It uses libopus, I don’t know how libopus itself works internally. We just do 48kHz to/from it.
I don’t know why the max playback rate isn’t included. You could file an issue with instructions to reproduce if you’re using the binary module, but there’s no time frame on when it would get looked into.
Thanks for the support, the topic seems to have quite a lot of nuance to it.
I did some further digging and it looks like Chromium always encodes at 48kHz and just sets a filter based on the max playback rate parameter.
The Opus codec itself: Opus: Opus Decoder : “Internally Opus stores data at 48000 Hz, so that should be the default value for Fs. However, the decoder can efficiently decode to buffers at 8, 12, 16, and 24 kHz so if for some reason the caller cannot use data at the full sample rate, or knows the compressed data doesn’t use the full frequency range, it can request decoding at a reduced rate. Likewise, the decoder is capable of filling in either mono or interleaved stereo pcm buffers, at the caller’s request.”
So Asterisk’s extra resampling probably isn’t hurting quality-wise, but performance-wise it could probably do slightly better if it exposed the different sample rates directly from libopus so that the separate slin resampling step could be avoided.