Skip to main content

Viewing the channel list

Once you’ve selected a provider, the plugin fetches and parses the provider’s M3U playlist to display available channels:
  1. Select a provider from the provider list
  2. The plugin fetches the M3U playlist from the provider’s catLink URL
  3. The playlist is parsed and channels are displayed in a list view
  4. Each channel shows its title, logo, and group information
Channel lists are cached for 1 hour (3600 seconds) to reduce network requests and improve performance.

Channel information displayed

Each channel in the list displays the following information:
  • title: The channel name (e.g., “Sky Sports Cricket”)
  • tvg_logo: The channel logo/thumbnail (extracted from the tvg-logo attribute)
  • group_title: The channel category or group (extracted from the group-title attribute)
The channel listing is implemented in main.py:45:
for ch in channels:
  li = xbmcgui.ListItem(label=ch.title)
  li.setArt({'thumb': ch.tvg_logo, 'icon': ch.tvg_logo})
  li.setInfo('video', {'title': ch.title, 'genre': ch.group_title})
  li.setProperty('IsPlayable', 'true')

How playback works

When you select a channel to play, the plugin performs the following steps:

1. Channel resolution

The plugin re-fetches the channel list from cache or network and finds the matching channel by title:
channels = get_channels(provider_url=provider_url)
channel = next((ch for ch in channels if ch.title == channel_title), None)

2. Stream information extraction

The following information is extracted from the channel’s M3U entry:
  • url: The stream URL (HLS, DASH, or direct video URL)
  • user_agent: Custom User-Agent header if specified
  • cookie: Cookie header for authentication
  • referer: Referer header if required by the stream
  • license_string: DRM license key for encrypted content
  • headers: Additional HTTP headers

3. Inputstream Adaptive configuration

The plugin automatically detects the stream type and configures Kodi’s Inputstream Adaptive accordingly:
if '.mpd' in url or '.m3u8' in url or '.m3u' in url or license_string:
  li.setProperty('inputstream', 'inputstream.adaptive')
The plugin supports both HLS (.m3u8) and DASH (.mpd) adaptive streaming formats.

4. Header propagation

All necessary HTTP headers are encoded and passed to the stream:
stream_headers = []
if headers:
  for k, v in headers.items():
    stream_headers.append(f'{k}={v}')

if user_agent:
  stream_headers.append(f'User-Agent={user_agent}')
if referer:
  stream_headers.append(f'Referer={referer}')
if cookie:
  stream_headers.append(f'Cookie={cookie}')

encoded_headers = '&'.join(stream_headers)
li.setProperty('inputstream.adaptive.manifest_headers', encoded_headers)
li.setProperty('inputstream.adaptive.stream_headers', encoded_headers)

DRM and adaptive streaming support

The plugin supports multiple DRM and streaming technologies:

HLS (HTTP Live Streaming)

Streams with .m3u or .m3u8 extensions are treated as HLS streams and played using Inputstream Adaptive.

DASH (Dynamic Adaptive Streaming over HTTP)

Streams with .mpd extensions are treated as DASH streams and played using Inputstream Adaptive.

Clearkey DRM

The plugin supports Clearkey DRM for encrypted content. License keys can be provided in two formats:
  1. Hex pair format: key_id:key (e.g., a1b2c3d4:e5f6g7h8)
if hex_pair_re.match(license_string):
  drm_config = f"org.w3.clearkey|{license_string}"
  li.setProperty('inputstream.adaptive.drm_legacy', drm_config)
  1. License server URL: A full HTTP(S) URL to a Clearkey license server
elif license_string and license_string.startswith('http'):
  drm_config = f"org.w3.clearkey|{license_string}|{urlencode(license_headers)}"
  li.setProperty('inputstream.adaptive.drm_legacy', drm_config)

M3U parsing examples

The plugin parses M3U playlists to extract channel information. Here are some examples from m3u_parser.py:

Basic channel entry

#EXTINF:-1 tvg-logo="https://example.com/logo.png" group-title="Sports",Sky Sports Cricket
https://example.com/stream.m3u8
This extracts:

Channel with custom headers

#EXTINF:-1 tvg-logo="logo.png" group-title="Sports",Channel Name
#EXTVLCOPT:http-user-agent=Mozilla/5.0
#EXTVLCOPT:http-referrer=https://example.com
https://example.com/stream.m3u8
This extracts additional properties:

DRM-protected channel

#EXTINF:-1 tvg-logo="logo.png",Protected Channel
#KODIPROP:inputstream.adaptive.license_key=a1b2c3d4:e5f6g7h8
https://example.com/protected.mpd
This extracts:
  • License key: “a1b2c3d4:e5f6g7h8”
  • DRM flag: is_drm = True

Pipe-separated parameters

#EXTINF:-1,Channel Name
https://example.com/stream.m3u8|User-Agent=Mozilla&Referer=https://example.com
The parser handles inline parameters after the pipe (|) character:
if "|" in full_url_line:
  url_parts = full_url_line.split("|")
  current_item.url = url_parts[0]
  params = url_parts[1].split("&")
  for p in params:
    if "=" in p:
      k, v = p.split("=", 1)
      if k.lower() == "user-agent":
        current_item.user_agent = v
      elif k.lower() == "referer":
        current_item.referer = v

Troubleshooting playback issues

Stream won’t play

If a stream fails to play:
  1. Check your internet connection: Ensure you have a stable internet connection
  2. Try a different channel: Some channels may be temporarily offline
  3. Try a different provider: Switch to another provider and try their channels
  4. Check Inputstream Adaptive: Ensure the Inputstream Adaptive add-on is installed and enabled in Kodi

No channels found

If you see “No channels found” error:
if not channels:
  xbmcgui.Dialog().notification(
      'Error', 'No channels found', xbmcgui.NOTIFICATION_ERROR)
This may indicate:
  • The provider’s playlist is temporarily unavailable
  • Network connectivity issues
  • The provider’s URL has changed
If channels consistently fail to load, try clearing the channel cache by restarting Kodi or waiting for the 1-hour cache TTL to expire.

Invalid provider URL

If you see “Invalid provider URL” error:
if not provider_url or not provider_url.startswith('http'):
  xbmcgui.Dialog().notification(
      'Error', 'Invalid provider URL', xbmcgui.NOTIFICATION_ERROR)
This indicates the provider’s catLink is malformed or missing. Try selecting a different provider.

Failed to resolve channel URL

If playback fails with “Failed to resolve channel URL”:
xbmcgui.Dialog().notification(
    'Error', 'Failed to resolve channel URL', xbmcgui.NOTIFICATION_ERROR)
This may be caused by:
  • Network timeouts
  • Corrupted cache data
  • The channel being removed from the provider’s playlist
For detailed error information, enable debug logging in Kodi and check the log file after experiencing playback issues.

Build docs developers (and LLMs) love