Zackriya-Solutions/meetily · error
No audio samples decoded from file
Error message
No audio samples decoded from file
What it means
Raised by decode_audio_file_with_progress (decoder.rs:558) after the Symphonia packet loop finished with an empty all_samples vector. The container probed successfully and an audio track was found (earlier guards for probe/no-track/sample-rate already passed), but every packet either failed to decode (each decode error is only warned and skipped via `continue`), belonged to a different track_id, or the stream hit EOF before yielding any audio. In practice this means the file is structurally an audio file but contains zero decodable audio data.
Source
Thrown at frontend/src-tauri/src/audio/decoder.rs:558
last_progress = current_progress;
callback(current_progress, &format!("Decoding audio: {}%", current_progress));
}
}
}
Err(e) => {
warn!("Error decoding packet: {}", e);
continue;
}
}
}
// Ensure we report 100% completion
if let Some(callback) = &progress_callback {
callback(100, "Decoding complete");
}
if all_samples.is_empty() {
return Err(anyhow!("No audio samples decoded from file"));
}
let total_frames = all_samples.len() / channels as usize;
let duration_seconds = total_frames as f64 / sample_rate as f64;
info!(
"Decoded {} samples ({:.2}s) at {}Hz, {} channels",
all_samples.len(),
duration_seconds,
sample_rate,
channels
);
Ok(DecodedAudio {
samples: all_samples,
sample_rate,
channels,
duration_seconds,View on GitHub (pinned to 0281737d87)
Solutions
- Inspect the preceding warn! log lines ('Error reading packet'/'Error decoding packet') - they name the Symphonia error that caused every packet to be skipped; that is the root cause.
- Test the file outside the app with ffprobe (or ffmpeg -v error -i file -f null -) to confirm it has a decodable audio stream and non-zero duration.
- If ffprobe shows a codec Symphonia lacks (e.g. Opus in MP4, ATRAC, WMA Pro), re-encode once: ffmpeg -i in.ext -ac 1 -ar 16000 out.wav and import the WAV.
- If ffmpeg is not installed, install it and retry so the MKV/WebM/WMA pre-conversion path in decoder.rs runs instead of Symphonia failing packet-by-packet.
- For a file still being written (live recording/export), wait until the writer finalizes the container (moov atom for MP4) and retry.
- If the first track is not audio, extend track selection at decoder.rs:448 to prefer tracks whose codec_params indicate real audio (declared sample_rate) instead of the first non-NULL codec.
Example fix
// before: first non-null codec track wins, may pick a data/cover track
let track = format.tracks().iter().find(|t| t.codec_params.codec != CODEC_TYPE_NULL)
.ok_or_else(|| anyhow!("No audio track found in file"))?;
// after: prefer a track with declared sample_rate (real audio)
let track = format.tracks().iter()
.filter(|t| t.codec_params.codec != CODEC_TYPE_NULL)
.max_by_key(|t| t.codec_params.sample_rate.is_some() as u8)
.ok_or_else(|| anyhow!("No audio track found in file"))?; Defensive patterns
Strategy: validation
Validate before calling
// Rust caller: cheap pre-check that the file has a decodable audio track
fn has_decodable_audio(path: &Path) -> bool {
let Ok(f) = std::fs::File::open(path) else { return false };
let mss = symphonia::default::MediaSourceStream::new(Box::new(f), Default::default());
let Ok(probed) = symphonia::default::get_probe().format(&Hint::new(), mss, &Default::default(), &Default::default()) else { return false };
probed.format.tracks().iter().any(|t| t.codec_params.sample_rate.is_some())
}
// or shell out: ffmpeg -v error -i file -f null - ; exit 0 means decodable Try / catch
// Treat decode failure as: try ffmpeg fallback once, else surface a clear message
let decoded = match decode_audio_file(&path) {
Ok(d) => d,
Err(e) if e.to_string().contains("No audio samples decoded") => {
let wav = convert_to_wav_16k_via_ffmpeg(&path)?; // explicit fallback
decode_audio_file(&wav)?
}
Err(e) => return Err(e),
}; Prevention
- Validate recordings with ffprobe before offering them to the import flow.
- Install ffmpeg on PATH so MKV/WebM/WMA and codec-mismatch cases go through conversion instead of Symphonia failure.
- Reject zero-byte and header-only files at the extension/size gate before decoding.
- Log the per-packet Symphonia warnings - they reveal the true codec error behind the empty-sample result.
When it happens
Trigger: Calling decode_audio_file/decode_audio_file_with_progress on a file where: (a) the codec is recognized but every packet decode returns Err (corrupt payload, truncated download, DRM-protected M4A), (b) the selected first audio track is not the track that actually carries packets (packet.track_id() != track_id for all packets), (c) a 0-byte or header-only audio file passed extension validation, or (d) an ffmpeg pre-conversion (MKV/WebM/WMA path) produced a WAV from a video-only source. Note needs_ffmpeg_conversion only fires for a fixed extension list, so e.g. an .mp4 with an unsupported internal codec goes straight to Symphonia.
Common situations: Importing a meeting recording that was still being written when copied; importing DRM-protected iTunes/Audible audio; mislabeled extensions (e.g. an .mp3 that is actually a renamed PDF); WebM/MKV imports without ffmpeg on PATH so the conversion path never runs; files where the first track is a cover-art/video track and the audio track is second.
Related errors
- Whisper transcription failed on segment {}: {}
- Invalid input path (non-UTF8)
- Invalid temp path (non-UTF8)
- Failed to probe audio format: {}
- No audio track found in file
AI-assisted analysis of Zackriya-Solutions/meetily@0281737d87 (2026-08-16).
Data as JSON: /api/errors/4132ed58d896a14e.
Report an issue: GitHub.