Files
projects/Dockers/self-hosted-iptv/README.md
T
Bram cc226806eb
Build and Push Docker Images / build-and-push (push) Successful in 19s
tmdb integration
2026-02-11 17:48:07 +01:00

60 lines
3.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Self-hosted IPTV
Serves M3U playlists that randomly schedule video files from `/movies` and `/series`, with the same show never appearing twice in a row.
## Setup
1. Create `/data/channels.json` (see `data/channels.json.example`).
**channels.json format:**
- `channels`: array of channel objects
- Each channel:
- `id`: unique id (used in URLs)
- `name`: display name
- `paths`: list of path keys to include:
- `"movies"` — all videos under `/movies`
- `"series/Show Name"` — all videos under `/series/Show Name`
2. Run the container with volumes:
```bash
docker build -t self-hosted-iptv .
docker run -d --name iptv -p 8080:8080 \
-v /path/to/movies:/movies:ro \
-v /path/to/series:/series:ro \
-v /path/to/data:/data \
self-hosted-iptv
```
When using TMDB metadata, mount `/data` read-write (as above) so the app can store and reuse metadata in `/data/tmdb_cache/`. Use `-v /path/to/data:/data:ro` only if you do not use TMDB.
**Optional EPG metadata (Dutch) from TMDB:**
To show series titles, episode names, and descriptions in the TV guide in **Dutch**, set a [TMDB API key](https://www.themoviedb.org/settings/api) (free after sign-up):
- `TMDB_API_KEY` your TMDB API key (v3).
Series are matched by folder name (e.g. `series/W817` → search "W817"); episode info is matched from filenames like `S01E01`. All metadata is requested in Dutch (`language=nl`).
- **Persistent cache:** Fetched metadata is stored under `/data/tmdb_cache/` (series search, series details, episode, episode credits). When generating the EPG, the app checks this cache first and only calls TMDB for missing entries. Mount `/data` read-write (omit `:ro`) so the cache can be written.
- **Rate limit:** TMDB allows 40 requests per 10 seconds. The app enforces this limit when calling the API; if the cache is warm, few or no requests are made during EPG generation.
3. In your IPTV client or **Plex DVR**, add:
- **Playlist URL:** `http://<host>:8080/playlist.m3u`
- **EPG (XMLTV) URL:** `http://<host>:8080/epg.xml`
Plex will show programme titles and times for each channel.
Each channel in the M3U points to a **continuous live stream** (`/live/<id>`): FFmpeg concatenates the channels randomized videos into one MPEG-TS stream and loops it. The **schedule** (and EPG) is built from video durations (via ffprobe) so start/stop times match whats actually playing. The same order is cached for 24h so the EPG and live stream stay in sync.
## Endpoints
- `GET /` — simple web index with playlist and EPG links
- `GET /playlist.m3u` — master M3U for Plex DVR (one live stream URL per channel)
- `GET /epg.xml` or `GET /xmltv.xml` — XMLTV EPG (14 days, UTC)
- `GET /live/<channel_id>` — continuous MPEG-TS stream for that channel (for tuning/recording)
- `GET /channel/<id>/playlist.m3u` — single channel M3U (list of individual video URLs)
- `GET /stream?path=movies/...` or `path=series/...` — stream a single video file
## Shuffle behaviour
Videos are grouped by path (e.g. one group per show or the whole movies folder). Each group is shuffled, then items are interleaved round-robin so the same show never plays back-to-back.