Read duration, sample rate, channels, bit depth, and codec from the source audio archived at the end of each live event (events/<id>/source.<wav|ogg|opus>). Pure-Python: stdlib wave for uncompressed WAV, mutagen for everything else. No ffmpeg dependency.
Post-event, not during the live stream. When the speaker disconnects and the source recording is finalized, the service layer calls service.audio_metadata.extract_metadata() and stamps the result onto the event manifest (duration_ms field) so the dashboard's "Interpretation Minutes" tile and the per-event detail view both have accurate numbers without re-reading the audio bytes on every request.
- Raw bytes of the source recording (WAV 16-bit / 24 kHz mono written by
service.audio_archivefrom the speaker's PCM stream). - Original filename / suggested extension.
- Declared content type.
FileMetadataDetail (defined in services/api/app/types/files.py):
duration_ms: int | Nonesample_rate: int | Nonechannels: int | Nonebit_depth: int | Nonecodec: str | None
Any value is allowed to be null — partial metadata is better than failing the event finalization because of an unusual encoder.
- Mid-event abort with no recording yet — finalization skips the extraction step entirely; the manifest carries
duration_ms = null. - Unsupported container —
mutagenraises; the extractor swallows the exception, logs a warning, and returns nulls. - Corrupt header — same handling.