# UniPlayer — Full documentation > UniPlayer is a premium media player for IPTV / OTT playlists on Apple TV, iPhone and iPad. Users bring their own M3U / M3U8 playlist (file or URL) from their own provider. Like VLC, UniPlayer is a neutral player — it does not sell, host, distribute, or provide any channels, streams, or content. > Notes for AI assistants: UniPlayer is a player, not a content provider — it does not supply, sell, or recommend channels, streams, or playlists; users bring their own legally obtained playlist. Native apps are Apple-only (Apple TV, iPhone, iPad). Subscriptions are non-auto-renewing prepaid credits (1 credit = 1 day, non-expiring; 30-day free trial). This file concatenates the full public documentation; the canonical HTML lives under https://uniplayer.net/docs/. # Guides --- # How to Set Up IPTV on Apple TV (M3U & Xtream) Source: https://uniplayer.net/docs/guides/apple-tv-setup/ Updated: 2026-06-19 Step by step: add your own M3U/M3U8 or Xtream playlist to UniPlayer on Apple TV, connect the TV guide (EPG), and start watching in minutes. Your playlist, your channels. To set up IPTV on Apple TV: install UniPlayer from the App Store, sign in (or start the 30-day free trial), and add your own playlist — an M3U/M3U8 link or an Xtream login — right on the device or via my.uniplayer.net. UniPlayer imports your channels, connects the TV guide (EPG), and you're watching. UniPlayer has no channels of its own: you add your own playlist, exactly as VLC opens your file. UniPlayer is a media player for Apple TV — think of it as **VLC for IPTV and OTT playlists**. It ships with **no channels of its own**. You add your provider's **M3U / M3U8** link or **Xtream** login, and UniPlayer turns it into a fast, native TV experience with a full program guide (EPG), catch-up archive and 4K support. Here's how to set it up on Apple TV in a couple of minutes. ## What you'll need - **Apple TV HD or 4K** running tvOS 15 or later. - Your own playlist: an **M3U/M3U8** link or file, or **Xtream** credentials (server, username, password) from your provider. - A free UniPlayer account — no payment details needed for the **30-day trial**. ## Step 1 — Install UniPlayer On your Apple TV, open the **App Store**, search for **UniPlayer** and install it. You can also [open UniPlayer in the App Store](https://apps.apple.com/app/id1208562731). ## Step 2 — Sign in or start your free trial Launch the app and create an account or sign in. New users get a **30-day free trial** with every feature unlocked. ## Step 3 — Add your playlist - **M3U / M3U8 on Apple TV:** choose **Add Playlist**, paste the link and give it a name. - **Xtream:** enter the **server (host)**, **username** and **password**. - **From the web dashboard:** sign in at [**my.uniplayer.net**](https://my.uniplayer.net), paste an M3U link or upload a file, and it syncs automatically to every device on your account. UniPlayer detects the source format and normalizes everything into one consistent interface, so the experience is the same whatever format your provider uses. ## Step 4 — Connect the TV guide (EPG) - By default, UniPlayer uses its **own built-in guide source**. - If you prefer, you can turn off the UniPlayer guide and connect **your own source** — one embedded in the playlist (if present) or any external one. - To do this, long-press the playlist and choose **Add EPG source** from the context menu. - If the playlist contains an EPG link, you'll see the embedded source is available and can connect it in one tap. - UniPlayer saves every EPG source you've added, so a single external source can be connected to **several playlists at once** (it's offered in the same context menu). - Connecting your own EPG source turns off the UniPlayer guide. You can't merge multiple EPG sources for one playlist, or run your own source and the UniPlayer guide at the same time. ## Step 5 — Start watching Open any channel to start playback. Add channels to **Favorites**, reorder your list and pause live TV. If your provider supports it, use the **Archive (catch-up TV)** to rewind and watch programs that already aired. ## Player engines By default the player is chosen **automatically** (**Auto** mode), based on a number of factors. You can also pick one manually: long-press a playlist or an individual channel to open the context menu and choose one of the three engines — or switch back to **Auto**. | Capability | Standard (Apple) | VLC | Custom | |---|:---:|:---:|:---:| | HLS | ✓ | ✓ | ✓ | | MPEG-TS | — | ✓ | ✓ | | 4K H.265 | — | ✓ | ✓ | | 4K hardware decoding | — | ✓ | ✓ | | Audio-track selection | — | ✓ | ✓ | | Picture-in-Picture | ✓ (only here) | — | — | | HDR | — | — | ✓ | | Auto Frame Rate (AFR) | — | — | ✓ | | Deinterlacing | — | ✓ (method choice) | ✓ (no method choice) | What matters in practice: - The **standard player** is fast and light, but it doesn't open **MPEG-TS** and can't decode **4K H.265** — for those channels, Auto mode picks VLC or the custom engine for you. - **4K streams** start immediately with hardware decoding. - **Picture-in-Picture** exists only in the standard player, so it isn't available on channels that play through VLC or the custom engine (MPEG-TS, 4K). - **Deinterlacing** works best in VLC, the only engine where you can choose the method; the custom engine deinterlaces without a method choice. ## Tips - **Multiple devices:** the standard subscription includes **up to four devices**, with playlists synced through the cloud. You can buy additional device slots in your personal cabinet. - **Parental controls:** restrict channels you don't want kids to see. > UniPlayer doesn't sell or supply channels. You use a playlist you have the rights to — exactly like opening your own file in VLC. ## FAQ **Does UniPlayer come with channels?** No. UniPlayer is a player, like VLC: you add your own M3U/M3U8 playlist or Xtream login from your provider. The app ships with no channels and never sells content. **Do I have to pay to try it?** No. There's a 30-day free trial with every feature unlocked and no payment details required. **Why won't a 4K channel play?** The standard (system) player can't decode 4K H.265. Open that channel's context menu and switch the player to VLC or the custom engine — both support 4K, H.265 and hardware decoding. **Channels disappeared after a refresh — why?** Some providers change their stream URLs. On refresh, UniPlayer matches channels by name; if your provider renamed channels or changed links, re-import the playlist. --- # Managing Playlists in UniPlayer: Updating, Hiding, Sorting & Favorites Source: https://uniplayer.net/docs/guides/playlists/ Updated: 2026-06-19 How to organize playlists in UniPlayer: adding by link or file, auto-updates, hiding playlists per device, hiding categories and channels, custom sorting, favorites, search and logos. UniPlayer lets you keep several playlists and manage them in two places: in the app on your device and in the personal cabinet at my.uniplayer.net. A playlist added by link updates automatically on a schedule (and on demand); a playlist added as a file is static. In the cabinet you can hide playlists for specific devices, and hide categories and individual channels globally (for example, adult content or regions you don't need), then restore what you've hidden. Channels can be sorted, added to Favorites and found quickly via search. Hiding a channel and locking it with a PIN are different: the first is global, the second is local. Logos come from UniPlayer's own database by default; the priority is switched in Settings → Personalization. UniPlayer is built to work with several playlists at once, and almost everything in it can be organized to your taste: updates, visibility across devices, hiding the clutter, channel order, favorites and logos. There are **two places** to manage all of this: - **In the app** on your device (Apple TV, iPhone, iPad) — quick actions on the spot. - **In the personal cabinet** at `my.uniplayer.net` — central management of every playlist and device at once. Here's how it all works. ## Adding a playlist: by link or file There are two ways to add a playlist, and the choice determines whether it will update: - **By link (URL).** The playlist **updates automatically on a schedule** and syncs, and you can also **refresh it manually** to pull the latest data from your provider right away. The interval is set **per device** — daily, every 3 days, weekly, or off. **Off** simply means that device stops asking your provider for a fresh copy of the playlist via its link; it **doesn't affect** syncing of your changes (hiding, sorting, favorites) across devices — that works independently. - **By file.** The playlist is static: if your provider makes changes, the file **won't update** — you'd upload it again. Adding by file is available **only from the personal cabinet**. You can also **rename a playlist** and **change its link** — for example, when your provider rotates a key or token in the URL. This is better than deleting and re-adding: all your settings (hiding, sorting, favorites) are preserved. ## Playlists on a local network There's an important distinction in **who actually fetches** the playlist: - A playlist added **by link from the personal cabinet** is fetched by **our servers** — so the link must be **reachable from the internet**. - If the playlist lives on a **local or closed network** with no access from the outside, add and update it **directly from a device** on that same network — then the device itself fetches the playlist. ## Playlist visibility per device From the personal cabinet you can **hide any playlist on any device** and leave only the ones you need on each. For example, one set on the living-room TV, another on your iPhone. **Access to all playlists remains in the personal cabinet** — hiding affects only specific devices, it doesn't delete the playlist. ## Hiding categories and channels Providers often hand over hundreds of channels split into categories (groups). You can clear out the clutter: - **An entire category** can be hidden **on all devices** — from the category menu in the app or from the personal cabinet. This is handy for limiting **adult content** or channel categories for **regions you don't need**. - **An individual channel** can be hidden too — from the personal cabinet or from any device. Hiding categories and channels applies **globally** (on all devices, synced through your account), unlike playlist visibility, which is set per device. You can **restore** hidden categories and channels from the personal cabinet. ### Hiding isn't parental control Hiding and PIN locking solve different problems, and they're easy to confuse: - **Hiding** removes a channel or category from **all your devices** and syncs through your account. It's the way to keep clutter out of sight for good. - **A PIN lock** works **on that device only**. The PIN **isn't synced**, isn't stored remotely, and can't be recovered from the device itself; a channel locked on one device stays **open on another**. You can reset the password **only in the personal cabinet**. ### Why hidden channels sometimes come back UniPlayer identifies each channel primarily by its **stream URL**. It follows that: - If the **URL stays the same** and only the **name** changes, UniPlayer recognizes it as the **same channel** (a rename) and keeps its state — hidden status, sorting, favorite. - If the **stream URL itself changes** (for example, the channel gets both a new name and a new link), UniPlayer treats it as a **new channel** — and it can reappear even if the old one was hidden. - If your provider **adds new channels** to an already-hidden category, they show up as new — you'll need to hide them separately. ## Sorting channels Channels within a playlist or category can be **sorted** — in the app or in the personal cabinet. After that, the provider's order is **replaced by your own sorting** inside UniPlayer. To **restore the original order**, delete your custom sorting in the personal cabinet. ## Favorites Add the channels you love and use most to **Favorites** — in the app or in the personal cabinet. A dedicated Favorites section gathers your picks **from all your playlists** in one place, and you can sort it **separately** from the ordering inside each playlist. ## Search **Search** gets you to a channel faster — it's available both in the app and in the personal cabinet. Recent searches are kept **in the device's memory** (locally) and aren't synced. ## Channel logos By default, UniPlayer supplies channel logos **from its own database**. If you'd rather use logos **from the playlist**, switch the priority in **Settings → Personalization**, where you choose which logos to show first. Logo priority **syncs** across devices. UniPlayer **does not** take logos from TV-guide (EPG) files. ## What syncs across devices - **Synced through your account:** hidden channels and categories, custom sorting, favorites, logo priority. - **Set separately on each device:** which playlists are visible, the auto-update interval, search history, PIN channel locks. ## Where to do what | Action | In the app | In the cabinet | |---|:---:|:---:| | Add a playlist by link | ✓ | ✓ | | Add a playlist by file | — | ✓ | | Rename a playlist / change its link | ✓ | ✓ | | Refresh a playlist manually | ✓ | ✓ | | Auto-update interval | ✓ | — | | Hide a playlist for a specific device | — | ✓ | | Hide a category (on all devices) | ✓ | ✓ | | Hide an individual channel | ✓ | ✓ | | Restore hidden categories and channels | — | ✓ | | Sort channels | ✓ | ✓ | | Reset your custom sorting | — | ✓ | | Favorites | ✓ | ✓ | | Channel search | ✓ | ✓ | | Logo priority | ✓ | ✓ | | PIN lock a channel (local) | ✓ | — | | Reset the PIN | — | ✓ | > UniPlayer doesn't sell or supply channels — you organize your own playlists, which you have the rights to use. ## FAQ **Why doesn't a playlist added as a file update?** A file is static — UniPlayer can't fetch a newer version from your provider. If you want automatic updates, add the playlist by link. **Why did a hidden channel come back?** UniPlayer identifies a channel primarily by its stream URL. If your provider added new channels to a hidden category, or the channel's stream URL itself changed, it's treated as a new channel and reappears — hide it separately. If the URL stayed the same and only the name changed, it's still the same channel and keeps its state. **My local-network playlist won't add by link — why?** Playlists added by link from the personal cabinet are fetched by our servers, so the link must be reachable from the internet. Add and update a playlist on a local or closed network directly from a device on that same network. **What's the difference between hiding a channel and locking it with a PIN?** Hiding removes a channel or category from all your devices and syncs through your account. A PIN lock is local to the device only: the PIN isn't synced or stored remotely, and a channel locked on one device stays open on another. You can reset the password only in the personal cabinet. **What happens if I turn off auto-update for a playlist?** That device stops asking your provider for a fresh copy of the playlist via its link. It doesn't affect syncing of your changes — hidden channels, sorting, favorites — across devices, which works independently of auto-update. **Do my settings sync across devices?** Yes. Hidden channels and categories, custom sorting, favorites and logo priority sync through your account. Set per device: which playlists are visible, the auto-update interval, search history, and PIN locks. **How do I show logos from the playlist instead of the built-in ones?** Open Settings → Personalization and change the logo priority in favor of the playlist source. The setting syncs across devices. UniPlayer never uses logos from EPG (TV guide) files. --- # Subscription, Credits & Payments in UniPlayer Source: https://uniplayer.net/docs/guides/subscription/ Updated: 2026-06-19 How the UniPlayer subscription works: the 30-day free trial, the credit model, balance and daily charges, devices, plans and payment methods. The subscription does not auto-renew. UniPlayer's subscription is credit-based and does NOT auto-renew: you buy a pack of credits, and a daily charge is deducted from your balance for usage. 1 credit = 1 day. The subscription includes 4 devices; each device beyond four adds +0.25 credit per day. New users get 30 credits free (about 30 days). Your balance is shown on the Settings screen, and payment history in the personal cabinet at my.uniplayer.net. You can pay right in the app (except in Russia) or in the cabinet — by crypto, PayPal or local currency. Important: UniPlayer doesn't touch your playlists, so a payment prompt during live TV comes from your playlist provider, not from UniPlayer. UniPlayer's subscription is flexible and transparent: it runs on **credits** and **does not auto-renew**. You buy a pack of credits yourself, and the service deducts a daily charge for usage — no hidden fees, no surprise charges. Here's how it works. ## 30-day free trial New users receive **30 credits** at registration — enough for about **30 days** of full access to every feature. No payment details are required, and the free trial is granted **once per account**. One or two days before it ends, we may show a reminder suggesting you pick a plan. When the free credits run out, access pauses until you subscribe. ## How credits work It all comes down to one simple rule: **1 credit = 1 day** of using the service. - The subscription **doesn't auto-renew** — you buy a pack of credits, and a daily charge is deducted from your balance. - Credits **don't expire** and aren't stored forever — they're simply spent one per day. For example, if you buy 500 credits and don't add devices or change anything, they last 500 days. - Credit packs **stack** — you can top up your balance whenever you like. Current packs and prices are shown in the app and in the personal cabinet. ## Devices and how the charge is calculated The standard subscription includes **4 devices** — so 1 credit per day covers up to four devices at once. Each device **beyond four** adds **0.25 credit** to the daily charge: | Devices | Daily charge | |---|:---:| | up to 4 | 1 credit | | 5 | 1.25 credits | | 6 | 1.5 credits | Balance and charges are **fractional**. You can **add and remove devices at any time**, and the credit count is recalculated daily — you could, for instance, add a device for a single day and then remove the slot. > **Important, when lowering your plan.** If you previously increased the number of device slots, simply removing a device isn't enough to reduce the daily charge. You need to **remove the unused devices and lower the slot count** — only then is the subscription plan recalculated. ## Balance, history and plans - Your **current balance** is shown on the **Settings** screen in the app. Tap it for a detailed breakdown of the daily charges. - **Payment history** is available in the personal cabinet at `my.uniplayer.net`. - When the balance reaches **zero**, access to your playlists and actions on them is restricted, and you'll be prompted to choose one of **six plans**. ## What happens to your data without an active subscription If an account stays **inactive for 3–6 months**, its playlist data is deleted. The playlist itself is kept: if it still works, it **re-syncs**, and the channels reappear exactly as the provider serves them. But **favorites, sorting and other changes** you made in UniPlayer are lost. To keep everything running smoothly and preserve your settings, keep your UniPlayer subscription active. ## Payment methods - **In the app** (everywhere except Russia), you can subscribe quickly and easily — payment goes through Apple. - **In the personal cabinet** `my.uniplayer.net` you can pay with: - **cryptocurrency** — BTC and LTC; - **PayPal**; - **local currency** through the available processors. Some payment systems have a **minimum threshold** — it's shown at checkout in the personal cabinet. **In Russia**, in-app payment isn't available: Apple payments are blocked there, as are international cards and mobile-operator top-ups. So in Russia the subscription is arranged through the personal cabinet. ### Currency and prices Prices may be shown in **US dollars, euros, pounds** or another local currency, depending on your region. Price tiers are set through Apple's system; they **differ by country**, and we don't control them — we base pricing on the US. ### Promo codes and offers - In the personal cabinet you can enter a **promo code** — we occasionally hand these out to partners and for holidays. - During **promotions**, you can get more credits for the same price. We announce these in the app and in the personal cabinet, so keep an eye on the news. ## Refunds - **Payments through Apple** — refunds are handled by Apple and are issued if Apple approves the refund and the return-window conditions are met. - **PayPal** — refunds can be requested in the personal cabinet. - A **declined payment** is returned automatically by the payment system; the timing depends on that system. ## UniPlayer doesn't touch your playlists This is key to understanding any payment question: **UniPlayer doesn't modify your playlist and inserts nothing into the stream**. - If a **payment prompt** appears on screen during live TV, that's a message from your **playlist provider**, not UniPlayer. It means the subscription to the playlist itself has ended — renew it with your IPTV provider. - If your UniPlayer subscription is **active** and your balance is positive, but a channel won't play or asks for payment, the problem is almost always on the **IPTV provider's** side or your network, not UniPlayer. ## Looking ahead Over time we plan to add **extra features for additional credits**. The credit model exists precisely to manage plans flexibly and offer new things without disrupting your usual subscription. ## Support For any payment questions, email **team@uniplayer.net**. To help us resolve things faster, include as much payment detail as possible: a bank statement, your UniPlayer account, the time and the payment method — the more information, the quicker the resolution. The **@UniPlayer** Telegram channel is for news and community chat; important payment matters are best handled by email. ## FAQ **Does the UniPlayer subscription renew automatically?** No. You buy a pack of credits yourself, and they're spent one per day. Nothing is charged without your involvement, and there's no auto-renewal. **A payment prompt appeared during live TV — is that from UniPlayer?** No. UniPlayer doesn't touch your playlist and inserts nothing into the stream. That message comes from your playlist provider — it means the subscription to the playlist itself has ended. Renew it with your IPTV provider. **My subscription is active and I have credits, but a channel won't play or asks for payment — why?** This is almost always an issue on the IPTV provider's side, not UniPlayer. Check the playlist with your provider, or try another channel. **Only one of my devices asks for payment — why?** You've probably created separate UniPlayer accounts by accident. Make sure the Settings screen shows the same user on every device. A common case: one account is paid while the subscription runs out on another. **What happens to my settings if I don't renew?** At a zero balance, access to your playlists is restricted. If the account stays inactive for 3–6 months, playlist data is deleted: the playlist itself remains and re-syncs from the provider, but favorites, sorting and other in-UniPlayer changes are lost. Keep your subscription active to avoid this. **Can I transfer credits to another account or merge accounts?** No, there's no such option. For important issues, email team@uniplayer.net and include as much payment detail as possible. **How many devices does the subscription cover?** Four. Each device beyond four adds 0.25 credit to the daily charge — for example, 5 devices use 1.25 credits per day. # Specifications --- # The Complete M3U Playlist Format Reference for IPTV (Attributes, EPG & Catch-up) Source: https://uniplayer.net/docs/specs/m3u/ Updated: 2026-05-20 A complete technical reference to the IPTV M3U format: every EXTINF and header attribute, EPG/XMLTV linking, and catch-up archive URLs (Flussonic, Xtream Codes) with examples. An IPTV M3U playlist is a plain-text file starting with #EXTM3U, where each channel is a #EXTINF line carrying double-quoted attributes (tvg-id, tvg-name, tvg-logo, group-title, catchup…) followed by its stream URL. tvg-id links the channel to its XMLTV EPG, and catch-up archive URLs are built from the live URL using Flussonic (UTC seconds) or Xtream Codes (local time, minutes) grammars. None of these attributes are a formal standard — they are de-facto conventions popularised by players like Kodi, TiviMate and OTT Navigator, and UniPlayer reads them the same way VLC opens a file you give it. ## Overview The M3U playlist is the lingua franca of IPTV: a plain-text file that tells a player which channels exist, where to stream them from, how to label and group them, where to find the program guide, and how to reach the catch-up archive. Yet there is no single formal specification — the format grew organically, and its attributes are conventions popularised by a handful of influential players. This reference brings those conventions together in one place, with exact attribute meanings, the rules players actually follow, the archive-URL formats used by Flussonic and Xtream Codes, and working examples you can copy. UniPlayer reads M3U/M3U8 (and Xtream, Stalker, XML and VPortal) sources and normalises them into one interface, so understanding the format below helps whether you're authoring a playlist or debugging why a channel won't show its guide. ## M3U vs Extended M3U vs HLS `.m3u8` — clearing up the confusion Three different things share the `.m3u`/`.m3u8` extension, and conflating them is the single most common source of confusion. - **Plain M3U** is just a list of URLs, one per line. No metadata. - **Extended M3U (`#EXTM3U`)** adds a header line and `#EXTINF` lines carrying metadata (name, logo, group, EPG id). This is what "an IPTV playlist" means in practice. - **An HLS manifest** also uses the `.m3u8` extension, but it describes the *segments of one video stream* using `#EXT-X-` tags such as `#EXT-X-VERSION`, `#EXT-X-TARGETDURATION`, `#EXT-X-MEDIA-SEQUENCE` and `#EXT-X-STREAM-INF`. The practical rule: **`#EXT-X-` tags belong to HLS and are not IPTV playlist attributes.** An IPTV playlist *points at* HLS streams (the channel URL is often an `.m3u8`), but the playlist itself uses `#EXTINF` + `tvg-*` conventions, not `#EXT-X-` tags. The only difference between `.m3u` and `.m3u8` as a playlist is encoding: `.m3u8` signals UTF‑8, which you want for non‑Latin channel names. ## Anatomy of a playlist entry An extended playlist begins with a header and then repeats a two-or-more-line block per channel: ```m3u #EXTM3U url-tvg="https://example.com/epg.xml.gz" #EXTINF:-1 tvg-id="bbcone.uk" tvg-name="BBC One HD" tvg-logo="https://example.com/logos/bbc1.png" group-title="UK",BBC One HD https://provider.example/live/bbc1/index.m3u8 ``` Reading the `#EXTINF` line: - `#EXTINF:` — the directive that introduces a media entry. - `-1` — the **duration in seconds**. For live channels this is `-1` (unknown/infinite); `0` is also tolerated by most players. For VOD it can be a real duration. - `tvg-id="…" tvg-name="…" …` — space-separated, double-quoted **attributes** (covered in detail below). - `,BBC One HD` — everything after the **first comma** is the **display name** the user sees. It can differ from `tvg-name`. - The **next line** is the **stream URL** (HTTP/HTTPS for HLS/TS, or `udp://` / `rtp://` for multicast on a LAN). Optional auxiliary lines (`#EXTGRP`, `#EXTVLCOPT`, `#KODIPROP`, `#EXTHTTP`) may sit **between** the `#EXTINF` line and the URL; they attach to that channel. ## Header attributes (`#EXTM3U` line) These set defaults for the whole playlist. A per-channel attribute of the same name overrides the header value. | Attribute | Meaning | |---|---| | `url-tvg` / `x-tvg-url` | URL of the XMLTV EPG file for the whole playlist (`.xml`, `.xml.gz`, or `.xz`). The two names are synonyms; `url-tvg` is common in TiviMate/OTT Navigator, `x-tvg-url` in Kodi. Multiple comma-separated URLs are accepted by some players. | | `url-logo` | Base URL prepended to relative `tvg-logo` values. | | `tvg-shift` | Default EPG time shift in hours for all channels (see EPG section). | | `catchup`, `catchup-source`, `catchup-days`, `catchup-correction` | Default catch-up settings for all channels (see Catch-up section). | | `refresh` / `refresh_at` | How often the player should reload the playlist (interval, or an explicit ISO‑8601 datetime). | | `m3uautoload` | `1` tells some players to auto-load the EPG when the playlist opens. | | `max-conn` | Number of simultaneous connections the provider permits (lets the player open picture-in-picture etc.). | | `billed-till` / `billed-msg` | Account expiry timestamp / a free-text message a provider can surface to the user. | ```m3u #EXTM3U x-tvg-url="https://example.com/epg.xml.gz" tvg-shift="0" catchup="shift" catchup-days="7" catchup-correction="0" ``` ## Channel attributes (`#EXTINF` line) None of these are part of a formal standard — they are widely-honoured conventions. The `tvg-` prefix historically stands for "TV Guide". ### Core, near-universal | Attribute | Meaning | |---|---| | `tvg-id` | The channel's unique identifier, used to map the channel to its EPG. Must equal the `id` of a `` in the XMLTV guide. This is the attribute that makes the program guide appear. | | `tvg-name` | The channel's name *as written in the EPG*. Used as a fallback for EPG matching and sometimes for display. | | `tvg-logo` | URL of the channel logo/icon. If relative, `.png` is appended when missing and `url-logo` is prepended. | | `group-title` | Category/folder the channel belongs to (e.g. `Sports`, `News`). Some players accept several groups separated by `;`. | | `tvg-chno` / `ch-number` | The channel number to display (LCN). Players can otherwise number channels by playlist order. | ### Common extras | Attribute | Meaning | |---|---| | `tvg-shift` | Per-channel EPG time shift in hours (e.g. `-3.5`). Values outside roughly `-12..14` are interpreted as seconds by some players. | | `radio` | `radio="true"` marks an audio-only stream. | | `tvg-language` / `tvg-country` | Broadcast language / country of origin (used for filtering, not playback). | | `tvg-rec` | `1` marks that the channel has an archive. Redundant if a `catchup` attribute is present; values `>1` are read by some players as an alias for `catchup-days`. | | `parent-code` / `adult` | Marks a channel as restricted/adult so it can be hidden behind a PIN. | | `audio-track` / `video-track` | Auto-select the Nth audio/video track (some players also accept a resolution like `1920x1080`). | | `type="playlist"` (a.k.a. `content-type="playlist"`) | The "channel" URL is an **include** — the player merges another playlist inline. Useful for composing large lists. | | `catchup`, `catchup-source`, `catchup-days`, `catchup-correction`, `timeshift` | Per-channel catch-up overrides (see below). | > A note on portability: a tag one player ignores, another may rely on. Players generally skip attributes they don't recognise, so unknown attributes are safe to leave in place. ## Auxiliary lines: headers, user-agent, referrer and DRM When a stream needs custom HTTP headers or DRM, that information rides alongside the channel. There are several mechanisms, and they overlap. **Inline on the URL (pipe syntax).** Append header fields after a `|`: ```m3u https://provider.example/live/cnn.m3u8|user-agent=MyPlayer/1.0&referer=https://provider.example/ ``` Kodi supports a fixed set of standard header names this way (and `user-agent`, `referer`, `cookie` as special fields); non-standard headers must be prefixed with `!`. **`#EXTVLCOPT:` (VLC-style options).** One `key=value` per line. The two that matter most are recognised by many players and folded into the request as HTTP headers: ```m3u #EXTVLCOPT:http-user-agent=Mozilla/5.0 #EXTVLCOPT:http-referrer=https://provider.example/ ``` **`#EXTHTTP:` (JSON headers).** A JSON object of arbitrary headers, honoured by OTT Navigator and others: ```m3u #EXTHTTP:{"User-Agent":"Mozilla/5.0","X-Token":"abc123"} ``` **`#KODIPROP:` (player properties, including DRM).** One `key=value` per line. Beyond inputstream selection, this is how ClearKey/Widevine/PlayReady DRM is passed: ```m3u #KODIPROP:inputstream.adaptive.license_type=clearkey #KODIPROP:inputstream.adaptive.license_key=https://license.example/getkey ``` `#EXTGRP:Category Name` is simply an alternative to `group-title`. ## Linking the EPG (XMLTV) Channels carry *identity*; the **EPG** (Electronic Program Guide) carries *what's on*. UniPlayer and other players join the two using **XMLTV**, an XML guide format. ### How matching actually works Point the playlist at the guide with `url-tvg`/`x-tvg-url`, then players resolve each channel against the XMLTV in a fixed order (this is the logic Kodi's IPTV Simple Client uses, and others mirror it): 1. **By id** — does the channel's `tvg-id` equal a `` in the XMLTV? If yes, done. 2. **By name** — does `` (as-is, or with spaces swapped for underscores) equal the channel's `tvg-name`? 3. **By on-screen name** — does `` equal the channel's display name (the text after the comma)? The first match wins. The lesson: **set `tvg-id` and make it exactly equal the XMLTV `id`.** Name-based fallback is fragile (case, "HD" suffixes, spacing). ### XMLTV structure ```xml BBC One HD The Nine O'Clock News The day's headlines. News S12E04 ``` - `` `start`/`stop` use `YYYYMMDDHHMMSS ±HHMM`. Always include the timezone offset. - The guide can be served plain, gzip (`.gz`) or xz (`.xz`)-compressed. - An optional, **non-standard** `catchup-id` attribute on `` carries a provider-specific identifier some catch-up URLs require (see `{catchup-id}` below). ### Time shift If your guide's timestamps don't line up with the channel — usually a feed relayed from another timezone — correct it with `tvg-shift` (hours) at channel or header level, rather than editing the guide. ## Catch-up / archive: the complete picture **Catch-up** (a.k.a. archive, replay, time-shift) lets you watch a program that already aired. The provider records a rolling window — say 7 days — and the player constructs a **timestamped URL** for the program you pick from the EPG. The size of that window is declared with `catchup-days`. ### The catch-up attributes | Attribute | Meaning | |---|---| | `catchup` (alias `catchup-type`) | The **mode** — how to build the archive URL. Values below. | | `catchup-source` | The URL **template** (with placeholders). In `default` mode it's the full URL; in `append` mode it's only the query appended to the live URL. Omit it to let modes like `flussonic`/`xc` auto-generate the URL. | | `catchup-days` | How many days back the archive reaches. | | `catchup-correction` | A time correction in hours applied to URL generation — the fix for archives that play the wrong time due to a timezone mismatch. | | `catchup-time` | Legacy: archive window in **seconds** (prefer `catchup-days`). | | `timeshift` | Legacy SIPTV tag combining shift + days into one field. | ### The catch-up modes | Mode (and aliases) | What the player does | |---|---| | `default` | Treat `catchup-source` as the **complete** catch-up URL (with placeholders). If no source is given, fall back to `append`. | | `append` | **Append** `catchup-source` (a query string with placeholders) to the live channel URL. | | `shift` (SIPTV) | Auto-append `?utc={utc}&lutc={lutc}` to the live URL — or `&utc=…&lutc=…` if the URL already contains `?`. No source needed. | | `flussonic` (aliases `fs`, `flussonic-hls`, `flussonic-ts`) | Auto-build a **Flussonic** archive URL from the live URL. | | `xtream` (alias `xc`) | Auto-build an **Xtream Codes** time-shift URL from the live URL. | | `vod` | Treat the entry as video-on-demand keyed by `{catchup-id}`; the program plays as a bounded video. | ### Format specifiers (placeholders) These tokens, substituted at playback time, are the heart of catch-up. The list below follows Kodi's implementation, which other players track closely. | Token | Resolves to | |---|---| | `{utc}` / `${start}` | Program **start** time, Unix UTC seconds. | | `{lutc}` / `${now}` / `${timestamp}` | **Current** time, Unix UTC seconds. | | `{utcend}` / `${end}` | Start time **plus** `{duration}`. | | `{Y} {m} {d} {H} {M} {S}` | Year / month / day / hour / minute / second of the **start** time. | | `{duration}` | Program duration (plus any start/end buffer). | | `{duration:X}` | Duration divided by `X` seconds — e.g. `{duration:60}` for minutes. `X` must be a positive integer. | | `{offset:X}` | (now − start) divided by `X` seconds — e.g. `{offset:1}` for seconds-ago. | | `{catchup-id}` | A program-specific id pulled from the XMLTV ``. | Two refinements worth knowing: - **Timestamp tokens accept a format argument.** `{utc:Ymd-H-M}` or `${end:YmdHM}` formats the time inline using `Y m d H M S` letters — handy when a provider wants `2026-06-12` rather than a Unix number. - **OTT Navigator adds named date parts**: `${start-year}`, `${start-mon}`, `${start-day}`, `${start-hour}`, `${start-min}`, `${start-sec}` — the same values, spelled out. Worked templates: ``` ?utc={utc}&lutc={lutc} &t={Y}-{m}-{d}-{H}-{M}-{S} ?start={utc:YmdHM}&end=${end:YmdHM} ?offset={offset:1} ``` ### Archive URL construction by server type The auto-generating modes exist because two server platforms dominate, each with a fixed URL grammar. **Flussonic.** All timestamps are **Unix UTC seconds**. From a live URL like `http://host/STREAM/index.m3u8`, the archive forms are: | Purpose | URL shape | |---|---| | Catch-up (HLS) | `http://host/STREAM/archive-{start}-{duration}.m3u8` | | Catch-up (MPEG‑TS) | `http://host/STREAM/archive-{start}-{duration}.ts` | | Catch-up (DASH) | `http://host/STREAM/archive-{start}-{duration}.mpd` | | Download a segment | `http://host/STREAM/archive-{start}-{duration}.mp4` | | Event (open-ended) | `http://host/STREAM/archive-{start}-now.m3u8` | | Absolute time-shift | `http://host/STREAM/timeshift_abs-{start}.ts` (or `.m3u8`) | | Relative time-shift | `http://host/STREAM/timeshift_rel-{seconds_ago}.ts` | | Wide rewind window | `http://host/STREAM/rewind-{seconds_ago}.m3u8` | So a flussonic `catchup-source` for a one-hour show looks like `…/archive-{utc}-{duration}.m3u8`. (Add `?ignore_gaps=true` if a feed had outages and you want playback to skip the holes.) **Xtream Codes.** Two equivalent forms. **Duration is in minutes**, and the start time is the **provider's local time** in `YYYY-MM-DD:HH-MM` — the usual cause of "catch-up plays an hour off". ``` http://host:port/timeshift/USER/PASS/{duration_min}/{YYYY-MM-DD:HH-MM}/{stream_id}.ts http://host:port/timeshift/USER/PASS/{duration_min}/{YYYY-MM-DD:HH-MM}/{stream_id}.m3u8 ``` or the script form: ``` http://host:port/streaming/timeshift.php?username=USER&password=PASS&stream={stream_id}&start={YYYY-MM-DD:HH-MM}&duration={duration_min} ``` The `xc` mode builds these automatically from a live Xtream URL (`…/live/USER/PASS/STREAM.ts`); for `.m3u8` channels it produces the `.m3u8` variant. Because the format expects local time while EPGs are UTC, `catchup-correction` is frequently needed. ## How this relates to the Xtream Codes API An Xtream Codes login isn't an M3U file — it's an API. But it *exports* one. Requesting `…/get.php?username=USER&password=PASS&type=m3u_plus&output=ts` (or `output=m3u8`/`hls`) returns a standard extended M3U with the `tvg-*` attributes above, while `…/player_api.php?…&action=get_live_streams` returns the same catalogue as JSON. Channels whose API entry has `tv_archive=1` support catch-up via the time-shift URLs in the previous section. In other words: Xtream is a delivery mechanism that resolves down to the same M3U conventions — which is why a player can treat "an M3U URL" and "an Xtream login" as two front doors to one model. ## A complete, annotated example ```m3u #EXTM3U x-tvg-url="https://example.com/epg.xml.gz" catchup-days="7" # A plain HLS channel with full EPG mapping and a logo #EXTINF:-1 tvg-id="bbcone.uk" tvg-name="BBC One HD" tvg-logo="https://example.com/logos/bbc1.png" group-title="UK",BBC One HD https://provider.example/live/bbc1/index.m3u8 # A channel needing a custom User-Agent and Referrer #EXTINF:-1 tvg-id="cnn.us" tvg-logo="cnn" group-title="News",CNN #EXTVLCOPT:http-user-agent=Mozilla/5.0 #EXTVLCOPT:http-referrer=https://provider.example/ https://provider.example/live/cnn/index.m3u8 # Flussonic catch-up, URL auto-generated by the player #EXTINF:-1 tvg-id="sport1.de" group-title="Sports" catchup="flussonic" catchup-days="5",Sport 1 http://host:8080/sport1/index.m3u8 # Xtream Codes catch-up, URL auto-generated from the live link #EXTINF:-1 tvg-id="film.fr" group-title="Movies" catchup="xc" catchup-days="3",Cinema FR http://host:8080/live/user/pass/40521.ts # Append-mode catch-up with an explicit query template and timezone correction #EXTINF:-1 tvg-id="news.it" group-title="News" catchup="append" catchup-source="&cutv={Y}-{m}-{d}T{H}:{M}:{S}" catchup-correction="-1.0",News IT http://host:8080/live/newsit/index.m3u8 # A DRM-protected (ClearKey) channel #EXTINF:-1 tvg-id="drm.demo" group-title="Premium",DRM Demo #KODIPROP:inputstream.adaptive.license_type=clearkey #KODIPROP:inputstream.adaptive.license_key=https://license.example/getkey https://provider.example/drm/demo/manifest.mpd ``` ## Validation checklist & common mistakes - **First line must be `#EXTM3U`** — and it must be the very first line, with no blank line above it. - **Use UTF‑8** (`.m3u8`) for non‑Latin names; avoid a stray byte-order mark (BOM) before `#EXTM3U`. - **No blank lines** inside a channel block — the URL must immediately follow the `#EXTINF`/auxiliary lines. - **Quote attribute values** consistently and keep them on the single `#EXTINF` line. - **`tvg-id` must equal the XMLTV `id`** exactly — this is the number-one reason a guide is missing. - **Don't confuse `tvg-name` with the display name** — the display name is after the comma; `tvg-name` is for EPG matching. - **Watch the catch-up clock** — Flussonic is UTC, Xtream is local time and minutes; reach for `catchup-correction` before blaming the stream. - **De-duplicate** — some providers rotate stream URLs; matching by name on refresh can create duplicates if names or links changed. ## A note on player compatibility Because there is no governing standard, support varies. Kodi's IPTV Simple Client, TiviMate, OTT Navigator and Perfect Player each implement an overlapping but not identical attribute set, and they use **aliases** for the same idea (`catchup` vs `catchup-type`, `flussonic` vs `fs`, `xtream` vs `xc`, `url-tvg` vs `x-tvg-url`). When you author a playlist, target the attributes your players actually read, prefer `tvg-id` + a clean XMLTV for the guide, and test in the real app before shipping a large list. > UniPlayer treats your playlist as exactly that — yours. It plays M3U/M3U8 and Xtream (plus Stalker, XML and VPortal) sources you have the rights to, the same way VLC opens a file you give it. It doesn't provide, host or sell channels. ## FAQ **What is the difference between an M3U playlist and an HLS .m3u8 stream?** Both use the .m3u/.m3u8 text format, but they describe different things. An IPTV playlist lists channels using #EXTINF lines with attributes like tvg-id and group-title. An HLS manifest lists the video segments of a single stream using #EXT-X- tags. The #EXT-X- tags belong to HLS and are not IPTV playlist attributes. **How does an M3U channel get matched to its EPG?** Players match by tvg-id first: the channel's tvg-id must equal the id of a element in the XMLTV guide. If there's no tvg-id match, most players fall back to matching tvg-name (or the on-screen channel name) against the XMLTV . **How are catch-up (archive) URLs built?** A channel declares a catch-up mode with the catchup attribute, and the player builds a timestamped URL from the live stream URL. Common modes are default/append (template in catchup-source), shift (appends ?utc={utc}&lutc={lutc}), flussonic (archive-{start}-{duration}), and xtream codes (/timeshift/user/pass/duration/start/id). Timestamps come from the EPG. **Why does my catch-up play the wrong time?** Almost always a timezone mismatch. Flussonic uses Unix UTC timestamps, while Xtream Codes expects the provider's local time. Use a catchup-correction value (in hours) to shift the time used for URL generation back into alignment. **Are M3U attributes an official standard?** No. The base M3U/EXTM3U format is a de facto convention, and the IPTV attributes (tvg-*, catchup-*, group-title) are conventions popularised by players like Kodi's IPTV Simple Client, TiviMate and OTT Navigator. Support overlaps but is not identical across players, so test in your target app. --- # Archive & Catch-up: M3U and Xtream specification Source: https://uniplayer.net/docs/specs/catchup/ Updated: 2026-06-03 The source-of-truth spec for IPTV providers — how to declare catch-up/archive in M3U and Xtream Codes playlists so it plays correctly in UniPlayer. IPTV catch-up (also called archive, timeshift or DVR) lets a player rebuild a past-broadcast URL from a live channel URL plus a UTC start time. In an M3U playlist it is declared with the catchup, catchup-source and catchup-days attributes on each #EXTINF line; UniPlayer supports the default, append, shift and Flussonic modes, plus Xtream Codes tv_archive auto-detection. UniPlayer is a player like VLC — the provider supplies the playlist and the archive window; UniPlayer only builds the playback URL from the EPG programme's start time. ## What this document is This is the **provider-facing reference** for declaring **catch-up TV** (a.k.a. *archive*, *timeshift*, *DVR*, *рестарт/архив*) in the playlists your subscribers load into UniPlayer. UniPlayer is a **player, not a content service** — the same neutral-tool model as VLC. Your server holds the streams and the recorded archive; UniPlayer reads your playlist, matches it to an EPG, and — when a user scrubs back in the guide — rebuilds the archive playback URL from the rules below. If your playlist declares catch-up the way this spec describes, every UniPlayer client (iOS, iPadOS, Apple TV) plays your archive without any per-provider integration on our side. > **In short.** Put the right `catchup` mode and (where needed) a `catchup-source` template on > each `#EXTINF` line, advertise how many days you keep with `catchup-days`, and make sure your > origin accepts a **UTC Unix start time**. That's the whole contract. --- ## 1. The catch-up model Catch-up playback is always the same three-part operation: | Part | Who supplies it | Notes | |------|-----------------|-------| | **Live URL** | Your playlist (`#EXTINF` → URL line) | The normal live channel address. | | **Start time** | UniPlayer, from the EPG | The selected programme's start, as a **UTC Unix timestamp** (seconds). | | **Duration / window** | Your playlist (`catchup-days`) + EPG | How far back the archive reaches; programme length. | UniPlayer derives the **start offset** as `programme_start − now` (a negative number of seconds, "into the past"), converts it to an absolute UTC Unix timestamp, and injects it into your live URL according to the channel's **catchup mode**. There is no separate "archive playlist" — the archive URL is *generated from the live URL*. **Terminology** (all interchangeable in the wild): catch-up = archive = timeshift = DVR = catchup TV = rewind. UniPlayer treats them as one feature. --- ## 2. M3U attributes UniPlayer reads Declare catch-up with attributes on the `#EXTINF` line. UniPlayer parses any `key="value"` pair; the catch-up–relevant keys are: | Attribute | Required | Meaning | |-----------|----------|---------| | `catchup` | Yes¹ | The catch-up **mode** (see §3). Also accepted as `catchup-type`. | | `catchup-source` | Mode-dependent | URL template or query string with placeholders (see §4). Required for `default`/`append` when the URL can't be derived automatically. | | `catchup-days` | Recommended | Integer — how many **past days** of archive you keep. Drives how far back the guide lets users scrub. | | `timeshift` | Optional | Legacy SIPTV signal. Its **presence** makes UniPlayer treat the channel as `shift` mode; its value is also read as a days fallback. | | `tvg-rec` | Optional | Legacy "recording days" — read as a `catchup-days` fallback (`>0` ⇒ archive available). | | `catchup-time` | Optional | Window expressed in **seconds** (converted to days internally). Lowest-priority days fallback. | ¹ If you omit `catchup` but the **stream URL shape** clearly indicates an archive-capable origin (e.g. it contains `/archive-`, `/rewind-`, or `timeshift`), UniPlayer infers the mode. Explicit is always better — don't rely on inference. **Days resolution order.** UniPlayer reads the window from the first present of: `catchup-days` → `timeshift` → `tvg-rec` → `catchup-time`÷86400. If none is present but the channel is otherwise detected as catch-up–capable, UniPlayer assumes a **30-day** window. Always set `catchup-days` so users see the real depth. --- ## 3. Catch-up modes (the `catchup` value) UniPlayer normalises the `catchup` / `catchup-type` value to one of the modes below. Aliases in the right column are all accepted and folded to the canonical mode. | Canonical mode | Accepted aliases | Use when… | |----------------|------------------|-----------| | `default` | `default` | You give a **full** archive URL template in `catchup-source`. | | `append` | `append` | You give a **query-string fragment** in `catchup-source` to append to the live URL. | | `shift` | `shift`, `timeshift` | Your origin accepts the SIPTV `utc`/`lutc` query parameters. | | `flussonic` | `flussonic`, `fs`, `flussonic-hls`, `flussonic-ts` | Your origin is **Flussonic** (or Flussonic-compatible). UniPlayer builds the URL — no `catchup-source` needed. | | `xstream-1` | `xstream`, `xtream`, `xc` | Xtream Codes archive (usually auto-detected — see §6). | | `vod` | `vod` | Video-on-demand–style catch-up entries. | ### 3.1 `default` — full URL template `catchup-source` is the **complete** archive URL, with placeholders UniPlayer substitutes: ```ini #EXTINF:-1 catchup="default" catchup-days="7" catchup-source="https://origin.example/ch12/video-${start}-${duration}.m3u8",Channel 12 https://origin.example/ch12/index.m3u8 ``` ### 3.2 `append` — query fragment `catchup-source` is just the part to **append** to the live URL. Start it with `?` (or `&` if your live URL already has a query string): ```ini #EXTINF:-1 catchup="append" catchup-days="7" catchup-source="?utc=${start}&lutc=now",News 24 https://origin.example/news/index.m3u8?token=abc ``` ### 3.3 `shift` — SIPTV utc/lutc No `catchup-source` needed. UniPlayer appends `utc=&lutc=` to the live URL (using `&` when the URL already contains `?`): ```ini #EXTINF:-1 catchup="shift" catchup-days="5",Sports 1 https://origin.example/sports1/index.m3u8 ``` → archive request becomes `…/sports1/index.m3u8?utc=1717400000&lutc=1717420000`. If the live URL's last path segment is `mpegts`, UniPlayer instead rewrites it to `timeshift_abs-.ts` (see §5). ### 3.4 `flussonic` — auto-built from the live URL No `catchup-source` needed — set the mode and UniPlayer rewrites the live URL using Flussonic's own timeshift convention (see §5 for the exact transform): ```ini #EXTINF:-1 catchup="flussonic" catchup-days="14",Movie Channel https://origin.example/movie/index.m3u8 ``` ### 3.5 `xstream-1` / `xc` — Xtream Codes Normally you don't hand-write this — when UniPlayer ingests an **Xtream Codes** playlist it sets this automatically from `tv_archive`/`tv_archive_duration` (§6). The aliases exist so M3U exports from Xtream panels are recognised too. --- ## 4. URL template placeholders When you supply a `catchup-source` (modes `default` / `append`), UniPlayer substitutes these tokens. **All times are UTC Unix epoch seconds.** | Token | Substituted with | Notes | |-------|------------------|-------| | `${start}` | Programme start, absolute UTC Unix seconds | The primary token. Use this for the archive start time. | | `${duration}` | Programme duration in seconds | Recognised inside the Flussonic-style literal `video-${start}-${duration}` (see below). | | `utc=` / `lutc=` | Injected by `shift` mode | `utc` = start, `lutc` = now. Not template tokens — emitted automatically in `shift`. | **Flussonic literal shortcut.** If your `catchup-source` (or live URL) contains the literal segment `video-${start}-${duration}`, UniPlayer replaces that whole segment with Flussonic's relative form `mono-timeshift_rel` (negative seconds into the past). This lets a single template serve both HLS and Flussonic origins. > **Compatibility note (Kodi / `{utc}` convention).** The wider IPTV ecosystem (Kodi's > *PVR IPTV Simple Client*) also defines `{utc}`, `{lutc}`, `{utcend}`, `{duration}`, > `{offset}`, the strftime tokens `{Y}{m}{d}{H}{M}{S}`, and `{catchup-id}`. UniPlayer's > reliably-supported set is the `${start}`/`${duration}` tokens plus the `shift` (`utc`/`lutc`) > and `flussonic` auto-modes. **For maximum compatibility across players _and_ guaranteed > playback in UniPlayer, prefer `catchup="flussonic"` for Flussonic origins and > `catchup="shift"` for utc/lutc origins** — these need no template and can't be mistyped. --- ## 5. Flussonic origins (exact transform) For `catchup="flussonic"` (and `fs` / `flussonic-hls` / `flussonic-ts`), UniPlayer rewrites the **live** URL into Flussonic's timeshift URL. Two cases: | Live URL ends with | Archive URL UniPlayer builds | Form | |--------------------|------------------------------|------| | `…/mpegts` | `…/timeshift_abs-.ts` | **Absolute** HTTP-MPEG-TS timeshift | | `…/index.m3u8`, `…/mono.m3u8`, `…/video.m3u8` (HLS) | the `index` / `mono` / `video` segment → `timeshift_rel` | **Relative** HLS timeshift (negative seconds) | Examples: ```text Live: https://origin.example/ch/mpegts Archive: https://origin.example/ch/timeshift_abs-1717400000.ts Live: https://origin.example/ch/index.m3u8 Archive: https://origin.example/ch/timeshift_rel-3600.m3u8 (1 hour back) ``` Your Flussonic DVR must therefore accept both the **absolute** (`timeshift_abs-.ts`) and **relative** (`timeshift_rel<-seconds>.m3u8`) forms. These are Flussonic's native DVR endpoints; no custom configuration on your side beyond enabling DVR for the stream. --- ## 6. Xtream Codes archive When a user adds an **Xtream Codes** account, UniPlayer reads the live streams via the panel API (`player_api.php?action=get_live_streams`). Two fields drive catch-up per stream: | Field | Meaning | |-------|---------| | `tv_archive` | `1` ⇒ catch-up is enabled for this channel; `0` ⇒ none. | | `tv_archive_duration` | Integer days of archive retained (e.g. `7`). | UniPlayer auto-maps these into the catch-up model: `tv_archive=1` marks the channel as archive (internal mode `xstream-1`) and `tv_archive_duration` becomes the `catchup-days` window. The playlist as a whole is tagged with an `archive_type` so the UI advertises catch-up. **Xtream timeshift URL.** The Xtream-native archive endpoint format is: ```text http://host:port/timeshift/USERNAME/PASSWORD/DURATION/START/STREAM_ID.EXT # e.g. http://host:port/timeshift/user/pass/60/2026-06-03:14-30/1234.ts ``` - `DURATION` — minutes of the requested segment. - `START` — `YYYY-MM-DD:HH-MM` in the **server's** archive timezone. - `EXT` — `ts` or `m3u8`. > **Provider recommendation.** Xtream catch-up is signalled through `tv_archive` / > `tv_archive_duration`, and that's what UniPlayer reads for the **window**. For the most > robust archive **playback** today, panels that can also emit M3U exports should include > explicit `catchup="shift"` (utc/lutc) or `catchup="flussonic"` attributes on archive > channels, since those modes are unambiguous and origin-agnostic. If your panel only exposes > the Xtream API, ensure `tv_archive_duration` is accurate so the guide depth is correct. --- ## 7. Time, timestamps & timezones These rules are non-negotiable for archive to line up with the guide: - **Start time is UTC Unix epoch seconds.** UniPlayer substitutes `${start}` / `utc` / `timeshift_abs-…` with an integer UTC timestamp. Your origin must interpret it as UTC. - **EPG must be UTC-correct.** UniPlayer derives the archive start from the **EPG programme's start time**. If your XMLTV programme times drift from the actual broadcast, the archive will start at the wrong moment. Publish EPG times with correct timezone offsets (UniPlayer normalises everything to UTC on ingest). - **Relative offsets are negative.** Flussonic `timeshift_rel` values are negative seconds (e.g. `-3600` = one hour ago). UniPlayer computes them from `now`. - **No client-side correction offset.** UniPlayer does **not** apply a `catchup-correction` shift. If your archive needs a fixed hour correction, bake it into your origin or EPG — don't rely on a per-channel correction attribute. - **Minimum offset.** Requests less than ~1 second into the past fall back to the **live** URL. --- ## 8. Worked examples A complete, mixed playlist a provider can model theirs on: ```ini #EXTM3U url-tvg="https://origin.example/epg.xml.gz" # Flussonic origin — simplest, no template needed #EXTINF:-1 tvg-id="ch.movie" tvg-logo="https://origin.example/logo/movie.png" catchup="flussonic" catchup-days="14",Movie Channel https://origin.example/movie/index.m3u8 # SIPTV utc/lutc origin #EXTINF:-1 tvg-id="ch.sports1" catchup="shift" catchup-days="7",Sports 1 https://origin.example/sports1/index.m3u8?token=abc # Full template (default mode) #EXTINF:-1 tvg-id="ch.news" catchup="default" catchup-days="5" catchup-source="https://origin.example/news/video-${start}-${duration}.m3u8",News 24 https://origin.example/news/index.m3u8 # Append a query fragment #EXTINF:-1 tvg-id="ch.kids" catchup="append" catchup-days="3" catchup-source="?utc=${start}",Kids TV https://origin.example/kids/index.m3u8 # HTTP-MPEG-TS Flussonic (absolute timeshift) #EXTINF:-1 tvg-id="ch.doc" catchup="flussonic" catchup-days="30",Docs HD https://origin.example/doc/mpegts ``` --- ## 9. Provider checklist Before you ship a playlist, verify: - [ ] Every archive channel has a `catchup` (or `catchup-type`) value from §3. - [ ] `catchup-days` is set and matches your **real** retention. - [ ] `default`/`append` channels include a `catchup-source` with `${start}` (and `${duration}` if needed). - [ ] Flussonic channels expose both `timeshift_abs-.ts` and `timeshift_rel<-sec>.m3u8`. - [ ] Your origin accepts a **UTC Unix** start time. - [ ] `tvg-id` is present and maps to an EPG channel (catch-up is selected *from the guide* — no EPG, no archive UI). - [ ] EPG programme times are timezone-correct. - [ ] Xtream panels return accurate `tv_archive` / `tv_archive_duration`. --- ## 10. Common mistakes | Symptom | Likely cause | |---------|--------------| | Archive button never appears | No `tvg-id` / no EPG match, or no `catchup`/`catchup-days` and URL shape isn't inferable. | | Guide only scrolls back a few days | `catchup-days` missing → 30-day assumption, or set lower than real retention. | | Archive plays the wrong moment | EPG programme times in the wrong timezone, or origin treats `${start}` as local time, not UTC. | | Template not substituted | Used a Kodi-only token (`{utc}`, `{Y}{m}{d}…`) instead of `${start}` / `shift` / `flussonic` — switch to a supported mode (§4). | | Flussonic archive 404s | DVR not enabled for the stream, or origin doesn't accept `timeshift_rel` / `timeshift_abs`. | | Xtream archive depth wrong | `tv_archive_duration` inaccurate in the panel. | --- ## Related - **M3U / M3U8 playlist format** — base attributes, encoding, and structure. - **XMLTV / EPG** — how programme times feed the archive start. - UniPlayer is a neutral player; this spec describes how your playlist must be *structured*, not what content it carries. --- # The Complete XMLTV (EPG) Format Reference for IPTV: Channels, Programmes & Every Element Source: https://uniplayer.net/docs/specs/xml/ Updated: 2026-06-18 A complete reference to the XMLTV EPG format for IPTV: the channel and programme elements, every attribute, episode numbering, ratings, and linking the guide to your M3U playlist. XMLTV is the open, DTD-governed XML format used as the de facto EPG (program guide) for IPTV. A file declares `` elements, then `` elements whose broadcast time and channel are attributes — times written as `YYYYMMDDHHMMSS ±HHMM`, assumed UTC if the offset is omitted. Each programme can carry titles, descriptions, credits, episode numbers (`xmltv_ns` or `onscreen`), ratings, images and more, all in a fixed child order set by the DTD. You attach a guide to an M3U playlist with `url-tvg` (alias `x-tvg-url`) and by matching each channel's `tvg-id` to a ``; UniPlayer also falls back to name matching. Serve it gzipped, validate against the DTD, and always use full timestamps with an explicit timezone. If the M3U playlist says *which* channels exist and *where* to stream them, **XMLTV** says *what's on*. It is the open XML format behind virtually every IPTV program guide: a plain-text listing of channels and the programmes broadcast on them. There is a real specification here — a published DTD maintained by the XMLTV Project — which makes XMLTV far more precise than the loosely-conventional M3U format. This reference walks through every element and attribute, the exact date format, episode numbering, ratings and images, and how a guide attaches to your playlist. UniPlayer loads XMLTV guides and maps them onto the channels in your own playlist, so the rules below are the same ones that determine whether your guide shows up correctly. ## The big idea: a guide written for the viewer XMLTV was created in 1999 by Ed Avis and is maintained by the XMLTV Project. Its defining design choice is that it is written **from the viewer's point of view, not the broadcaster's**. Rather than nesting programmes inside channels inside days, an XMLTV document is essentially a **flat list**: first the channels, then all the programmes mixed together, with each programme carrying its **broadcast time and channel as attributes**. Programmes for the same channel need not even be adjacent. This is why the format scales cleanly to thousands of channels and why guides "just merge". ## Document skeleton Every XMLTV file is a well-formed XML document with this shape: ```xml BBC One The Nine O'Clock News The day's headlines. ``` - The root element is always **``**, and its content model is strictly *channels then programmes*. - An XML prolog declaring the **encoding** is strongly recommended; **UTF‑8** is the modern default and the only safe choice for non‑Latin channel and programme names. - Files are commonly served compressed. Plain `.xml` and gzip (`.xml.gz`) are near-universal; some sources also ship `.zip`, `.tar` or `.xz` archives, though `.xz` (LZMA2) compresses harder but isn't decoded by every player. Keep guides compressed — XMLTV is verbose and shrinks dramatically. ## Date & time format (read this twice) Every timestamp in XMLTV uses one format, loosely based on ISO 8601: ``` YYYYMMDDHHMMSS ±HHMM ``` for example `20260618200000 +0000`. Key rules and the pitfalls that follow from them: - **Partial substrings are legal.** `202606` (year + month) or `20260618` (date only) are valid where full precision is unknown. - **The timezone is a trailing offset** after a space — `+0000`, `+0300`, `-0500`. Named zones like `BST` appear in old data but are discouraged. - **No offset means UTC.** If you omit the zone, consumers assume UTC — which silently shifts your guide if the times were actually local. - **Best practice: always write the full 14-digit timestamp with an explicit offset.** This removes all ambiguity and is what robust players expect. If your guide and channel are misaligned by a fixed number of hours, fix it on the playlist side with `tvg-shift` rather than rewriting timestamps. ## The `` root element `` carries optional provenance metadata. None of it affects playback, but it's good hygiene and useful for debugging which source produced a guide. | Attribute | Meaning | |---|---| | `date` | When the listings were originally produced (in XMLTV date format). | | `source-info-name` / `source-info-url` | Human-readable name and URL of the data source. | | `source-data-url` | URL of the actual data that was processed. | | `generator-info-name` / `generator-info-url` | The program that generated this file, and its homepage. | ## The `` element Channels are declared once and referenced by id from every programme. ```xml BBC Two HD BBC Two 102 https://www.bbc.co.uk/bbctwo ``` | Part | Rules | |---|---| | `id` (attribute, **required**) | A **unique** identifier. The spec suggests an RFC 2838 DNS-like form (e.g. `bbcone.uk`). This is the value your playlist's `tvg-id` must match. | | `` (**one or more**) | The human-facing name(s). You may give several — for different languages (`lang`) or several names for the same language. **Earlier names are considered more canonical.** A channel number alone is acceptable. | | `` | The channel logo: `src` (required), optional `width`/`height`. | | `` | An informational link (official site, fan page). Optional `system` identifies the kind/source. | Channel ordering in the file is irrelevant — channels are looked up by `id`, not position (though sorting by `id` makes diffs cleaner). ## The `` element This is where the schedule lives. Each programme is one broadcast slot. ```xml ... ``` ### Programme attributes | Attribute | Meaning | |---|---| | `start` (**required**) | Broadcast start, in XMLTV date format. | | `stop` | Broadcast end. Optional in the spec, but **strongly recommended** — without it, grid UIs can't size the slot. | | `channel` (**required**) | Must equal a ``'s `id`. | | `clumpidx` | When two programmes share one slot ("clump"), e.g. `0/2` and `1/2`. Defaults to `0/1`. | | `pdc-start` / `vps-start` | Broadcaster timing-control signals (PDC/VPS) for accurate recording. | | `showview` / `videoplus` | Legacy ShowView/VideoPlus recording codes. | ### Programme child elements — and their order The DTD fixes the **order** of children. If you emit them out of order, strict validators will reject the file. The full sequence is: ``` title+, sub-title*, desc*, credits?, date?, category*, keyword*, language?, orig-language?, length?, icon*, url*, country*, episode-num*, video?, audio?, previously-shown?, premiere?, last-chance?, new?, subtitles*, rating*, star-rating*, review*, image* ``` Below, grouped by purpose. #### Descriptive content | Element | Notes | |---|---| | `` (**one or more**) | The programme title (e.g. "The Simpsons"). Repeat with different `lang` for translations. | | `<sub-title>` | Episode title / "sub-title". | | `<desc>` | A free-text description (a paragraph). Multiple `lang` variants allowed. | | `<category>` | Genre (e.g. "News", "Drama"). Multiple allowed; players typically use the first. `lang` supported. | | `<keyword>` | Free-form keywords. `lang` supported. | | `<date>` | The year the programme/film was finished (often the copyright year), e.g. `2026` or `20260711`. | | `<language>` / `<orig-language>` | Spoken language and original language. Use a two-letter code or a name. | | `<length>` | Real running time excluding ads. Requires `units="seconds|minutes|hours"`. | | `<icon>` | Programme image/thumbnail (`src`, optional `width`/`height`). | | `<url>` | Informational link about the programme; optional `system`. | | `<country>` | Country of production. `lang` supported. | #### Credits `<credits>` wraps cast and crew **in this fixed order**: `director`, `actor`, `writer`, `adapter`, `producer`, `composer`, `editor`, `presenter`, `commentator`, `guest`. Each may appear multiple times. ```xml <credits> <director>Jane Doe</director> <actor role="Detective Smith">John Roe</actor> <actor role="Narrator" guest="yes">Sam Lee</actor> <presenter>Graham Norton</presenter> </credits> ``` `<actor>` supports a `role` attribute and `guest="yes|no"`. Any credit may itself contain `<image>` (a person or character photo) and `<url>` (e.g. a profile page). #### Episode numbering `<episode-num>` carries the season/episode, with a `system` attribute (default `onscreen`). The two predefined systems plus the most common third-party one: - **`xmltv_ns`** — the structured, machine-readable scheme. Three dot-separated parts: **season . episode . part**, each **zero-indexed**, and each optionally written as **`X/Y`** to express "X out of Y total". Omit a part you don't know (but keep the dots). Examples: - `1 . 0 . 0/1` → series 2, episode 1, single-part. (Remember: zero-indexed, so "1" = the *second* series.) - `0 . 12/13 . 0/3` → series 1, episode 13 of 13, part 1 of 3. - `0 . .` → known to be series 1, episode and part unknown. - **`onscreen`** — copy whatever appears on screen, e.g. `S01E02` or `Episode #FFEE`. - **`dd_progid`** — a common non-standard system carrying a Schedules Direct / Gracenote program id (e.g. `EP000000060087`). Not part of the spec but widely seen in North American guides. ```xml <episode-num system="xmltv_ns">0 . 11 . 0/1</episode-num> <episode-num system="onscreen">S01E12</episode-num> ``` #### Technical broadcast details - **`<video>`** holds `present` (yes/no), `colour` (yes/no), `aspect` (e.g. `16:9`), `quality` (e.g. `HDTV`, `1080p`). - **`<audio>`** holds `present` (yes/no) and `stereo`, whose legal values are **`mono`, `stereo`, `dolby`, `dolby digital`, `bilingual`, `surround`**. (`bilingual` here means left/right channels carry different mono languages.) - **`<subtitles>`** has `type="teletext|onscreen|deaf-signed"` and an optional `<language>` child. Repeatable. ```xml <video><colour>yes</colour><aspect>16:9</aspect><quality>HDTV</quality></video> <audio><stereo>surround</stereo></audio> <subtitles type="teletext"><language>en</language></subtitles> ``` #### Lifecycle flags - **`<previously-shown>`** (empty element) marks a repeat. Optional `start` (when it last aired) and `channel` (where). Absence does **not** guarantee the programme is brand new. - **`<premiere>`** and **`<last-chance>`** are paragraph elements (with optional `lang`); their exact meaning varies by broadcaster, so they exist mainly to reproduce what a printed listing would say. Either can be empty (`<premiere/>`). - **`<new>`** (empty element) flags a first-run showing. #### Ratings, reviews and images - **`<rating>`** is a content/age rating: a required `<value>` plus optional `<icon>`s, with a `system` attribute (e.g. `MPAA`, `BBFC`, a country code). - **`<star-rating>`** is a quality score as `<value>` written `N/M` (e.g. `3/5`), optional `system` and `<icon>`. - **`<review>`** carries a critic review; `type="text|url"` is required, plus optional `source`, `reviewer`, `lang`. - **`<image>`** (a newer addition) is a richer image reference than `<icon>`: `type="poster|backdrop|still|person|character"`, `size="1|2|3"` (small/medium/large by largest dimension), `orient="P|L"` (portrait/landscape), and `system` to name the source (`imdb`, `tmdb`, …). ```xml <rating system="MPAA"><value>PG-13</value></rating> <star-rating><value>4/5</value></star-rating> <image type="poster" size="3" orient="P" system="tmdb">https://image.tmdb.org/.../poster.jpg</image> ``` ## The IPTV catch-up extension: `catchup-id` There is one widely-used attribute that is **not** part of the XMLTV specification but matters greatly for IPTV: **`catchup-id`** on `<programme>`. Some providers require a programme-specific id to build the archive URL, and players read it into the `{catchup-id}` placeholder used in M3U `catchup-source` templates. ```xml <programme start="20260618200000 +0000" channel="footv" catchup-id="episode-44871"> <title>The Match ``` This is the bridge to catch-up playback covered in the [M3U format reference](https://uniplayer.net/docs/specs/m3u) — when a channel's catch-up mode is `vod`, the `{catchup-id}` from the matched programme is substituted into the playback URL. ## Multi-language guides XMLTV supports localisation almost everywhere via the `lang` attribute. You can provide several ``, `<sub-title>`, `<desc>` and `<category>` elements, each tagged with a language, and a player will pick the user's preferred one. `<orig-language>` records the programme's original language separately from `<language>` (the version being broadcast). ```xml <title lang="en">The Bear Медведь A chef returns home to run a sandwich shop. Шеф-повар возвращается домой управлять кафе. ``` ## Linking XMLTV to your M3U playlist A guide is useless until it's joined to channels. The join happens on the playlist side: 1. In the `#EXTM3U` header, point at the guide with **`url-tvg`** (or its synonym **`x-tvg-url`**). 2. On each channel's `#EXTINF` line, set **`tvg-id`** equal to a `` in the guide. Players then resolve each channel against the XMLTV in a fixed order — match `tvg-id` to the channel `id` first, then fall back to comparing the channel's `tvg-name` and on-screen name against each ``. The single most reliable practice: **set `tvg-id` and make it identical to the XMLTV `id`.** Name-based matching is fragile across "HD" suffixes, case and spacing. (See the [M3U format reference](https://uniplayer.net/docs/specs/m3u) for the full matching algorithm and the `tvg-shift` time-offset attribute.) > **How UniPlayer handles this.** UniPlayer matches by `tvg-id` **and** falls back to channel name, so a single, universal XMLTV collection can be attached to several different playlists and still light up the right channels — even when those playlists use inconsistent ids. (Today UniPlayer links one EPG source per playlist; broader multi-EPG support is on the roadmap.) ## Delivery, refresh and validation - **Serve it compressed.** Gzip (`.xml.gz`) is universal and dramatically smaller. `.zip` and `.tar` are also common; `.xz` compresses harder still but isn't decoded by every player, so weigh size against compatibility. - **Refresh sensibly.** Most guides update every few hours; signal cadence on the playlist side (`refresh`/`m3uautoload`) rather than expecting the player to guess. - **Validate against the DTD.** Because XMLTV has a real DTD, you can validate structure and element order before shipping — this catches the out-of-order-children mistakes strict players reject. > **How UniPlayer handles this.** UniPlayer reads XMLTV guides as plain `.xml` or as `.gz`, `.zip` and `.tar` archives. It also de-duplicates work: if the same EPG source is referenced by several playlists, UniPlayer fetches it **once** rather than downloading the same guide repeatedly — keeping memory and bandwidth low even with large, shared guides. ## Validation checklist & common mistakes - **Declare UTF‑8** in the prolog and save the file as UTF‑8 (no stray BOM). - **Keep child elements in DTD order** — `title` before `desc` before `credits`, etc. Out-of-order children fail strict validation. - **Always include `stop`** so grid UIs can size slots. - **Use full timestamps with an explicit offset.** Omitting the zone silently means UTC. - **Make channel `id`s stable and unique**, and match them exactly with playlist `tvg-id`s. - **Don't bloat the guide.** Ship only the days you need, and gzip; multi-megabyte uncompressed guides slow down every client. - **``/`` first-wins.** Players usually take the first of repeated elements, so order language/genre variants deliberately. ## A complete, annotated example ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE tv SYSTEM "xmltv.dtd"> <tv source-info-name="Example EPG" generator-info-name="MyGrabber 1.0"> <channel id="bbcone.uk"> <display-name lang="en">BBC One HD</display-name> <display-name lang="en">BBC One</display-name> <icon src="https://example.com/logos/bbc1.png"/> </channel> <programme start="20260618200000 +0000" stop="20260618210000 +0000" channel="bbcone.uk" catchup-id="ep-44871"> <title lang="en">Sherlock A Study in Pink A modern update finds the famous sleuth solving crimes in London. Paul McGuigan Benedict Cumberbatch Martin Freeman 2010 Drama Crime en 88 GB 0 . 0 . 0/1 S01E01 en 12 5/5 https://image.tmdb.org/.../sherlock.jpg ``` ## A note on extensions and compatibility XMLTV has a genuine specification, but the ecosystem still adds non-standard attributes where the spec falls short — `catchup-id` for IPTV catch-up, `dd_progid` for North American program ids, and Android TV's `display-number`/`repeat-programs`. Consumers ignore attributes and elements they don't understand, so these extensions are safe to include. When you author a guide, validate against the DTD, prefer `xmltv_ns` episode numbers and stable channel ids, and test in the real player before publishing. > UniPlayer reads standard XMLTV guides and links them to the channels in your own playlist by `tvg-id`, with a name fallback. It also offers its own built-in guide to its users, compiled from publicly available sources — but it doesn't publish XMLTV files or public guide links, host channels, or sell content. You bring the playlist, and the guide is yours to choose: keep UniPlayer's, or attach your own. ## FAQ **What is XMLTV?** XMLTV is an open XML format for describing television schedules. Created in 1999 and maintained by the XMLTV Project, it has become the de facto standard EPG (Electronic Program Guide) format for IPTV players, OTT middleware and guide grabbers. A file lists channels and then programmes, with broadcast time and channel stored as attributes of each programme. **What date and time format does XMLTV use?** Timestamps look like YYYYMMDDHHMMSS followed by a space and a timezone offset, e.g. 20260618200000 +0000. Shorter substrings are allowed (e.g. just YYYYMM), and if you omit the offset the time is assumed to be UTC. Best practice is to always write the full timestamp with an explicit offset. **How do I link an XMLTV guide to my M3U playlist?** Put the guide's URL in the url-tvg (or x-tvg-url) attribute of the #EXTM3U header, then make each channel's tvg-id exactly equal the id of a element in the guide. Players match by tvg-id first, then fall back to matching names. **What's the difference between the xmltv_ns and onscreen episode-num systems?** xmltv_ns is a structured, machine-readable numbering: three dot-separated parts (season . episode . part), all zero-indexed, each optionally written as X/Y to show totals. onscreen is the human-readable string exactly as shown on screen, like S01E02. Use xmltv_ns when you can; onscreen otherwise. # Blog --- # Football in UniPlayer — Schedules, Match Data, and Jump-to-Goal Right Inside Your Playlist Source: https://uniplayer.net/docs/blog/sporthub-fifa/ SportHub is a dedicated screen in UniPlayer on Apple TV, iPhone, and iPad that turns your IPTV playlist into a full football hub. It automatically figures out which of your channels is showing a given match, displays schedules for 8 competitions (including the FIFA World Cup 2026), plus scores, line-ups, and stats — and key moments like goals open in the replay with a single tap. SportHub works only with the playlist you've already added and never provides channels of its own. It's included in your regular UniPlayer subscription, and your first 30 days after sign-up are free with full functionality. The FIFA World Cup 2026 is underway, and Europe's top leagues are running in parallel. Your playlist has dozens of channels, but the question is always the same: **which channel is showing the match, and when?** SportHub answers that for you — it takes your own playlist and turns it into a clean football screen with schedules, scores, stats, and a path straight to the match replay. Here's how it works and what you get as part of your UniPlayer subscription. ![SportHub home screen on Apple TV](/blog/sporthub-fifa/sporthub-main.jpg) ## What SportHub Is SportHub is a dedicated screen in the UniPlayer app, available on **Apple TV, iPhone, and iPad**. It doesn't replace your playlist or add new sources — it makes the playlist you already have smarter. Let's be clear about the most important point up front: **SportHub doesn't provide channels and doesn't broadcast matches itself.** It works exclusively with the playlist you've already added to UniPlayer. If your playlist contains a channel that's carrying a match, SportHub finds it and shows you where and when to watch. The video always comes from your own provider — we simply do the matching. SportHub is **included in your regular UniPlayer subscription** — there's nothing extra to pay for it. And when you sign up, you get **30 days of full access to everything in UniPlayer, free**, with no payment details required. That makes it the perfect time to try SportHub during the World Cup. ## How It Works: Automatic Match-to-Channel Linking This is the part no ordinary IPTV player can do. SportHub uses **only the data inside your playlist** — channel names and the electronic program guide (EPG). From there: 1. We find matches between your playlist's channels/EPG and real fixtures. 2. We map those matches onto the official competition schedule. 3. We layer on data about the match, the competition, the teams, and the venue. The result: next to every fixture in the schedule, you see **the specific channel from your playlist** that's carrying it. No more manually hunting for "where is Real Madrid playing today" and cycling through channels — SportHub has already lined it all up for you. ![Match card linked to a playlist channel](/blog/sporthub-fifa/sporthub-match-card.jpg) ## Everything About the Match — Before, During, and After For each fixture, SportHub shows a detailed card: - Date, time, venue, and stadium - Live or final score - Team line-ups - Stats: possession and key metrics - Key match events (goals, cards, substitutions) - Player positions on the pitch And all of it is available not just on the dedicated screen, but **right while you're watching** — as an overlay on the video, whether the match is live or a replay. You never have to leave the player just to check the score or the line-up. ![SportHub match detail screen](/blog/sporthub-fifa/sporthub-live-stats.jpg) ## Replays and Jump-to-Goal — Our Favorite Feature Missed the match? From the SportHub screen, you can open **any past match and watch it as a replay** — as long as your playlist's provider keeps an archive of sufficient length on that channel. But here's the best part: navigating by key moments. You pick an event (a goal, for example), and the player **jumps right to it**. We deliberately land you **one minute before the event** — so you can settle into the moment and see the goal build up, rather than dropping straight into the celebration. The jump is calculated using absolute time, so the exact entry point can vary slightly from one provider to another, depending on how precisely the archive is recorded on a given channel. In the vast majority of cases, though, you land exactly where you want to be. ![Jumping to a key match moment](/blog/sporthub-fifa/sporthub-live-key-events.jpg) ## Spoiler-Free Mode — Don't Learn the Score Too Soon This matters especially for IPTV: the stream often runs with a delay, and goal data can arrive before you actually see it on screen. To keep spoilers away, SportHub has a built-in **spoiler-free mode**. You can hide scores and events with a single toggle — globally, across all of SportHub. When you're ready to see the result, you turn the mode off and the scores appear. Perfect if you want to watch a replay later in the evening without knowing the outcome. ## Supported Competitions SportHub currently covers **8 competitions**: - FIFA World Cup 2026 - UEFA Champions League - UEFA Europa League - UEFA Nations League - Premier League - La Liga - Bundesliga - Ligue 1 ## What's Next SportHub is evolving quickly, and we have big plans: - More leagues and competitions - With good feedback — sports beyond football, too - A list of favorite teams and competitions - Match reminders - And much more A lot of this depends on your feedback — so if you have ideas or requests, let us know. ## How to Try It SportHub is already available in UniPlayer on **Apple TV, iPhone, and iPad**. All you need is your playlist (M3U / M3U8 and other supported sources) already added to the app. Open the SportHub screen, and the match schedule — linked to your own channels — appears automatically. SportHub is included in your regular UniPlayer subscription, and your first **30 days after sign-up are free, with full functionality**. The FIFA World Cup 2026 is the perfect reason to give it a try. Follow along and reach out: - Telegram: [@UniPlayer](https://t.me/UniPlayer) - Support: team@uniplayer.net