resources/lib/bbc.py — BBC iPlayer resolver
Role
Resolves live TV channels (BBC One, Two, Three, Four, CBBC, CBeebies, News, Parliament, Alba, Scotland, S4C) and on-demand iPlayer episodes to DASH manifests. BBC streams have nodrm — these are clear DASH, so no license URL is involved.
The plugin entry point in default.py has a
_bbc_enabled() gate that reads the has_tv_license
addon setting before allowing BBC content. See
default.py:_resolve_channel line 119. This
is purely advisory (an honour-system popup) — BBC's MediaSelector only
geofences by UK-IP — but it's clearly the right UX choice if you're a UK
developer shipping a Kodi addon.
Constants
The same MediaSelector 6 JSON endpoint that bbc.co.uk's own player
uses. mediaset=pc is the desktop PC profile; mobile/tablet
would also work but with lower max resolution.
Which CDN supplier is preferred when multiple DASH streams are returned. Akamai > Limelight/Limelight Bidi > Bidi > CloudFront. The choice is mostly historical; on tor (OSMC, UK-IP) Akamai tends to give the lowest start-up latency.
Regex that matches the inline JSON the iPlayer episode page writes into
the page as a JS global. This is the same JSON the web player uses; we
parse it to get the version list (each iPlayer episode has multiple
"versions" for signed, audio-described, HD, etc.) — we pick the first one
and use its id as the vpid for MediaSelector.
Resolution helpers
For VOD episodes: takes the show's URL slug (e.g. m000abc1)
and fetches the iPlayer episode HTML page, parses the
__IPLAYER_REDUX_STATE__ JSON, picks the first version's id.
This is needed because MediaSelector expects the version id
(vpid), not the page slug. Throws
"BBC: could not load episode page" or
"BBC: no versions found" on parse failure.
For live channels the channel_id (e.g.
bbc_one_hd) is the vpid. For VOD episodes, the
vpid comes from _get_vpid. Hits MediaSelector,
detects the "result":"geolocation" response and raises
"BBC: Geoblocked" — there's no in-addon IP-tunnel fallback, so
non-UK access just fails.
Iterates data["media"], picks media entries where
kind starts with "video" (filters out audio-only). For each,
looks at its connection entries, restricts to
protocol == "https" + transferFormat == "dash",
computes a CDN priority via the CDN_PRIORITY table, sorts
ascending, returns the first (lowest-priority-rank) stream URL.
MediaSelector returns many connection entries per media — only those with the exact kind "video_X" (where X is e.g. "ek360", "iptv-all") are considered. Audio-only connections (kind "audio" or "audio_video") are silently skipped — Kodi picks up audio tracks from the DASH manifest itself.
Resolvers
BBC live channels don't go through _get_vpid (the channel
id is already the vpid). Calls _select_dash_stream and
hands the manifest to setup_dash_item()
with manifest_type="mpd" and no license URL (clear DASH).
Powering the linked-to-from-the-library VOD play URLs. Two HTTP hops:
_get_vpid(episode_id) → iPlayer page → MediaSelector. Heavy
debug logging at lines 65/67/69 (every step writes to kodi.log) — useful
when chasing intermittent failures. Hands off via
setup_dash_item(), no license.