Skip to content

Investigate enabling Opus DTX for voice sources #1445

@kixelated

Description

@kixelated

Background

We recently added a kind hint (voice | music | auto) to the publish-side audio Encoder (js/publish/src/audio/encoder.ts) that maps to Opus application + signal. We deliberately left usedtx off for now.

DTX (Discontinuous Transmission) lets Opus send sparse comfort-noise frames during silence, which can meaningfully reduce bandwidth for microphone sources. WebRTC ships DTX off by default and only enables it via SDP usedtx=1, so it's not a slam-dunk default — but for our kind: 'voice' path it's worth testing.

Concerns to validate

  1. Frame timing. With DTX, the encoder stops emitting frames during silence (or emits one comfort-noise frame every ~400ms). Our watch-side jitter buffer + PLC needs to tolerate that gap without false "stalled" signals or audible artifacts.
  2. Comfort noise repetition. When the receiver hasn't gotten a frame in a while, does the decoder hold the last comfort-noise envelope, or do we need to feed it repeated CN frames manually? Worth checking the WebCodecs AudioDecoder behavior for Opus DTX gaps.
  3. MoQ frame-per-group model. Each audio frame opens a new QUIC stream. DTX reduces frame rate during silence, so the per-stream overhead is less of a concern, but the relay's handling of long inter-frame gaps on a track should be confirmed.
  4. Catalog jitter field. js/hang/src/catalog/audio.ts advertises the max jitter before the next frame. With DTX this can be much larger during silence. Decide if we re-advertise during silence or just bump the static value.

Implementation sketch

  • Extend toEncoderConfig to set usedtx: true when kind === 'voice'.
  • Add a watch-side capture/playback test with a known silence interval and verify no glitches.
  • Measure bandwidth savings on a typical voice call.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    good first issueGood for newcomersjavascriptPull requests that update Javascript code

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions