Spotify integration added

This commit is contained in:
2026-05-17 13:35:34 +02:00
parent 9a9275dae5
commit 4d53efc9e4
16 changed files with 1890 additions and 82 deletions
+39 -24
View File
@@ -1,46 +1,61 @@
FROM debian:bookworm-slim
FROM python:3.13-slim
# Install Mopidy from the official repo + GStreamer + plugins
# ── System dependencies ───────────────────────────────────────────────────────
# GStreamer runtime + GObject Introspection typelibs needed at runtime.
# libgirepository + libglib dev headers + gcc needed to compile PyGObject.
# gosu: used by entrypoint to drop from root → mopidy after fixing permissions.
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
curl gnupg ca-certificates \
# Add Mopidy apt repo
&& curl -1sLf 'https://dl.cloudsmith.io/public/mopidy/mopidy/setup.deb.sh' \
| bash \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
mopidy \
# GStreamer pipeline (needed for filesink output to FIFO)
# GStreamer runtime
gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-ugly \
gstreamer1.0-tools \
# Python / pip for Mopidy extensions
python3-pip \
python3-gst-1.0 \
libgstreamer1.0-0 \
libgstreamer-plugins-base1.0-0 \
# GObject Introspection typelibs (used by PyGObject at runtime)
gir1.2-gstreamer-1.0 \
gir1.2-gst-plugins-base-1.0 \
# Build deps for PyGObject (can't be removed — runtime .so links against them)
libgirepository-2.0-dev \
libglib2.0-dev \
libcairo2-dev \
gcc \
pkg-config \
# Misc
curl \
gettext-base \
gosu \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Mopidy Python extensions
# Add or remove plugins to suit your setup.
RUN pip3 install --break-system-packages \
mopidy-local \
mopidy-mpd \
mopidy-youtube \
yt-dlp
# ── Python packages ───────────────────────────────────────────────────────────
# PyGObject must be compiled first so pip can resolve mopidy's gst dependency.
# setuptools provides pkg_resources (no longer bundled in Python 3.13).
# mopidy-spotify 5.x uses the Spotify Web API (no libspotify C extension).
RUN pip install --no-cache-dir PyGObject \
&& pip install --no-cache-dir \
"setuptools<72" \
mopidy \
mopidy-local \
mopidy-mpd \
mopidy-youtube \
"mopidy-spotify>=5.0.0" \
yt-dlp
# Mopidy runs as the mopidy user (created by the package)
RUN mkdir -p /var/lib/mopidy /config \
# ── Runtime user ──────────────────────────────────────────────────────────────
# Entrypoint runs as root, fixes volume ownership, then execs as mopidy via gosu.
RUN groupadd -r audio 2>/dev/null || true \
&& useradd -r -g audio -d /var/lib/mopidy -s /sbin/nologin mopidy \
&& mkdir -p /var/lib/mopidy /config \
&& chown -R mopidy:audio /var/lib/mopidy /config
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
EXPOSE 6680
USER mopidy
HEALTHCHECK --interval=20s --timeout=5s --start-period=15s \
HEALTHCHECK --interval=20s --timeout=5s --start-period=30s \
CMD curl -sf http://localhost:6680/mopidy/rpc \
-d '{"jsonrpc":"2.0","id":1,"method":"core.get_version"}' \
-H 'Content-Type: application/json' | grep -q '"id": 1' || exit 1
+18 -3
View File
@@ -1,8 +1,11 @@
#!/usr/bin/env bash
# Mopidy entrypoint
# Ensures the audio FIFO exists (Snapserver must open it too, ordering matters)
# Mopidy entrypoint — runs as root, fixes permissions, then drops to mopidy user.
set -e
# Fix ownership of the data volume (may be stale from a previous container build
# with a different mopidy uid, or from Docker initialising a new volume as root).
chown -R mopidy:audio /var/lib/mopidy 2>/dev/null || true
FIFO=/audio/mopidy.fifo
# Create FIFO if missing (init-pipes.sh should have done this, but be safe)
@@ -14,9 +17,21 @@ fi
echo "[mopidy] FIFO ready: $FIFO"
# Load Spotify credentials from shared config volume (written by the settings UI).
# Values here take precedence over env vars from docker-compose / .env.
_SPOTIFY_JSON=/config/shared/spotify.json
if [[ -f "$_SPOTIFY_JSON" ]]; then
_ID=$(python3 -c "import json; d=json.load(open('$_SPOTIFY_JSON')); print(d.get('client_id',''))" 2>/dev/null || true)
_SEC=$(python3 -c "import json; d=json.load(open('$_SPOTIFY_JSON')); print(d.get('client_secret',''))" 2>/dev/null || true)
[[ -n "$_ID" ]] && export SPOTIFY_CLIENT_ID="$_ID"
[[ -n "$_SEC" ]] && export SPOTIFY_CLIENT_SECRET="$_SEC"
echo "[mopidy] Spotify credentials loaded from shared config"
fi
# Expand only our own vars — leave Mopidy's $XDG_* vars untouched
envsubst '${SPOTIFY_CLIENT_ID}${SPOTIFY_CLIENT_SECRET}${SNAPSERVER_HOST}${BEETS_HOST}' \
< /config/mopidy.conf > /tmp/mopidy.conf
echo "[mopidy] Config expanded from template"
exec "$@"
# Drop from root → mopidy user for the actual Mopidy process
exec gosu mopidy "$@"
+3 -5
View File
@@ -131,11 +131,9 @@ enabled = true
hostname = 0.0.0.0
connection_timeout = 120
#[spotify]
# mopidy-spotify requires pyspotify which has no arm64 build (libspotify was
# discontinued by Spotify). Spotify playback is handled via librespot/snapserver.
#client_id = ${SPOTIFY_CLIENT_ID}
#client_secret = ${SPOTIFY_CLIENT_SECRET}
[spotify]
client_id = ${SPOTIFY_CLIENT_ID}
client_secret = ${SPOTIFY_CLIENT_SECRET}
[muse]
enabled = true