chore(audio): read attachment duration via native <audio preload=metadata>

Merged
GG
3mo ago
+12-144

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.