What
src/web/NativeAudioBrowser.ts:160-162 declares three metadata callbacks as no-op defaults:
onChapterMetadata: (chapters: ChapterMetadata[]) => void = () => {}
onTrackMetadata: (metadata: TrackMetadata) => void = () => {}
onTimedMetadata: (metadata: TimedMetadata) => void = () => {}
Nothing in src/web/ ever calls them. src/features/metadata.ts documents all three unconditionally, so a consumer targeting web subscribes to an emitter that can never fire, with nothing to indicate that. The now-playing formatter's timedMetadata parameter is undefined on web for the same reason.
What's feasible
The web player is Shaka 4.x (src/web/TrackPlayer/Player.ts), attached to an <audio> element:
- Timed metadata (HLS ID3 / DASH EMSG) — Shaka dispatches a
metadata event. Map it to onTimedMetadata. (Present in the shipped bundle; the typed .d.ts has no typed event map for it, so confirm the payload shape against Shaka's docs when implementing.)
- Chapters —
player.getChapters(language) / getChaptersAsync(), plus Shaka's handling of chapters text tracks. Map to onChapterMetadata.
- Static track metadata — no clean Shaka equivalent. ID3 frames observed at load could approximate it, but the semantics wouldn't match the native side.
What's not feasible
ICY (Icecast/Shoutcast) metadata on progressive HTTP streams. Those play through the browser's own pipeline, which strips the interleaved metadata and exposes no API for it. Supporting it would mean:
- fetching the stream with
Icy-MetaData: 1;
- reading
icy-metaint, which requires the origin to send Access-Control-Expose-Headers: icy-metaint;
- de-interleaving metadata blocks from the audio byte stream;
- feeding the remaining audio through MSE —
ManagedMediaSource on iOS Safari.
That's a substantial subsystem whose success depends on per-origin CORS cooperation the library can't require. For consumers whose sources are predominantly ICY, this issue buys little — worth weighing before picking it up.
Proposal
- Wire
onTimedMetadata and onChapterMetadata from Shaka.
- Add
@platform documentation to all three, stating what does and doesn't arrive on web — specifically that ICY timed metadata never does.
- Leave
onTrackMetadata inert but documented.
Verification
Needs an HLS stream carrying ID3 timed metadata; there's no such fixture in the repo today.
Relates to #97 (task 4).
What
src/web/NativeAudioBrowser.ts:160-162declares three metadata callbacks as no-op defaults:Nothing in
src/web/ever calls them.src/features/metadata.tsdocuments all three unconditionally, so a consumer targeting web subscribes to an emitter that can never fire, with nothing to indicate that. The now-playing formatter'stimedMetadataparameter isundefinedon web for the same reason.What's feasible
The web player is Shaka 4.x (
src/web/TrackPlayer/Player.ts), attached to an<audio>element:metadataevent. Map it toonTimedMetadata. (Present in the shipped bundle; the typed.d.tshas no typed event map for it, so confirm the payload shape against Shaka's docs when implementing.)player.getChapters(language)/getChaptersAsync(), plus Shaka's handling ofchapterstext tracks. Map toonChapterMetadata.What's not feasible
ICY (Icecast/Shoutcast) metadata on progressive HTTP streams. Those play through the browser's own pipeline, which strips the interleaved metadata and exposes no API for it. Supporting it would mean:
Icy-MetaData: 1;icy-metaint, which requires the origin to sendAccess-Control-Expose-Headers: icy-metaint;ManagedMediaSourceon iOS Safari.That's a substantial subsystem whose success depends on per-origin CORS cooperation the library can't require. For consumers whose sources are predominantly ICY, this issue buys little — worth weighing before picking it up.
Proposal
onTimedMetadataandonChapterMetadatafrom Shaka.@platformdocumentation to all three, stating what does and doesn't arrive on web — specifically that ICY timed metadata never does.onTrackMetadatainert but documented.Verification
Needs an HLS stream carrying ID3 timed metadata; there's no such fixture in the repo today.
Relates to #97 (task 4).