Sign inSign up

kjoyce77/hls-subtitle-proxy

By kjoyce77

•Updated 6 months ago

An HLS proxy that intercepts live streams and burns WebVTT subtitles directly into the video.

Image
0

2.7K

kjoyce77/hls-subtitle-proxy repository overview

⁠hls-subtitle-proxy

An HLS proxy that intercepts live streams and burns WebVTT subtitles directly into the video, producing a single-track output compatible with any player — including those that don't support HLS subtitle tracks (Roku, many smart TVs, etc.).

⁠Repository

If you are viewing this on Docker Hub you can find the source repository on Gitlab at nodeto/hls-subtitle-proxy or by clicking here⁠.

⁠Quick Start

docker run -d \
  --restart unless-stopped \
  --name hls-subtitle-proxy \
  -p 8081:8080 \
  -e UPSTREAM=http://your-iptv-source/playlist.m3u \
  kjoyce77/hls-subtitle-proxy

Point your IPTV client at http://<host>:8081/playlist.m3u.

⁠How It Works

  1. Fetches the upstream M3U playlist and filters to your configured channels.
  2. For each channel, probes the HLS master playlist for a WebVTT subtitle track.
  3. On segment requests, downloads the .ts segment + matching subtitle cues, then uses ffmpeg to burn the subtitles into the video in real time.
  4. Serves the modified segments back to the client as a standard HLS stream.

⁠Configuration

All settings are configured via environment variables.

Env VarDefaultDescription
UPSTREAMUpstream M3U playlist URL (required)
EXT_URL(derived from listen address)External URL clients use to reach this proxy
CHANNELSComma-separated list of channel IDs
CONFIGPath to a channels.json config file (mount into container)
PRESETmediumx264 speed preset (ultrafast … veryslow)
WORKERS2Number of concurrent ffmpeg encode workers
CACHE_DIR(auto temp dir)Directory for cached encoded segments
VERBOSESet to any value to enable verbose logging
ADDR:8080Listen address (host:port) — note: this only affects the listen address inside the container; change the host-side port via Docker's -p flag instead
⁠Channel Configuration

Channels can be configured in two ways:

  1. CHANNELS env — comma-separated list of channel IDs:

    -e CHANNELS=csi,law-and-order,star-trek-1
    
  2. Mounted config file — mount a JSON file into the container and set CONFIG:

    -v /path/to/channels.json:/app/channels.json:ro
    

    A channels.json file looks like:

    {
      "channels": [
        "csi",
        "law-and-order",
        "star-trek-1"
      ]
    }
    

    If a channels.json is mounted to /app/channels.json it will be picked up automatically without needing to set CONFIG.

⁠Examples

Minimal — proxy all channels:

docker run -d \
  --restart unless-stopped \
  --name hls-subtitle-proxy \
  -p 8080:8080 \
  -e UPSTREAM=https://example.com/playlist.m3u \
  kjoyce77/hls-subtitle-proxy

With channel filtering and encoding preset:

docker run -d \
  --restart unless-stopped \
  --name hls-subtitle-proxy \
  -p 8080:8080 \
  -e UPSTREAM=https://example.com/playlist.m3u \
  -e CHANNELS=csi,star-trek-1,doctor-who-classic \
  -e PRESET=fast \
  -e EXT_URL=http://myserver.local:8080 \
  kjoyce77/hls-subtitle-proxy

With a mounted config file:

docker run -d \
  --restart unless-stopped \
  --name hls-subtitle-proxy \
  -p 8080:8080 \
  -e UPSTREAM=https://example.com/playlist.m3u \
  -v /path/to/channels.json:/app/channels.json:ro \
  kjoyce77/hls-subtitle-proxy

Docker Compose:

services:
  hls-proxy:
    image: kjoyce77/hls-subtitle-proxy
    ports:
      - "8080:8080"
    environment:
      UPSTREAM: https://example.com/playlist.m3u
      CHANNELS: csi,law-and-order,star-trek-1
      PRESET: fast
    restart: unless-stopped

⁠License

MIT License - see LICENSE⁠ for details.

Tag summary

Content type

Image

Digest

sha256:cef03db50…

Size

59.9 MB

Last updated

6 months ago

docker pull kjoyce77/hls-subtitle-proxy