Skip to main content

Module opus

Module opus 

Source
Expand description

Opus codec (RFC 6716) — the wideband voice profile for telephony.

Wraps the reference C libopus via the opus crate. The profile is fixed for the WaveKat call path: 16 kHz mono (“wideband”), Application::Voip, in-band FEC on, DTX off. A 20 ms frame is therefore 320 PCM samples in, one variable-size packet out.

§Wire constants vs. audio reality

Three numbers here look contradictory and are not:

  • The SDP rtpmap is always opus/48000/2 and the RTP timestamp advances by OPUS_RTP_SAMPLES_PER_FRAME (960) per 20 ms packet. RFC 7587 §4.1 pins the RTP clock to 48 kHz and the channel count to 2 regardless of what the codec actually does — they are wire-format constants, not a description of the stream.
  • The PCM on either side of the codec is OPUS_PCM_SAMPLE_RATE (16 kHz) mono. That’s the audio reality: wideband speech.

Confusing the 48 kHz wire clock with the 16 kHz PCM rate is the classic Opus-over-RTP interop bug; the constants below exist so consumers never re-derive these numbers.

§Loss recovery is driven by the consumer

Unlike G.711, Opus can recover lost packets — but only if the receive path notices the loss (an RTP sequence-number gap) and asks:

  • OpusDecoder::decode_fec — recover the lost frame from the next packet’s embedded redundancy (in-band FEC / LBRR). The encoder only embeds that redundancy because we set a nonzero expected packet loss; set_inband_fec(true) alone puts nothing on the wire.
  • OpusDecoder::conceal — packet-loss concealment when nothing usable arrived at all: the decoder extrapolates a plausible frame instead of emitting a click or silence.

Opus lives in wavekat-core (not wavekat-sip) for the same reason G.711 does: codecs are a consumer-layer choice — wavekat-sip deliberately stays codec-agnostic.

Structs§

OpusDecoder
Stateful Opus decoder for one inbound stream.
OpusEncoder
Stateful Opus encoder with the fixed WaveKat voice profile.

Constants§

OPUS_DEFAULT_BITRATE
Target bitrate: the middle of the 24–32 kbps wideband-voice sweet spot from doc 45 — a large quality jump over G.711’s 64 kbps narrowband at under half the bandwidth.
OPUS_DEFAULT_PACKET_LOSS_PERC
Expected packet-loss percentage told to the encoder. Nonzero is what makes libopus actually spend bits on in-band FEC redundancy.
OPUS_DEFAULT_PAYLOAD_TYPE
De-facto default dynamic RTP payload type for Opus in SDP offers.
OPUS_FRAME_SAMPLES
PCM samples in one 20 ms frame at OPUS_PCM_SAMPLE_RATE: what OpusEncoder::encode consumes per call and what a normal 20 ms packet decodes to.
OPUS_MAX_FRAME_SAMPLES
PCM samples in the largest legal Opus frame (120 ms) at OPUS_PCM_SAMPLE_RATE. The far end chooses its own frame size, so decode buffers must size for this, not for 20 ms.
OPUS_PCM_SAMPLE_RATE
PCM sample rate on both sides of the codec: 16 kHz wideband, the locked profile from doc 45. This — not 48 kHz — is the rate the microphone is resampled to before encode and the rate decoded frames come out at.
OPUS_RTP_CLOCK_RATE
The RTP timestamp clock rate for Opus — always 48 kHz per RFC 7587 §4.1, independent of the actual encode rate. Wire constant.
OPUS_RTP_SAMPLES_PER_FRAME
RTP timestamp advance per 20 ms Opus packet: 20 ms at the mandatory 48 kHz wire clock. Feed this to the RTP sender’s samples_per_frame (the G.711 equivalent is 160).