Hdhriptv
An IPTV tuner that is compatible with HDHomeRun API's supported across a variety of applications and video players.
Install / Use
/learn @arodd/HdhriptvREADME
hdhriptv
Turn any M3U/IPTV playlist into a HDHomeRun tuner that Plex, Jellyfin, Emby, and other DVR software discover automatically.
What is hdhriptv?
hdhriptv is a lightweight server that makes your IPTV playlist look like a physical HDHomeRun TV tuner on your network. HDHomeRun is the most widely supported network TV tuner standard -- nearly every DVR application can detect and use one automatically. hdhriptv takes advantage of that by speaking the same protocol, so you can plug your IPTV channels into the DVR workflow you already use without any special client-side setup.
Point hdhriptv at an M3U playlist, curate the channels you want to publish through a built-in admin UI, and your DVR will discover it automatically -- just like a real tuner. From there, your DVR handles the rest -- guide data, recordings, live TV, and multi-device playback -- all using channels from your IPTV subscription.
hdhriptv is written in Go with an embedded SQLite database -- no external database required. It runs as a single binary, in Docker (multi-arch: amd64 and arm64), or as a systemd service. The only external dependency is ffmpeg, needed for the default ffmpeg-copy stream mode. If you use direct proxy mode, no ffmpeg is required. The Docker image includes ffmpeg out of the box.
Key Features
Channel Management
- Import channels from any M3U/IPTV playlist
- Curate which channels to publish through a web-based admin UI
- Attach multiple sources per channel with ordered failover priority
- Dynamic channel rules that automatically sync matching catalog items into channel sources
- Dynamic channel blocks for bulk channel creation from filter queries
- Merge/duplicate detection to identify overlapping catalog entries
Streaming
- Three stream modes: direct proxy, ffmpeg remux (copy), and ffmpeg transcode
- Shared sessions -- multiple viewers on the same channel share one upstream connection
- Automatic stall detection and source failover with configurable recovery policies
- Recovery filler (null packets, PSI, or decodable A/V slate) keeps clients connected during failover
- Configurable tuner count to match upstream provider limits
Discovery and Compatibility
- HDHomeRun UDP discovery (port 65001) -- detected automatically by DVR software
- UPnP/SSDP discovery with full device description and ContentDirectory browsing
- Standard lineup endpoints:
/discover.json,/lineup.json,/lineup.xml,/lineup.m3u - Optional legacy HTTP listener on port 80 for clients that ignore advertised ports
- Optional mDNS/Avahi integration for .local hostname resolution
DVR Integration
Every HDHomeRun-compatible app discovers hdhriptv automatically. For deeper integration, Channels DVR and Jellyfin get dedicated sync and refresh workflows:
- Forward sync: push hdhriptv channel mappings into your DVR's custom lineup
- Reverse sync: pull DVR-side mappings back into hdhriptv
- Per-channel DVR mapping control with lineup and station-ref support
- Jellyfin-native lineup refresh after playlist updates
- Channels DVR custom mapping API support
Automation
- Scheduled playlist refresh via cron expressions
- Auto-prioritize: probe sources and reorder by quality/availability
- Source health tracking with cooldown ladders for failing sources
- Background source probing at configurable intervals
- All jobs observable through the admin API with progress and status tracking
Admin and Observability
- Web UI for catalog browsing, channel management, tuner status, and automation
- Rapid source-add workflow for quickly building channel lineups
- Live tuner and session dashboard with recovery trigger controls
- Session history console with filterable diagnostics
- Full JSON API for scripting and integration
- Health check endpoint (
/healthz) for load balancers and orchestrators - Optional Prometheus metrics endpoint (
/metrics) - Per-client IP rate limiting with trusted proxy support
Compatibility
hdhriptv works with any software that supports HDHomeRun tuners. It is tested with the following DVR and media platforms:
| Platform | Discovery | Live TV | DVR/Recording | Notes |
|----------|-----------|---------|---------------|-------|
| Plex | Automatic (HDHomeRun scan) | Yes | Yes | Also supports manual IP entry |
| Channels DVR | Automatic (HDHomeRun scan) | Yes | Yes | Deepest integration: forward/reverse sync, custom lineup mapping |
| Jellyfin | Automatic (HDHomeRun tuner) | Yes | Yes | Native lineup refresh integration; use port 80 if detection fails |
| Emby | Automatic (HDHomeRun tuner) | Yes | Yes | Use port 80 if detection fails |
| VLC | Direct URL | Yes | -- | Open any /auto/v{channel} URL directly |
| UPnP apps | SSDP/ContentDirectory | Browse/Play | -- | BubbleUPnP, Kodi UPnP browser, and similar (read-only browse) |
Stream mode compatibility: ffmpeg-copy (the default) provides the best balance of compatibility and efficiency. Use ffmpeg-transcode if clients have trouble with your source codec/container format. Use direct for lowest overhead when sources already produce compatible MPEG-TS output.
Quick Start
Prerequisites
- Go
1.25.4or newer (seego.mod) - Network reachability from client devices to this service
ffmpeginstalled if using:STREAM_MODE=ffmpeg-copy(default)STREAM_MODE=ffmpeg-transcode
- No
ffmpegrequired if usingSTREAM_MODE=direct
Run Locally (Linux and Mac)
You can either download a prebuilt release binary for Linux
(hdhriptv-linux-amd64 / hdhriptv-linux-arm64) or macOS
(hdhriptv-darwin-amd64 / hdhriptv-darwin-arm64) from:
https://github.com/arodd/hdhriptv/releases
-
Download the release binary for your platform from the release page above.
-
Make the downloaded binary executable:
chmod +x ./hdhriptv-*
- Or build locally from source instead:
go build -o hdhriptv ./cmd/hdhriptv
- Run with minimum practical settings (replace
./hdhriptvwith your downloaded filename if not building locally):
PLAYLIST_URL="https://example.com/playlist.m3u" \
ADMIN_AUTH="admin:change-me" \
./hdhriptv
- Verify service health and discovery:
curl -s http://127.0.0.1:5004/healthz
curl -s http://127.0.0.1:5004/discover.json
curl -s http://127.0.0.1:5004/lineup.json
- Open
http://127.0.0.1:5004/ui/catalogand publish channels from catalog items.lineup.jsonis channel-only and remains empty until at least one channel is published.
Run With Docker
By default, use the public Docker Hub image:
docker pull arodd/hdhriptv:latest
Run container:
docker run --rm -it \
-p 5004:5004/tcp \
-p 65001:65001/udp \
-p 1900:1900/udp \
-v hdhriptv-data:/data \
-e PLAYLIST_URL="https://example.com/playlist.m3u" \
-e ADMIN_AUTH="admin:change-me" \
-e UPNP_ENABLED=true \
arodd/hdhriptv:latest
Notes:
- The image includes
ffmpeg. - The runtime image uses
alpine:3.23and installsffmpegfrom Alpine'scommunityrepository. - Multi-arch image available (amd64, arm64).
- SQLite state persists in
/datawhen a volume is mounted. - Add
-p 80:80/tcp -e HTTP_ADDR_LEGACY=:80if you need legacy client compatibility.
Optionally, build and run from the local Dockerfile instead:
docker build -t hdhriptv:local .
docker run --rm -it \
-p 5004:5004/tcp \
-p 65001:65001/udp \
-p 1900:1900/udp \
-v hdhriptv-data:/data \
-e PLAYLIST_URL="https://example.com/playlist.m3u" \
-e ADMIN_AUTH="admin:change-me" \
-e UPNP_ENABLED=true \
hdhriptv:local
Build and publish the same multi-arch image flow used in GitLab CI from your local machine (run docker login first):
make release-local REGISTRY_IMAGE=registry.example.com/org/hdhriptv IMAGE_TAG=latest
Run on Windows
-
Download the Windows binary release (
hdhriptv-windows-amd64.exe). -
Install
ffmpegandffprobe(Windows builds):- Gyan release builds: https://www.gyan.dev/ffmpeg/builds/#release-builds
- BtbN release builds: https://github.com/BtbN/FFmpeg-Builds/releases
-
Extract the build and point both flags to executable paths (not just the
bindirectory):--ffmpeg-path C:\Users\<you>\ffmpeg\bin\ffmpeg.exe--ffprobe-path C:\Users\<you>\ffmpeg\bin\ffprobe.exe
-
Common startup pattern:
.\hdhriptv.exe `
--playlist-url https://example.com/playlist `
--ffmpeg-path C:\users\person\ffmpeg\bin\ffmpeg.exe `
--ffprobe-path C:\users\person\ffmpeg\bin\ffprobe.exe `
--http-addr-legacy :80 `
--friendly-name "HDHRIPTV Windows"
Stream Modes and Tradeoffs
| Mode | ffmpeg Required | CPU Use | Compatibility | Notes |
| --- | --- | --- | --- | --- |
| direct | No | Lowest | Lowest/variable | Byte-for-byte upstream proxy; codec/container unchanged. |
| ffmpeg-copy | Yes | Low | High | Remux to MPEG-TS without transcoding. Good default. |
| ffmpeg-transcode | Yes | Highest | Highest | Transcodes to H.264/AAC MPEG-TS for difficult clients. |
Configuration Reference
The most common settings are listed below. For the full reference including all flags, internal stream tuning, and SQLite diagnostic toggles, see docs/CONFIGURATION.md.
| Flag | Environment Variable | Default | Notes |
| --- | --- | --- | --- |
| --playlist-url | PLAYLIST_URL | empty | M3U playlist URL. If empty, no automatic refresh runs. |
| --db-path | DB_PATH | ./hdhr-iptv.db | SQLite file location. |
| --http-addr | HTTP_ADDR | :5004 | Primary HTTP listener. |
| --http-addr-legacy | HTTP_ADDR_LEGACY | empty | Optional second listener, often :80. |
| --tuner-count | TUNER_COUNT | 2 | Max concurrent stream sessions. |
| --traditional-guide-start | TRADITIONAL_GUIDE_START | 100 | First guide number assigned to traditional channels. Must be between 1 and 9999. Existing traditional channels are renumbered on sta
