services: ytplayer: build: . restart: unless-stopped volumes: # libsql DB file persists across container rebuilds - ytplayer-data:/app/data environment: PORT: "3000" DB_PATH: "/app/data/ytplayer.db" APP_VERSION: "1.0.0" # Unlocks /admin (API tokens, lyric/chapter history + restore). Set it in # Dokploy's Environment tab — never commit it. Unset = admin disabled. ADMIN_PASSWORD: "${ADMIN_PASSWORD:-}" # Phone remote: "1" = a phone may only pair with a screen on the same # network (same public IP as seen by the server). Off by default. REMOTE_SAME_NETWORK: "${REMOTE_SAME_NETWORK:-0}" # Shared secret the lyrics-worker uses to list songs and upload lyrics. # Set in Dokploy's Environment tab (same value feeds both services). LYRICS_WORKER_TOKEN: "${LYRICS_WORKER_TOKEN:-}" # Optional: force yt-dlp search instead of InnerTube API # SEARCH_INNERTUBE: "0" # force yt-dlp search # Optional: override yt-dlp binary path if you mount a custom one # YTDLP_PATH: "/usr/local/bin/yt-dlp" # Server media cache (server/media-cache.js) — defaults shown. # MEDIA_DIR: "/app/data/media" # on the ytplayer-data volume # MEDIA_CACHE_MAX_BYTES: "10737418240" # 10 GiB, LRU eviction past this # MEDIA_MIN_FREE_BYTES: "5368709120" # skip caching below 5 GiB free disk # MEDIA_AUTO_MAX_SECONDS: "3600" # longest video auto-cached on play # MEDIA_TRANSCODE: "1" # 0 disables the compression lane # MEDIA_CODEC: "hevc" # hevc | h264 # MEDIA_CRF: "28" # MEDIA_PRESET: "medium" # MEDIA_THREADS: "2" # MEDIA_OPT_MAX_SECONDS: "3600" # don't re-encode videos longer than this healthcheck: test: ["CMD", "curl", "-sf", "http://localhost:3000/api/version"] interval: 30s timeout: 5s retries: 3 start_period: 15s networks: - dokploy-network - lyrics labels: - "traefik.enable=true" - "traefik.http.routers.ytplayer-http.rule=Host(`worship.hesed.sbs`)" - "traefik.http.routers.ytplayer-http.entrypoints=web" - "traefik.http.routers.ytplayer-http.middlewares=redirect-to-https" - "traefik.http.routers.ytplayer-https.rule=Host(`worship.hesed.sbs`)" - "traefik.http.routers.ytplayer-https.entrypoints=websecure" - "traefik.http.routers.ytplayer-https.tls.certresolver=letsencrypt" - "traefik.http.services.ytplayer-svc.loadbalancer.server.port=3000" # Transcribes saved songs that have no lyrics yet, one at a time, with # faster-whisper on CPU (no API keys, no credits). Separate container so it # never competes with playback/downloads: capped CPU + memory, low priority, # and it fetches audio from the ytplayer service over the private network. lyrics-worker: build: ./scripts/lyrics restart: unless-stopped depends_on: - ytplayer environment: YTP_BASE: "http://ytplayer:3000" YTP_TOKEN: "${LYRICS_WORKER_TOKEN:-}" WHISPER_MODEL: "large-v3-turbo" # ~1.6 GB download on first start WHISPER_THREADS: "2" WATCH_SECONDS: "300" volumes: - lyrics-models:/models - lyrics-state:/data cpus: "2" mem_limit: 3g networks: - lyrics volumes: ytplayer-data: driver: local lyrics-models: driver: local lyrics-state: driver: local networks: dokploy-network: external: true lyrics: driver: bridge