Skip to content

Opus Support #137

Description

@hischampion

Opus files get handed to the Vorbis decoder and fail. audio/ogg doesn't say which codec is inside, and openFileStream sends all of it to OggVorbisStreamProcessor where VorbisFileBridge returns rc=-132 (OV_ENOTVORBIS).

I've got it working on a branch: https://github.com/hischampion/AudioStreaming/pull/1/changes. CI is green, but I don't have a Mac so it's never run on a device. It's also authored heavily with Claude Opus.

Would you want a PR?

Summary

  • OggVorbisStreamProcessorOggStreamProcessor, driving an injected decoder protocol. The renderer loop and packet accounting are untouched — only decoder references were renamed.
  • A sniffer that reads the first Ogg page for OpusHead vs \x01vorbis, since codec can't be known from file hint or Content-Type.
  • OpusFileBridge, mirroring VorbisFileBridge, on sbooth/opus-binary-xcframework — same author as the ogg and vorbis packages.

Three commits: the Opus support, a shared ring buffer, and a couple of CI jobs. The last two are separable.

Tests
20 cases, including:

  • sniffer: real Opus and Vorbis files
  • sniffer: multi-segment first page, where the lacing table shifts the payload
  • sniffer: Ogg FLAC, Speex and non-Ogg all report unsupported
  • sniffer: truncated input asks for more bytes instead of guessing
  • bridge: mono and stereo decode to the right rate, channels and length
  • bridge: stereo fixture is 440 Hz left / 660 Hz right, so a broken deinterleave reads as the wrong frequency rather than as silence
  • bridge: a fixture declaring input_sample_rate: 44100 still decodes at 48 kHz (the Opus pitch-shift trap)
  • bridge: recovers from a failed open when the header is larger than the 16 KB open threshold
  • bridge: Vorbis streams and junk are rejected

Manually ran the bridge against libopusfile and output is bit-identical to ffmpeg's. Valgrind is clean.

Goal
The motive here is to support a certain streaming app for the self-hosted music server Navidrome, which defaults to opus when transcoding.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions