A complete IPTV solution that combines a Python bridge service with xTeVe to provide sports streams in M3U and XMLTV formats for Plex and other IPTV players.
Before you begin, ensure you have:
-
Plex Pass Subscription
- Required for Live TV & DVR functionality
- Available at plex.tv/plans
-
PPV.wtf VIP Account
-
Docker and Docker Compose
- Required for running the services
- Installation instructions available at docs.docker.com
- Quick Start
- Getting Your Auth Token
- Connecting to Plex
- Features
- Components
- Endpoints
- Docker Commands
- Notes
- Create the directory structure:
mkdir -p /mnt/<yourpool>/plexrelay
mkdir -p /mnt/<yourpool>/xteve- Create a docker-compose.yml file and paste the following content:
version: "3.9"
services:
plexrelay:
image: ghcr.io/timelessfun/plexrelay:latest
container_name: plexrelay-bridge
ports:
- "8880:8880"
volumes:
- /mnt/<yourpool>/plexrelay:/app/data
environment:
- PPV_AUTH_TOKEN=your_auth_token_here
restart: unless-stopped
xteve:
image: alturismo/xteve:latest
container_name: xteve
environment:
- PUID=568 # change to match your user ID
- PGID=568 # change to match your group ID
- TZ=America/Vancouver # change to your timezone
volumes:
- /mnt/<yourpool>/xteve:/config
ports:
- "34400:34400" # xTeVe web interface
restart: unless-stopped
depends_on:
- plexrelay-
Replace the following in the docker-compose.yml:
your_auth_token_herewith your PPV.wtf auth token (see below for instructions)<yourpool>with your actual storage pool name
-
Start the services:
docker-compose up -d- Access the services:
- Bridge Status: http://localhost:8880
- xTeVe Interface: http://localhost:34400/web
- (Optional) Verify M3U playlist works using
curl http://localhost:8880/playlist.m3uYou should see something like the following:
#EXTM3U
#EXTINF:-1 tvg-id="7304" tvg-name="Minnesota Twins vs. Cleveland Guardians" tvg-logo="https://i.imgur.com/DnxoXh3.png" group-title="MLB",Minnesota Twins vs. Cleveland Guardians
https://LINKTOSTREAM- Configure xTeVe:
- Go to http://localhost:34400/web
- Navigate to Settings → M3U/XSPF
- Add M3U Playlist:
- Name: "PlexRelay"
- URL: http://plexrelay:8880/playlist.m3u
- EPG URL: http://plexrelay:8880/epg.xml
- Click Test, then Save
- Go to Mappings to configure your channels
- Save your configuration
- Go to PPV.wtf and log in to your account
- Open your browser's Developer Tools (F12 or right-click -> Inspect)
- Go to the Network tab
- Refresh the page
- Click the first element that appears
- Click the "Cookies" section
- Copy the value of the "ThugSession" value including the quotations - this is your auth token
- Replace
your_auth_token_herein the docker-compose.yml with your actual token
-
In xTeVe (http://localhost:34400/web):
- Go to Settings → M3U/XSPF
- Note the "M3U URL" and "XMLTV URL" values
- These will be something like:
- M3U:
http://localhost:34400/playlist.m3u - XMLTV:
http://localhost:34400/epg.xml
- M3U:
-
In Plex:
- Go to Settings → Live TV & DVR
- Click "Set Up Plex DVR"
- Choose "M3U Playlist" as the source
- Enter the M3U URL from xTeVe
- Enter the XMLTV URL from xTeVe
- Click "Next"
- Select the channels you want to include
- Click "Next"
- Choose your DVR settings (recording quality, etc.)
- Make sure that you change the Guide Refresh Interval to be 1 hour This ensures that the listings will show up on plex as they are added
- Click "Next"
- Review your settings and click "Finish"
-
Accessing Live TV:
- In Plex, go to the "Live TV" section
- Your configured channels should now be available
- You can watch live streams and schedule recordings
-
Troubleshooting:
- If channels don't appear, verify the M3U and XMLTV URLs are accessible
- Check xTeVe logs for any stream issues
- Ensure your Plex server can reach the xTeVe container
- Try refreshing the guide data in Plex if EPG is not showing
- Fetches and caches sports streams (NBA, NFL, MLB, NHL) from PPV.wtf
- Provides M3U playlist and XMLTV EPG data
- Updates stream data every 6 hours
- Caches MPEG-TS URLs to reduce API calls
- Filters out expired games automatically
- Integrates with xTeVe for channel management and EPG
- Python-based service that interfaces with PPV.wtf
- Provides M3U and XMLTV endpoints
- Accessible at port 8880
- Channel management and EPG integration
- Provides a unified M3U playlist for Plex
- Web interface for configuration
- Accessible at port 34400
/- Status page showing service information/playlist.m3u- M3U playlist of available streams/epg.xml- XMLTV EPG data for the streams
/web- Web interface for configuration/playlist.m3u- Final M3U playlist for Plex/epg.xml- Final EPG data for Plex
- Start all services:
docker-compose up -d - View logs:
docker-compose logs -f - Stop all services:
docker-compose down - Restart all services:
docker-compose restart - View logs for specific service:
docker-compose logs -f plexrelayordocker-compose logs -f xteve
- This installation guide was designed for a TrueNAS Scale docker installation.
- The bridge service caches stream data and MPEG-TS URLs to reduce API calls
- Streams are automatically filtered to show only NBA, NFL, MLB, and NHL games
- Expired games are automatically removed from the playlist
- The service updates every 6 hours to fetch new streams and remove expired ones
- This service is designed for those with VIP status in PPV.wtf
- xTeVe provides the final M3U playlist that should be used in Plex
The PlexRelay service stores its cache data in the /mnt/<yourpool>/plexrelay directory. This includes:
- Stream information cache
- MPEG-TS URL cache
- All cached data is automatically refreshed every 6 hours
This persistent storage ensures that:
- The service starts up quickly using cached data
- Stream information is preserved across container restarts
- API calls are minimized by using cached data