Skip to content

filipeneves/bacalhau

Repository files navigation

🐟 bacalhau

bacalhau Logo

Self-hosted IPTV Player for NAS and Docker

Features β€’ Quick Start β€’ GPU Acceleration β€’ Configuration β€’ Codec Support

ko-fi

Discord


Features

  • πŸ“Ί M3U/M3U8 Playlist Support - Import local files or URLs (up to 200MB)
  • πŸ”— Xtream Codes API - Connect to Xtream-compatible providers
  • 🎬 VOD Support - Browse and play Movies & Series from Xtream Codes playlists
  • πŸ“– EPG Guide - Electronic Program Guide with XMLTV support
  • 🎬 Live Recording - Record streams directly to your server
  • πŸ”— Stream Sharing - Share live streams with guests via unique URLs
  • πŸ‘₯ Guest Viewer Tracking - See who's watching your shared streams in real-time
  • ⚑ GPU Transcoding - Hardware-accelerated video encoding
  • πŸ’Ύ Persistent Playlists - Playlists stored on disk, accessible from any device
  • 🎨 Dark/Light Theme - Customizable interface
  • 🐳 Docker-first - Designed for self-hosted environments
  • πŸ“± Responsive - Works on desktop and mobile browsers

Quick Start

NAS Deployment (Pre-built Images)

For NAS systems like Synology, QNAP, or Unraid, use pre-built images from GitHub Container Registry. No need to clone the repo!

  1. Create a docker-compose.yml file:
name: bacalhau

services:
  web:
    image: ghcr.io/filipeneves/bacalhau:latest
    ports:
      - "8456:80"
    depends_on:
      - proxy
      - transcoder
    restart: unless-stopped

  proxy:
    image: ghcr.io/filipeneves/bacalhau-proxy:latest
    ports:
      - "8888:8080"
    restart: unless-stopped

  transcoder:
    # Choose your image based on GPU and architecture:
    # - ghcr.io/filipeneves/bacalhau-transcoder:latest        (CPU only, amd64 + arm64)
    # - ghcr.io/filipeneves/bacalhau-transcoder:latest-vaapi  (AMD/Intel GPU, amd64 only)
    # - ghcr.io/filipeneves/bacalhau-transcoder:latest-nvidia (NVIDIA GPU, amd64 only)
    # ⚠️ ARM NAS (Synology, etc.): Use the CPU-only image (no -vaapi or -nvidia suffix)
    image: ghcr.io/filipeneves/bacalhau-transcoder:latest
    ports:
      - "3001:3001"
    volumes:
      - ./recordings:/recordings
      - ./playlists:/playlists
    # Uncomment for AMD/Intel GPU on x86 systems:
    # devices:
    #   - /dev/dri:/dev/dri
    restart: unless-stopped

volumes:
  recordings:
  playlists:
  1. Create data directories and start:
mkdir -p recordings playlists
docker compose up -d
  1. Access the player at: http://your-nas-ip:8456

Building from Source

  1. Clone the repository:
git clone https://github.com/filipeneves/bacalhau.git
cd bacalhau
  1. Create data directories:
mkdir -p recordings playlists
  1. Start the services:
docker compose up -d
  1. Access the player at: http://localhost:8456

Development Mode

For development with hot-reload:

docker compose --profile dev up dev

Then access at: http://localhost:5173

Services

Service Port Description
Web UI (prod) 8456 Main player interface
Web UI (dev) 5173 Development server with hot-reload
CORS Proxy 8888 Proxy for cross-origin streams
Transcoder 3001 FFmpeg transcoding & playlist storage

Available Images

Image Description
ghcr.io/filipeneves/bacalhau:latest Web UI (nginx, multi-arch)
ghcr.io/filipeneves/bacalhau-proxy:latest CORS proxy (multi-arch)
ghcr.io/filipeneves/bacalhau-transcoder:latest CPU-only transcoder (multi-arch)
ghcr.io/filipeneves/bacalhau-transcoder:latest-vaapi AMD/Intel GPU transcoder (amd64)
ghcr.io/filipeneves/bacalhau-transcoder:latest-nvidia NVIDIA GPU transcoder (amd64)

GPU Acceleration

bacalhau supports hardware-accelerated video transcoding for reduced CPU usage and better performance.

Supported GPU Types

GPU Encoder Docker Config Requirements
NVIDIA NVENC Dockerfile.nvidia nvidia-container-toolkit
AMD VAAPI Dockerfile.vaapi /dev/dri device
Intel QSV/VAAPI Dockerfile.vaapi /dev/dri device
Apple VideoToolbox N/A (macOS only) -
CPU libx264 Dockerfile None

NVIDIA GPU Setup

  1. Install nvidia-container-toolkit:
# Ubuntu/Debian
sudo apt install nvidia-container-toolkit
sudo systemctl restart docker
  1. Update docker-compose.yml:
transcoder:
  build:
    context: ./transcoder
    dockerfile: Dockerfile.nvidia
  deploy:
    resources:
      reservations:
        devices:
          - driver: nvidia
            count: all
            capabilities: [gpu, video]
  1. Rebuild and start:
docker compose down
docker compose build transcoder
docker compose up -d

AMD/Intel GPU Setup (VAAPI)

  1. Update docker-compose.yml:
transcoder:
  build:
    context: ./transcoder
    dockerfile: Dockerfile.vaapi
  devices:
    - /dev/dri:/dev/dri
  1. Rebuild and start:
docker compose down
docker compose build transcoder
docker compose up -d

Verify GPU Access

Check if GPU is detected inside the container:

# For VAAPI (AMD/Intel)
docker exec bacalhau-transcoder-1 vainfo

# Check available encoders
docker exec bacalhau-transcoder-1 ffmpeg -hide_banner -encoders 2>/dev/null | grep -i "vaapi\|nvenc\|qsv"

Configuration

Environment Variables

Create a .env file or set these in your environment:

Variable Default Description
RECORDINGS_PATH ./recordings Path to store recordings
PLAYLISTS_PATH ./playlists Path to store playlists
VITE_PROXY_URL http://localhost:8888 CORS proxy URL
VITE_TRANSCODER_URL http://localhost:3001 Transcoder service URL
BACALHAU_USER - Username for authentication (optional)
BACALHAU_PASSWORD - Password for authentication (optional)
SESSION_SECRET - Secret key for session encryption (optional)

Authentication

bacalhau supports optional password protection for your instance. This is useful when exposing your server to the internet or sharing it with others.

⚠️ Note: The current authentication system is temporary. A full-fledged authentication and user management system with multiple users is planned for a future release.

To enable authentication, add these environment variables to your docker-compose.yml:

transcoder:
  environment:
    - BACALHAU_USER=your_username
    - BACALHAU_PASSWORD=your_password
    - SESSION_SECRET=your-random-secret-key-here

Example:

transcoder:
  image: ghcr.io/filipeneves/bacalhau-transcoder:latest
  ports:
    - "3001:3001"
  volumes:
    - ./recordings:/recordings
    - ./playlists:/playlists
  environment:
    - RECORDINGS_DIR=/recordings
    - PLAYLISTS_DIR=/playlists
    - BACALHAU_USER=admin
    - BACALHAU_PASSWORD=changeme
    - SESSION_SECRET=change-this-to-a-random-string
  restart: unless-stopped

After enabling authentication, restart the transcoder service:

docker compose down
docker compose up -d

When you access the app, you'll be prompted to log in with your credentials. Sessions are valid for 7 days.

Playlist Storage

Playlists are stored on disk (not in browser storage) so they persist across devices and browsers. This is ideal for NAS deployments where you want to access the same playlists from any device on your network.

# In .env file
PLAYLISTS_PATH=/path/to/your/playlists

# Or inline with docker compose
PLAYLISTS_PATH=/mnt/nas/playlists docker compose up -d

Recording Storage

To customize where recordings are saved, set the RECORDINGS_PATH environment variable:

# In .env file
RECORDINGS_PATH=/path/to/your/recordings

# Or inline with docker compose
RECORDINGS_PATH=/mnt/nas/recordings docker compose up -d

Settings

Access settings via the βš™οΈ icon in the player:

  • General - Theme preferences
  • Playlists - Manage M3U playlists and Xtream connections
  • Transcoding - GPU acceleration and quality settings
  • Recording - View and manage recordings
  • Credits - Version info and credits

Codec Support

Input Formats (Decoding)

Format Container Status
H.264/AVC TS, MP4, MKV βœ… Supported
H.265/HEVC TS, MP4, MKV βœ… Supported
MPEG-2 TS βœ… Supported
VP9 WebM βœ… Supported
AAC All βœ… Supported
MP3 All βœ… Supported
AC3/EAC3 TS βœ… Supported

Output Formats (Encoding)

GPU H.264 H.265 Notes
NVIDIA h264_nvenc hevc_nvenc GTX 600+
AMD h264_vaapi hevc_vaapi RX 400+
Intel h264_qsv / h264_vaapi hevc_qsv 6th gen+
CPU libx264 libx265 Universal

Stream Protocols

Protocol Status Notes
HLS (.m3u8) βœ… Native Direct playback
MPEG-TS βœ… Via transcoder Converted to HLS
HTTP(S) βœ… Supported Via CORS proxy

Docker Compose Reference

Full Configuration

services:
  dev:
    build:
      context: .
      dockerfile: Dockerfile
      target: development
    ports:
      - "5173:5173"
    environment:
      - VITE_PROXY_URL=http://localhost:8888
      - VITE_TRANSCODER_URL=http://localhost:3001
    depends_on:
      - proxy
      - transcoder

  proxy:
    image: redocly/cors-anywhere
    ports:
      - "8888:8080"

  transcoder:
    build:
      context: ./transcoder
      dockerfile: Dockerfile.vaapi  # or Dockerfile.nvidia
    ports:
      - "3001:3001"
    volumes:
      - ${RECORDINGS_PATH:-./recordings}:/recordings:z
      - ${PLAYLISTS_PATH:-./playlists}:/playlists:z
    devices:
      - /dev/dri:/dev/dri  # For AMD/Intel GPU
    # For NVIDIA, replace devices with:
    # deploy:
    #   resources:
    #     reservations:
    #       devices:
    #         - driver: nvidia
    #           count: all
    #           capabilities: [gpu, video]

Production Deployment

For production, use the prod profile:

docker compose up -d

This serves the built static files via nginx on port 8456.

Troubleshooting

Stream not playing

  1. Check if the transcoder is running:
docker logs bacalhau-transcoder-1
  1. Verify CORS proxy is accessible:
curl http://localhost:8888/https://example.com

GPU not detected

  1. Check device permissions:
ls -la /dev/dri/
  1. Verify container has access:
docker exec bacalhau-transcoder-1 ls -la /dev/dri/

High CPU usage

Enable GPU acceleration in Settings β†’ Transcoding and select your GPU type.

Development

Prerequisites

  • Node.js 20+
  • Docker & Docker Compose

Local Development

# Install dependencies
npm install

# Start dev server
npm run dev

Build for Production

npm run build

Credits

bacalhau is created by Filipe Neves

License

MIT License - see LICENSE for details.


🐟 bacalhau means salted codfish in Portuguese
πŸ‡«πŸ‡· Cooked in France & Luxembourg πŸ‡±πŸ‡Ί by a Portuguese πŸ‡΅πŸ‡Ή

About

🐟 Modern IPTV player with GPU-accelerated HLS transcoding. Supports M3U playlists, Xtream Codes API & EPG guides. Built with Vue 3 + Vuetify, Dockerized for easy NAS deployment. Hardware encoding via NVIDIA NVENC, AMD/Intel VAAPI, or Apple VideoToolbox. Server-side playlist storage for persistence across devices.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

Packages

 
 
 

Languages