Skip to main content
In multimedia, there’s often confusion between container formats and audio codecs. Symphonia draws a clear distinction between these two concepts, which is fundamental to its architecture.

Container Formats vs Audio Codecs

Container Format = The box that holds the data
Audio Codec = How the audio is compressed inside that box

Container Formats (Demuxers)

A container format is a file structure that encapsulates one or more codec bitstreams along with metadata. Think of it as an envelope that:
  • Wraps encoded data in packets with timestamps and track IDs
  • Supports multiple tracks (audio, video, subtitles)
  • Provides seeking through timestamp indexes
  • Stores metadata (artist, album, cover art)
  • Handles interleaving of multiple streams
In Symphonia, container formats are represented by the FormatReader trait.

Audio Codecs (Decoders)

An audio codec is an algorithm that compresses and decompresses audio data. A codec:
  • Compresses audio to reduce file size (lossy or lossless)
  • Decompresses back to PCM samples for playback
  • Has no knowledge of containers, timestamps, or seeking
  • Processes packets of compressed data
In Symphonia, audio codecs are represented by the Decoder trait.

Format and Codec Relationships

Many combinations are possible:
File ExtensionContainer FormatTypical Codec(s)
.mp3MP3 framesMP3 (MPEG Layer 3)
.flacFLACFLAC
.m4aISO/MP4AAC, ALAC
.oggOGGVorbis, Opus
.opusOGGOpus
.wavWAV (RIFF)PCM, ADPCM
.mkvMatroskaAny (Vorbis, Opus, AAC, etc.)
.webmWebM (Matroska)Vorbis, Opus

Format Detection

Symphonia uses the Probe to automatically detect container formats by scanning for byte-level markers.

How Probe Works

Format Descriptors

Each format provides a descriptor (symphonia-core/src/probe.rs:100) with:
pub struct Descriptor {
    pub short_name: &'static str,      // "mp3"
    pub long_name: &'static str,       // "MPEG Audio Layer 3"
    pub extensions: &'static [&'static str],  // ["mp3", "mp2", "mp1"]
    pub mime_types: &'static [&'static str],  // ["audio/mpeg"]
    pub markers: &'static [&'static [u8]],    // Byte signatures
    pub score: fn(&[u8]) -> u8,        // Confidence scorer
    pub inst: Instantiate,             // Instantiation function
}

Providing Hints

You can help the probe by providing hints from external information:
let mut hint = Hint::new();
hint.with_extension("mp3");

let probed = probe.format(&hint, mss, &fmt_opts, &meta_opts)?;
Hints are advisory only. The probe will verify format markers regardless of hints to prevent misdetection.

Codec Selection

Once a format is detected, you select a track and instantiate a decoder for its codec.

Track Selection

use symphonia::core::codecs::CODEC_TYPE_NULL;

// Get all tracks from the container
let tracks = format.tracks();

// Find the first audio track with a known codec
let track = tracks
    .iter()
    .find(|t| t.codec_params.codec != CODEC_TYPE_NULL)
    .expect("no supported audio tracks");

Codec Types

Symphonia defines codec types as constants (symphonia-core/src/codecs.rs:23):
pub const CODEC_TYPE_VORBIS: CodecType;
pub const CODEC_TYPE_MP3: CodecType;
pub const CODEC_TYPE_MP2: CodecType;
pub const CODEC_TYPE_MP1: CodecType;
pub const CODEC_TYPE_AAC: CodecType;
pub const CODEC_TYPE_OPUS: CodecType;

CodecRegistry

The CodecRegistry (symphonia-core/src/codecs.rs:524) maps codec types to decoder implementations:
use symphonia::default::get_codecs;

// Get the default registry with all enabled codecs
let codecs = get_codecs();

// Create a decoder for the track
let decoder = codecs.make(&track.codec_params, &dec_opts)?;

Supported Formats and Codecs

Symphonia supports a wide range of formats and codecs. Support is categorized by quality status.

Format Support (Demuxers)

FormatStatusGaplessFeature Flag
WaveExcellentYeswav
OGGGreatYesogg
MKV/WebMGoodNomkv
ADPCMGoodYesadpcm
PCMExcellentYespcm
VorbisExcellentYesvorbis
FLACExcellentYesflac

Codec Support (Decoders)

CodecStatusGaplessFeature FlagDefault
FLACExcellentYesflacYes
MP3ExcellentYesmp3, mpaNo
VorbisExcellentYesvorbisYes
PCMExcellentYespcmYes
MP2GreatNomp2, mpaNo
MP1GreatNomp1, mpaNo
AAC-LCGreatNoaacNo
ALACGreatYesalacNo
ADPCMGoodYesadpcmYes
Enable all formats with all-formats feature flag, all codecs with all-codecs, or everything with all.

Gapless Playback

Gapless playback removes encoder delay (padding at start) and encoder padding (at end) to enable seamless track transitions.

Enabling Gapless

use symphonia::core::formats::FormatOptions;

let fmt_opts = FormatOptions {
    enable_gapless: true,
    ..Default::default()
};

let probed = probe.format(&hint, mss, &fmt_opts, &meta_opts)?;

How It Works

When gapless is enabled:
  1. FormatReader provides trim information in packets:
    packet.trim_start  // Frames to trim from start
    packet.trim_end    // Frames to trim from end
    
  2. Decoder returns full audio buffer
  3. Application trims samples based on trim values:
    let decoded = decoder.decode(&packet)?;
    
    // Trim samples if needed
    if packet.trim_start > 0 || packet.trim_end > 0 {
        decoded.trim(packet.trim_start as usize, packet.trim_end as usize);
    }
    

Gapless Support by Format/Codec

Both the format and codec must support gapless:
CombinationGapless?Notes
MP3 in MP3YesExcellent gapless support
FLAC in FLACYesExcellent gapless support
Vorbis in OGGYesExcellent gapless support
AAC in MP4NoFormat doesn’t provide trim info yet
Opus in OGGNoNot yet implemented
PCM in WAVYesNo compression, inherently gapless

Custom Formats and Codecs

You can add support for custom formats or codecs.

Implementing a Custom Format

1

Implement FormatReader

use symphonia_core::formats::{FormatReader, FormatOptions};
use symphonia_core::io::MediaSourceStream;

pub struct MyFormatReader {
    // Your state
}

impl FormatReader for MyFormatReader {
    fn try_new(source: MediaSourceStream, options: &FormatOptions) -> Result<Self> {
        // Parse format header
        // Extract tracks
        // Return reader instance
    }
    
    fn next_packet(&mut self) -> Result<Packet> {
        // Read next packet from stream
    }
    
    // Implement other required methods...
}
2

Create a Descriptor

use symphonia_core::probe::{Descriptor, QueryDescriptor};

impl QueryDescriptor for MyFormatReader {
    fn query() -> &'static [Descriptor] {
        &[
            Descriptor {
                short_name: "myformat",
                long_name: "My Custom Format",
                extensions: &["myf"],
                mime_types: &["audio/myformat"],
                markers: &[b"MYFORMAT"],  // Format signature
                score: Self::score,
                inst: Instantiate::Format(|source, opt| {
                    Ok(Box::new(Self::try_new(source, opt)?))
                }),
            },
        ]
    }
    
    fn score(context: &[u8]) -> u8 {
        // Return confidence score 0-255
    }
}
3

Register with Probe

let mut probe = Probe::default();
probe.register_all::<MyFormatReader>();

let probed = probe.format(&hint, mss, &fmt_opts, &meta_opts)?;

Implementing a Custom Codec

1

Implement Decoder

use symphonia_core::codecs::{Decoder, CodecParameters};
use symphonia_core::audio::AudioBufferRef;

pub struct MyDecoder {
    // Your decoder state
}

impl Decoder for MyDecoder {
    fn try_new(params: &CodecParameters, options: &DecoderOptions) -> Result<Self> {
        // Initialize decoder with parameters
    }
    
    fn decode(&mut self, packet: &Packet) -> Result<AudioBufferRef<'_>> {
        // Decode packet data to PCM samples
    }
    
    fn reset(&mut self) {
        // Reset decoder state
    }
    
    // Implement other required methods...
}
2

Register with CodecRegistry

let mut registry = CodecRegistry::new();
registry.register_all::<MyDecoder>();

let decoder = registry.make(&track.codec_params, &dec_opts)?;

Next Steps

Architecture

Understand how formats and codecs fit into Symphonia’s architecture

Audio Primitives

Learn about AudioBuffer and sample format handling

Media Sources

Understand how Symphonia reads from different sources

Decoding Audio

Complete guide to decoding audio with Symphonia

Build docs developers (and LLMs) love