Skip to content

Track

Track is the queue item shape shared across adapter and consumer boundaries.

Use this page as the canonical source for track payload semantics used by queue operations, snapshot projections, and event payloads.

TrackType is derived from TRACK_TYPES:

const TRACK_TYPES = ['file', 'progressive', 'hls', 'dash'] as const;
type TrackType = (typeof TRACK_TYPES)[number];

HeaderGroup defines setup-scoped shared HTTP headers that tracks can reference through headerGroupId.

interface HeaderGroup {
id: string;
headers: Record<string, string>;
}
FieldTypeRequiredNotes
idstringYesStable identifier referenced by Track.headerGroupId.
headersRecord<string, string>YesStatic headers reused by tracks that reference this group.
FieldTypeRequiredNotes
idstringYesStable track identifier for remove/skip operations.
urlstringYesPlayback URL consumed by native transport.
titlestringNoOptional display metadata.
artiststringNoOptional display metadata.
albumstringNoOptional display metadata.
artworkstringNoOptional artwork URL for lockscreen/notification surfaces.
durationnumberNoOptional duration in seconds when known.
typeTrackTypeNoDeclared media semantics used by native capability projectors.
headerGroupIdstringNoOptional reference to a setup-scoped HeaderGroup. Unknown IDs fail fast at add() time.
headersRecord<string, string>NoStatic per-track HTTP headers used by native playback transport.

When headerGroupId and headers are both present, resolution happens at queue admission time:

  • group only → effective headers = group headers
  • track only → effective headers = track headers
  • both → effective headers = { ...group, ...track } (track wins per key)
  • neither → no auth headers

Important boundary: merged effective headers are runtime-internal. Consumers should treat snapshots/events as public projections and avoid relying on internal merged-request state.

  • type expresses media-kind intent (file, progressive, hls, dash) used by runtime capability projection.
  • type does NOT guarantee that a specific operation (for example seek) is always available.
  • Runtime decisions should combine track declaration with runtime projections and snapshot signals (for example nullable duration semantics).

Based on the contract comments, v1 support scope is intentionally narrow:

  • Applied by Android/iOS runtime media requests for that specific track.
  • Isolated per track, not shared across queue transitions.

Shared groups do not replace per-track support. headers remains fully supported and is the per-track override path when both are present.

v1 non-goals explicitly documented in the contract:

  • DRM or license-request authentication flows.
  • Token refresh or dynamic auth callbacks.
  • Cookie/session renewal orchestration.

What this means in practice:

  • headers is useful for static per-track request headers.
  • headers is not an auth lifecycle engine and should not be treated as one.
import type { Track } from '@ddgutierrezc/legato-contract';
const track: Track = {
id: 'song-42',
url: 'https://cdn.example.com/song-42.mp3',
};
const track: Track = {
id: 'podcast-ep-12',
url: 'https://cdn.example.com/podcast/ep-12.mp3',
title: 'Episode 12',
artist: 'Legato Studio',
album: 'Season 2',
artwork: 'https://cdn.example.com/podcast/ep-12.jpg',
duration: 1620,
};
const track: Track = {
id: 'live-hour',
url: 'https://stream.example.com/live.m3u8',
type: 'hls',
};
import type { Track } from '@ddgutierrezc/legato-contract';
const track: Track = {
id: 'song-42',
url: 'https://cdn.example.com/song-42.mp3',
type: 'progressive',
headers: {
Authorization: 'Bearer demo-token',
'X-Client': 'mobile-app',
},
};
const track: Track = {
id: 'song-43',
url: 'https://cdn.example.com/song-43.mp3',
type: 'progressive',
headerGroupId: 'premium-us',
};
const track: Track = {
id: 'song-44',
url: 'https://cdn.example.com/song-44.mp3',
type: 'progressive',
headerGroupId: 'premium-us',
headers: {
Authorization: 'Bearer one-off-override',
},
};
  • Setting type: 'hls' or type: 'dash' and assuming seek is always available. Seek remains runtime-capability-dependent.
  • Omitting stable id values (for example randomizing per render). Queue operations (remove, skip) depend on stable identifiers and indexes.
  • Treating headers as shared global auth state across all queue items. Header scope is per track.
  • Assuming headerGroupId replaces per-track headers. It does not; both can coexist, with per-track keys taking precedence.
  • Expecting unknown headerGroupId values to be ignored. Admission fails fast at add() time.
  • Expecting headers to solve token refresh, cookie renewal, or DRM license workflows. Those are out of contract v1 scope.