Appearance
Playback & images
How to treat the playbackUrl and coverUrl fields you get back from episodes and streams.
Playback URLs
Both Episode.playbackUrl and Stream.playbackUrl are HLS (.m3u8) URLs you hand to any standard HLS player (AVPlayer, ExoPlayer, hls.js, video.js, ...).
graphql
query($id: ID!) {
property(id: $id) {
brands(limit: 1) {
items {
seasons(limit: 1) {
items {
episodes(limit: 1) {
items { title status playbackUrl }
}
}
}
}
}
}
}Treat the URL as opaque
Use the playbackUrl value exactly as returned. Never derive, parse, or hardcode playback hosts or path shapes - they are an implementation detail and can change without notice. Use the field, not a pattern you inferred from it.
playbackUrl is always present - status is the gate
playbackUrl is non-null even when the content is not playable yet:
- An episode returns a URL even mid-transcode. Only play it when
statusisREADY; whenPROCESSING, show a "still processing" state. - A stream returns a URL even when off-air. Only play it when
statusisLIVE; whenOFFLINE, show a channel-offline state.
Always branch on status before starting playback - do not assume a non-null URL means playable.
Cover images
coverUrl exists on Brand, Season, Episode, and Stream. When non-null it is a ready-to-use absolute image URL (the best available rendition). As with playback URLs, treat it as opaque - render it, do not parse it.
coverUrl is nullable: it returns null when no cover image exists for that item. Always have a placeholder fallback.
How each cover resolves:
- Brand - the brand's own cover image, or
nullif none is set. - Season - the season's cover, falling back to its season-group or brand cover.
- Episode - the episode's own cover, then its main video's thumbnail, then the season / season-group / brand cover. In practice most episodes resolve to the video thumbnail.
Streams
Stream.coverUrl is not resolved yet (a fast-follow) and currently returns null. A value appearing later where it was null is a non-breaking change.