chore(audio): read attachment duration via native <audio preload=metadata>
Proposal / suggestion
A fix for the audio-duration regression (CORE-2476) already landed on release-8.7.0 via #41599, using a useMediaDuration hook. This draft is an alternative approach for that same regression — opened for discussion, not to compete. Close it if #41599 is preferred.
What changes
Replaces the useMediaDuration hook + its module-level Map cache + imperative new Audio() with a hidden, declarative <audio preload="metadata"> element per attachment. The length is read from the native loadedmetadata event.
<audio
hidden
preload='metadata'
src={src}
onLoadedMetadata={(e) => setPreviewDuration(Number.isFinite(e.currentTarget.duration) ? e.currentTarget.duration : 0)}
>
<track kind='captions' />
</audio>
CORE-2476
durationTime={active ? duration : previewDuration} — shared player element drives the active track; the hidden element only supplies the length before playback.
Why
This is the exact mechanism the self-contained fuselage AudioPlayer used before the persistent-player refactor (#41120) replaced per-message elements with a single shared one and dropped metadata loading for inactive tracks. Restoring it declaratively means:
- No cache — React owns the element lifecycle; unmount aborts the fetch. Same fetch count as the hook (one metadata request per mounted attachment, browser HTTP-cached).
- No extra hook file / no
new Audio()— fewer moving parts. - Same scope as #41599 (duration display only; does not touch seek / CORE-2477).
Trade-offs vs #41599
| #41599 (hook + cache) | this (native tag) | |
|---|---|---|
| duration before play | ✅ | ✅ |
| cache dedupe across remounts | ✅ Map(256) | ❌ (relies on browser HTTP cache) |
Known gap in both: audio recorded in-app (MediaRecorder) reports duration === Infinity and shows no length. Neither approach forces the scan needed to resolve it — worth a follow-up.
Summary by CodeRabbit
- Bug Fixes
- Improved duration handling for audio attachments.
- Audio previews now show their duration before playback begins.
- Duration updates accurately while audio is playing, providing a more consistent playback experience.