An audio file to decode (MP3, FLAC, OGG, WAV, etc.)
1
Add Symphonia to your project
Add Symphonia to your Cargo.toml. By default, only royalty-free formats are enabled (OGG, FLAC, Vorbis, PCM, Wave, WebM).For MP3 support, enable the mp3 feature:
Cargo.toml
[dependencies]symphonia = { version = "0.5", features = ["mp3"] }
Other format support
MP4/M4A container: Enable isomp4
AAC codec: Enable aac
ALAC codec: Enable alac
All formats: Enable all
Example with multiple formats:
symphonia = { version = "0.5", features = ["mp3", "isomp4", "aac"] }
2
Create a media source stream
Symphonia reads from a MediaSourceStream, which wraps any source implementing Read and Seek.
use symphonia::core::io::MediaSourceStream;use std::fs::File;fn main() { let args: Vec<String> = std::env::args().collect(); let path = args.get(1).expect("file path not provided"); // Open the audio file let file = Box::new(File::open(path).expect("failed to open file")); // Create the media source stream let mss = MediaSourceStream::new(file, Default::default());}
For unseekable sources (like stdin), use ReadOnlySource:
use symphonia::core::io::ReadOnlySource;let src = ReadOnlySource::new(std::io::stdin());
3
Probe the format and create a decoder
Use Symphonia’s probe to automatically detect the audio format and create a decoder for the track.
use symphonia::core::codecs::{DecoderOptions, CODEC_TYPE_NULL};use symphonia::core::formats::FormatOptions;use symphonia::core::meta::MetadataOptions;use symphonia::core::probe::Hint;// Create a hint (optional but improves detection)let mut hint = Hint::new();hint.with_extension("mp3");// Use default optionslet format_opts = FormatOptions::default();let metadata_opts = MetadataOptions::default();let decoder_opts = DecoderOptions::default();// Probe the media sourcelet probed = symphonia::default::get_probe() .format(&hint, mss, &format_opts, &metadata_opts) .expect("unsupported format");// Get the format readerlet mut format = probed.format;// Find the first audio tracklet track = format .tracks() .iter() .find(|t| t.codec_params.codec != CODEC_TYPE_NULL) .expect("no supported audio tracks");// Create a decoder for the tracklet mut decoder = symphonia::default::get_codecs() .make(&track.codec_params, &decoder_opts) .expect("unsupported codec");let track_id = track.id;
Enable gapless playback for a better listening experience:
let mut format_opts = FormatOptions::default();format_opts.enable_gapless = true;
4
Decode packets in a loop
The decode loop retrieves packets from the format reader and decodes them into audio samples.
use symphonia::core::errors::Error;loop { // Get the next packet let packet = match format.next_packet() { Ok(packet) => packet, Err(Error::ResetRequired) => { // Track list changed (e.g., chained OGG streams) // Recreate decoders and restart unimplemented!(); } Err(Error::IoError(err)) if err.kind() == std::io::ErrorKind::UnexpectedEof => { // End of stream reached break; } Err(err) => { eprintln!("Error reading packet: {}", err); break; } }; // Skip packets from other tracks if packet.track_id() != track_id { continue; } // Consume any new metadata while !format.metadata().is_latest() { format.metadata().pop(); // Process metadata if needed } // Decode the packet match decoder.decode(&packet) { Ok(decoded) => { // Successfully decoded! Process audio samples here println!("Decoded {} samples", decoded.capacity()); } Err(Error::IoError(_)) => { // Packet failed to decode, skip it continue; } Err(Error::DecodeError(_)) => { // Invalid data in packet, skip it continue; } Err(err) => { eprintln!("Unrecoverable decode error: {}", err); break; } }}
Always check for UnexpectedEof to detect end-of-stream. Without this, your program will panic when the file ends.
5
Convert to interleaved samples
Use SampleBuffer to convert decoded samples to a specific format (e.g., f32) in interleaved order.
use symphonia::core::audio::SampleBuffer;let mut sample_buf: Option<SampleBuffer<f32>> = None;let mut sample_count = 0;// Inside the decode loop, after successful decode:match decoder.decode(&packet) { Ok(decoded) => { // Create sample buffer on first packet if sample_buf.is_none() { let spec = *decoded.spec(); let duration = decoded.capacity() as u64; sample_buf = Some(SampleBuffer::<f32>::new(duration, spec)); } // Copy decoded samples to interleaved buffer if let Some(buf) = &mut sample_buf { buf.copy_interleaved_ref(decoded); // Access the samples let samples = buf.samples(); sample_count += samples.len(); println!("Total samples decoded: {}", sample_count); // Now you can play, process, or save these samples } } // ... error handling}
The audio format isn’t enabled. Check your Cargo.toml features and add the required format support.
no supported audio tracks
The file may be corrupted, or it might be a video file. If decoding video files, search specifically for audio tracks instead of using the default track.
unsupported codec
The codec isn’t enabled. Enable the appropriate codec feature in Cargo.toml (e.g., mp3, aac, alac).