Slopsoil is a Discord self-bot that streams live TV, IPTV playlists, YouTube videos, Jellyfin media, and any HTTP/HLS/RTSP stream directly into a Discord voice channel - as a screenshare that all server members can watch together.
Features include TVheadend integration, Jellyfin integration, M3U/IPTV playlist management with live EPG (now-playing), YouTube playback via yt-dlp, and hardware-accelerated H.264 encoding via VA-API or NVIDIA NVENC.
Disclaimer:
Slopsoil is a self-bot. It runs on a real Discord user account, not a bot application.
Self-bots violate Discord's Terms of Service.
Use it on an account you are willing to lose, and do not use it in a way that disrupts other users or servers.
The authors take no responsibility for account terminations or other consequences.
Keywords: discord iptv bot, discord youtube stream, stream tv to discord, discord live stream bot, discord voice channel video, iptv discord, self-bot streaming, tvheadend discord, hls discord bot
- Screenshots
- Features
- How It Works
- Requirements
- Installation - Bare Metal
- Installation - Docker Compose
- Configuration
- Commands
- Rebuilding the Docker Container
- Hardware Acceleration
- Running Tests
| Channel List | Stream Running |
|---|---|
![]() |
![]() |
- YouTube & media streaming - play any URL that yt-dlp supports (YouTube VODs, YouTube Live, Twitch VODs, etc.) directly into a voice channel; live streams are detected automatically and streamed without downloading
- MJPEG / CGI stream support - play
.cgivideo URLs (IP cameras, legacy streaming servers) and MJPEG-over-HTTP streams directly - IPTV / M3U playlist support - add M3U sources by URL; channels are listed with live EPG now-playing info
- TVheadend integration - browse and play live TV channels from a TVheadend server; search the EPG by show title and schedule playback; showtimes are shown in the configured timezone
- Jellyfin integration - search and stream movies, series, and episodes from a Jellyfin media server; transcoding is offloaded to Jellyfin so the bot streams H.264/AAC with subtitles suppressed
- Auto-leave on empty channel - the bot automatically leaves and stops streaming when the last user leaves the voice channel
- Go-live / screenshare delivery - streams appear as a screenshare so all members in the channel can watch
- H.264 hardware acceleration - auto-detects NVIDIA NVENC, VA-API (Intel/AMD), or falls back to software encoding
- Discord DAVE E2EE support - correctly handles Discord's end-to-end encryption protocol for voice channels
- Role-based access control - admin, friend, viewer, and none tiers; friends list and guild membership are used automatically
slopsoil sends H.264 video and Opus audio directly over Discord's voice UDP protocol, appearing to other users as a screenshare (go-live stream). It patches discord.py-self at runtime to add video capability negotiation and implements the full RTP packetization pipeline including SPS/VUI rewriting, RFC 6184 FU-A fragmentation, and DAVE E2EE encryption.
For a detailed technical explanation of the streaming pipeline, the discord.py-self patches, and the esoteric protocol-level discoveries made while building this, see STREAMING.md.
| Requirement | Notes |
|---|---|
| Python 3.11+ | |
| FFmpeg | Fedora: ffmpeg-free (not RPM Fusion's ffmpeg). See Hardware Acceleration. |
| libdave / dave.py | The official Discord DAVE E2EE C library; dave.py wraps it |
| A Discord account token | Not a bot token - slopsoil runs as a self-bot on a real user account |
- Docker Engine 24+ and Docker Compose v2
- Optional: a VA-API GPU (
/dev/dri) or NVIDIA GPU for hardware encoding
git clone https://github.com/topsoil/slopsoil.git
cd slopsoilFedora / RHEL:
sudo dnf install ffmpeg-freeUbuntu / Debian:
sudo apt install ffmpegImportant: Do not use RPM Fusion's
ffmpegpackage on Fedora. It ships libx264, whose output causes Discord to drop the stream after one frame. Fedora's built-inffmpeg-freepackage (libopenh264) is required. See STREAMING.md for the full explanation.
python -m venv venv && source venv/bin/activate
pip install -r requirements.txtThis installs:
discord.py-self- self-bot library with voice supportPyNaCl- libsodium bindings for RTP encryptionpython-dotenv-.envfile loadingdavey- stub package (replaced at runtime by the DAVE compatibility shim)dave.py- DisnakeDev's official libdave Python bindings (working DAVE/E2EE)yt-dlp- YouTube and media downloader
Copy the example environment file and fill in your values:
cp .env.example .envSee Configuration for details on each variable.
python3 bot.pygit clone https://github.com/topsoil/slopsoil.git
cd slopsoilcp .env.example .envEdit .env with your Discord token and other settings. See Configuration.
docker compose up -d --buildThe container will build automatically on first run. IPTV source data is persisted in a named Docker volume (slopsoil-data) so your M3U sources survive container restarts and updates.
docker compose logs -fAll configuration is done via environment variables in .env:
# Required - your Discord account token (not a bot token)
DISCORD_TOKEN=your_token_here
# Comma-separated Discord user IDs that can control the bot
ALLOWED_USER_IDS=123456789012345678,987654321098765432
# Optional - TVheadend server (all three must be set to enable TV commands)
TVHEADEND_URL=http://192.168.1.100:9981
TVHEADEND_USER=admin
TVHEADEND_PASS=yourpassword
# Optional - IANA timezone for showtimes displayed by !search (e.g. America/New_York)
# If unset, the system timezone of the machine running the bot is used.
TIMEZONE=
# Optional - Jellyfin server (both must be set to enable Jellyfin commands)
JELLYFIN_URL=http://192.168.1.100:8096
JELLYFIN_API_KEY=your_api_key_here| Variable | Required | Description |
|---|---|---|
DISCORD_TOKEN |
Yes | Your Discord account token |
ALLOWED_USER_IDS |
Yes | Comma-separated user IDs with admin access |
TVHEADEND_URL |
No | Base URL of your TVheadend server |
TVHEADEND_USER |
No | TVheadend username |
TVHEADEND_PASS |
No | TVheadend password |
TIMEZONE |
No | IANA timezone name for !search showtimes (e.g. America/Chicago). Defaults to the system timezone. |
JELLYFIN_URL |
No | Base URL of your Jellyfin server |
JELLYFIN_API_KEY |
No | Jellyfin API key (generate in Dashboard → API Keys) |
TVheadend is optional. If any of the three TVHEADEND_* variables are missing, the !channels, !search, and TVheadend-backed !play commands are not loaded.
- Open Discord in a browser
- Open DevTools (F12) → Network tab
- Filter for requests to
discord.com/api - Look for the
Authorizationheader on any request - that value is your token
Security: Keep your token private. Anyone with your token can access your Discord account.
| Command | Role | Description |
|---|---|---|
!join |
Friend | Join your current voice channel |
!leave |
Friend | Leave the voice channel |
!stop |
Friend | Stop the active stream |
| Command | Role | Description |
|---|---|---|
!play <channel number> |
Friend | Play a TVheadend channel by number |
!play <channel name> |
Friend | Play a channel by name (case-insensitive substring match; searches TVheadend and IPTV) |
!play <URL> |
Friend | Play any URL — YouTube VODs, YouTube Live streams, direct HLS/HTTP/RTSP streams, .cgi MJPEG feeds, etc. Live streams are detected automatically and streamed without downloading. |
!channels |
Viewer | List all available channels with live now-playing info (paginated) |
!search <show title> |
Friend | Search EPG for a show — plays immediately if airing now, or schedules for upcoming airtime. Showtimes are shown in the TIMEZONE configured in .env. |
| Command | Role | Description |
|---|---|---|
!media <title> |
Friend | Search Jellyfin for a movie or series and stream it into your voice channel. A single movie match plays immediately. For series, the bot walks you through season → episode selection. Accepts an optional sXXeYY suffix (e.g. !media breaking bad s03e05) to jump directly to a specific episode. Transcoding is handled server-side by Jellyfin; subtitles are always suppressed. |
| Command | Role | Description |
|---|---|---|
!add-source <name> <url> |
Admin | Add an M3U playlist source |
!sources |
Admin | List all sources with enabled/disabled status |
!sources enable <name> |
Admin | Enable a source |
!sources disable <name> |
Admin | Disable a source |
!delete-source |
Admin | Interactively delete a source |
| Command | Role | Description |
|---|---|---|
!ping |
Any | Check if the bot is responding |
!help |
Any | List available commands |
| Role | Who qualifies |
|---|---|
| Admin | User IDs listed in ALLOWED_USER_IDS |
| Friend | Users on the bot account's friends list |
| Viewer | Members of any guild the bot account is in |
| None | Everyone else |
When you pull new changes to the project, rebuild the container image:
# Pull latest changes
git pull
# Rebuild the image and restart the container
docker compose up -d --buildIf you only changed .env (no code changes), a restart is enough - no rebuild needed:
docker compose restartTo completely reset the container and its image (does not delete IPTV source data, which lives in the volume):
docker compose down
docker compose up -d --buildTo also wipe the IPTV source data volume:
docker compose down -v
docker compose up -d --buildslopsoil auto-detects the best available H.264 encoder in this priority order:
| Encoder | Type | Requires |
|---|---|---|
h264_nvenc |
NVIDIA GPU | NVIDIA driver + nvidia-container-toolkit |
h264_vaapi |
VA-API (Intel/AMD) | /dev/dri device |
libopenh264 |
Cisco software | Included in ffmpeg-free |
libx264 |
Software (fallback) | Not used in Docker (see below) |
Uncomment the devices section in docker-compose.yml:
devices:
- /dev/dri:/dev/driThen rebuild:
docker compose up -d --buildInstall nvidia-container-toolkit, then add to docker-compose.yml:
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]The Docker image is based on Fedora and uses ffmpeg-free. This package does not include libx264 (which requires a separate RPM Fusion repository and a different FFmpeg build). More importantly, libx264-encoded streams cause Discord to silently drop the stream after the very first frame. libopenh264 and the hardware encoders do not have this problem. See STREAMING.md for the technical details.
The test suite covers the permissions system, video compat patches, voice utilities, and the DAVE shim logic.
source venv/bin/activate
pip install pytest pytest-asyncio pytest-mockOr without activating the venv:
venv/bin/pip install pytest pytest-asyncio pytest-mockvenv/bin/pytest# Verbose output with print statements
venv/bin/pytest -v -s
# Stop on first failure
venv/bin/pytest -x
# Run a specific file
venv/bin/pytest tests/test_permissions.py
# With coverage report
venv/bin/pip install pytest-cov
venv/bin/pytest --cov --cov-report=term-missing

