Skip to content

Instantly share code, notes, and snippets.

@timvw
Last active March 3, 2026 09:25
Show Gist options
  • Select an option

  • Save timvw/84ef8768ff876ef6805012b3eb4015b0 to your computer and use it in GitHub Desktop.

Select an option

Save timvw/84ef8768ff876ef6805012b3eb4015b0 to your computer and use it in GitHub Desktop.
On-speaker Spotify boot primer for Bose SoundTouch — fetches token from soundcork, primes at boot, no jq needed

On-Speaker Spotify Boot Primer for Bose SoundTouch

Self-contained boot-time Spotify primer that runs directly on the speaker. No Spotify credentials on the device — it fetches a fresh token from a soundcork server at boot.

No jq, no rootfs modification — just files on persistent storage.

How It Works

Bose SoundTouch speakers run embedded Linux with a persistent writable volume at /mnt/nv. The init script shelby_local (S97) has a built-in hook:

[ -x /mnt/nv/rc.local ] && /mnt/nv/rc.local

This runs before SoundTouch itself (S99), so we background a primer script that waits for the Spotify Connect ZeroConf endpoint (port 8200) to come up, fetches a fresh Spotify token from soundcork, and primes the speaker — all within ~30 seconds of boot.

File Layout

/mnt/nv/
  rc.local                                      boot hook (S97 checks this)
  .profile                                      PATH setup for interactive SSH
  bin/
    spotify-boot-primer                         main script
  BoseApp-Persistence/1/
    spotify-primer.conf                         soundcork credentials (mode 600)
    Sources.xml, Presets.xml, ...               existing speaker data

Scripts live in /mnt/nv/bin/ (added to PATH via .profile), config lives alongside the speaker's own persistence files in /mnt/nv/BoseApp-Persistence/1/.

Speaker Environment

Tested on SoundTouch 20. Other SoundTouch models likely similar.

Item Detail
OS Linux 3.14.43+ ARM (hostname spotty)
Root FS Read-only ubifs (can be remounted rw)
Persistent storage /mnt/nv — writable ubifs, ~24M free
curl 7.50.3 with OpenSSL (HTTPS works)
bash/grep/sed/awk Available via busybox
jq Not available (not needed)
Init SysV, runlevel 5
Production mode Yes — cron is disabled

Prerequisites

  1. SSH access to the speaker:

    ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa root@SPEAKER_IP
    
  2. A running soundcork server with:

    • A linked Spotify account (via the management API OAuth flow)
    • The GET /mgmt/spotify/token endpoint (returns {accessToken, username})
    • Management API credentials (HTTP Basic Auth)

Installation

SSH into the speaker and run:

# 1. Create bin directory
mkdir -p /mnt/nv/bin

# 2. Create the config file with your soundcork connection info
cat > /mnt/nv/BoseApp-Persistence/1/spotify-primer.conf << 'EOF'
SOUNDCORK_URL=https://soundcork.example.com
SOUNDCORK_USER=admin
SOUNDCORK_PASS=secret
EOF
chmod 600 /mnt/nv/BoseApp-Persistence/1/spotify-primer.conf

# 3. Copy spotify-boot-primer to the speaker (see file in this gist)
#    From your local machine:
#    cat spotify-boot-primer | ssh root@SPEAKER_IP "cat > /mnt/nv/bin/spotify-boot-primer"
chmod +x /mnt/nv/bin/spotify-boot-primer

# 4. Create the boot hook
cat > /mnt/nv/rc.local << 'EOF'
#!/bin/bash
/mnt/nv/bin/spotify-boot-primer &
EOF
chmod +x /mnt/nv/rc.local

# 5. Set up PATH for interactive SSH sessions (optional but convenient)
cat > /mnt/nv/.profile << 'EOF'
export PATH="/mnt/nv/bin:$PATH"
EOF

Testing

If activeUser is set but presets still fail, check spotify-primer logs for the activate-speaker step.

# Manual test (speaker must be running):
/mnt/nv/bin/spotify-boot-primer

# Check logs:
logread | grep spotify-primer

# Full test — reboot the speaker:
reboot
# Wait ~30s, then SSH back in and check:
logread | grep spotify-primer
curl -s "http://localhost:8200/zc?action=getInfo" | grep activeUser

Example Boot Log

spotify-primer[1735]: Config loaded (server=https://soundcork.example.com)
spotify-primer[1735]: Waiting for ZeroConf endpoint (max 120s)...
spotify-primer[1735]: ZeroConf endpoint is up (waited 21s)
spotify-primer[1735]: Speaker 'Bose-Woonkamer' has no active Spotify user — priming...
spotify-primer[1735]: Requesting Spotify token from soundcork...
spotify-primer[1735]: Got token for user {username} (BQDUAb0_2h...)
spotify-primer[1735]: addUser accepted (status 101) — verifying...
spotify-primer[1735]: Speaker primed successfully (activeUser={username})

Architecture

Speaker boot
  |
  v
shelby_local (S97) -- [ -x /mnt/nv/rc.local ] && /mnt/nv/rc.local
  |
  v                                 SoundTouch (S99)
rc.local                              |
  |                                    v
  +-- spotify-boot-primer &       port 8200 up
         |                             ^
         +-- wait for port 8200 ------+
         |
         +-- GET soundcork/mgmt/spotify/token
         |     (HTTP Basic Auth)
         |
         +-- POST localhost:8200/zc
         |     action=addUser
         |
         v
      Speaker primed for Spotify

Update Notes

2026-03: Improve preset reliability after boot

  • Added a post-prime activation call to soundcork:
    • POST /mgmt/spotify/activate-speaker?device_name=Bose
  • Reason: addUser (ZeroConf) can set activeUser but still leave the speaker in an idle/unselected Spotify state, causing SoundTouch presets to fail.
  • New behavior:
    1. Prime with ZeroConf (addUser)
    2. Verify activeUser
    3. Trigger activation via soundcork for more reliable preset playback
  • Activation failure is non-fatal: script logs a warning and exits 0 (Spotify Connect priming still succeeded).

Notes

  • The script is idempotent — if the speaker is already primed, it exits immediately
  • No Spotify credentials stored on the speaker — only the soundcork URL and management credentials
  • Soundcork handles all Spotify OAuth token refresh logic
  • The speaker needs network access to reach your soundcork server
  • /mnt/nv holds all user presets/config, so firmware updates should preserve it — but back up your files just in case

Related

#!/bin/bash
# /mnt/nv/rc.local — runs at boot via shelby_local (S97)
# Launches Spotify boot primer in background since SoundTouch starts at S99
/mnt/nv/bin/spotify-boot-primer &
#!/bin/bash
#
# spotify-boot-primer — Self-contained Spotify primer for Bose SoundTouch speakers
#
# Runs at boot (via /mnt/nv/rc.local), waits for the ZeroConf endpoint to
# come up, fetches a fresh Spotify token from a soundcork server, and primes
# the speaker. No Spotify credentials stored on the device.
#
# Only needs: curl, grep, sed (all available on the speaker via busybox).
#
# Install:
# 1. mkdir -p /mnt/nv/bin
# 2. Copy this script to /mnt/nv/bin/spotify-boot-primer
# 3. Create /mnt/nv/BoseApp-Persistence/1/spotify-primer.conf
# 4. Create /mnt/nv/rc.local that backgrounds this script
# 5. chmod +x /mnt/nv/rc.local /mnt/nv/bin/spotify-boot-primer
#
# Config file format (/mnt/nv/BoseApp-Persistence/1/spotify-primer.conf):
# SOUNDCORK_URL=https://soundcork.example.com
# SOUNDCORK_USER=admin
# SOUNDCORK_PASS=secret
#
# Related:
# https://github.com/timvw/soundcork
# https://github.com/gmuth/soundtouch-device-survival
# https://gist.github.com/timvw/84ef8768ff876ef6805012b3eb4015b0
#
set -uo pipefail
CONF="/mnt/nv/BoseApp-Persistence/1/spotify-primer.conf"
LOG_TAG="spotify-primer[$$]"
ZC_URL="http://localhost:8200/zc"
MAX_WAIT=120 # max seconds to wait for port 8200
RETRY_DELAY=3 # seconds between retries
# --- Logging ---
log() {
logger -s -t "$LOG_TAG" -p "$1" "$2"
}
# --- JSON parsing without jq ---
# Extract a string value: echo '{"key":"val"}' | json_str key
json_str() {
grep -o "\"$1\" *: *\"[^\"]*\"" | sed "s/\"$1\" *: *\"//;s/\"$//"
}
# Extract a numeric value: echo '{"key":123}' | json_num key
json_num() {
grep -o "\"$1\" *: *[0-9]*" | sed "s/\"$1\" *: *//"
}
# --- Load config ---
if [ ! -f "$CONF" ]; then
log err "Config not found: $CONF"
exit 1
fi
. "$CONF"
for var in SOUNDCORK_URL SOUNDCORK_USER SOUNDCORK_PASS; do
if [ -z "${!var:-}" ]; then
log err "Missing $var in $CONF"
exit 1
fi
done
log info "Config loaded (server=${SOUNDCORK_URL})"
# --- Wait for ZeroConf endpoint (port 8200) ---
log info "Waiting for ZeroConf endpoint (max ${MAX_WAIT}s)..."
waited=0
while true; do
if curl -sf --max-time 2 "${ZC_URL}?action=getInfo" >/dev/null 2>&1; then
break
fi
waited=$((waited + RETRY_DELAY))
if [ $waited -ge $MAX_WAIT ]; then
log err "ZeroConf endpoint not available after ${MAX_WAIT}s — giving up"
exit 1
fi
sleep $RETRY_DELAY
done
log info "ZeroConf endpoint is up (waited ${waited}s)"
# --- Check if already primed ---
info=$(curl -sf --max-time 5 "${ZC_URL}?action=getInfo" 2>/dev/null)
active_user=$(echo "$info" | json_str activeUser)
device_name=$(echo "$info" | json_str remoteName)
if [ -n "$active_user" ]; then
log info "Already primed (device=$device_name, activeUser=$active_user) — nothing to do"
exit 0
fi
log info "Speaker '$device_name' has no active Spotify user — priming..."
# --- Get token from soundcork server ---
log info "Requesting Spotify token from soundcork..."
token_response=$(curl -sf --max-time 15 \
-u "${SOUNDCORK_USER}:${SOUNDCORK_PASS}" \
"${SOUNDCORK_URL}/mgmt/spotify/token" \
2>&1)
if [ $? -ne 0 ] || [ -z "$token_response" ]; then
log err "Failed to get token from soundcork (is the server reachable?)"
exit 1
fi
access_token=$(echo "$token_response" | json_str accessToken)
user=$(echo "$token_response" | json_str username)
if [ -z "$access_token" ] || [ -z "$user" ]; then
error_msg=$(echo "$token_response" | json_str detail)
log err "Soundcork returned error: ${error_msg:-no token/username in response}"
exit 1
fi
log info "Got token for user $user (${access_token:0:10}...)"
# --- Prime the speaker ---
result=$(curl -sf --max-time 10 -X POST "$ZC_URL" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "action=addUser&userName=${user}&blob=${access_token}&clientKey=&tokenType=accesstoken" \
2>&1)
status=$(echo "$result" | json_num status)
status_str=$(echo "$result" | json_str statusString)
if [ "$status" != "101" ]; then
log err "addUser failed: status=$status ($status_str)"
exit 1
fi
# --- Verify (retry — speaker needs a few seconds after cold boot) ---
log info "addUser accepted (status 101) — verifying..."
primed=false
for i in 1 2 3 4 5; do
sleep $((i * 2))
active_user=$(curl -sf --max-time 5 "${ZC_URL}?action=getInfo" | json_str activeUser)
if [ -n "$active_user" ]; then
log info "Speaker primed successfully (activeUser=$active_user)"
primed=true
break
fi
done
if [ "$primed" != "true" ]; then
log warning "Speaker accepted addUser but activeUser still empty after 30s"
exit 1
fi
# --- Activate speaker via Spotify Web API ---
# ZeroConf priming registers the speaker with Spotify but leaves it idle.
# The Spotify desktop app activates the streaming session by calling
# PUT /v1/me/player — we replicate that via soundcork so that SoundTouch
# presets can initiate Spotify playback without manual intervention.
log info "Activating speaker streaming session via soundcork..."
sleep 5 # give the speaker time to register with Spotify's servers
activate_response=$(curl -sf --max-time 60 \
-X POST \
-u "${SOUNDCORK_USER}:${SOUNDCORK_PASS}" \
"${SOUNDCORK_URL}/mgmt/spotify/activate-speaker?device_name=Bose" \
2>&1)
if [ $? -ne 0 ] || [ -z "$activate_response" ]; then
log warning "Speaker activation failed (presets may not work until Spotify app connects)"
# Non-fatal: ZeroConf priming succeeded, Spotify Connect works.
# Only SoundTouch preset playback is affected.
exit 0
fi
log info "Speaker activated: ${activate_response}"
exit 0
#!/usr/bin/env bash
#
# spotify-prime-speaker — Prime a Bose SoundTouch speaker for Spotify playback
#
# Activates Spotify on a SoundTouch speaker by sending an access token
# via the Spotify Connect ZeroConf endpoint (port 8200). This is the
# same mechanism the Spotify desktop app uses internally.
#
# Works standalone — no soundcork, ueberboese, or other server required.
#
# Requirements: curl, jq
#
# Usage:
# ./spotify-prime-speaker SPEAKER_IP ACCESS_TOKEN
#
# Example:
# ./spotify-prime-speaker 192.168.1.143 BQDj...your_token...
#
# How to get an access token:
# - Spotify Developer Console: https://developer.spotify.com
# (create an app, use the "Get Token" button)
# - Via soundcork management API: POST /mgmt/spotify/auth/init
# - Via ueberboese management API: POST /mgmt/spotify/init
# - Any Spotify OAuth Authorization Code flow with user-read-email scope
#
# Notes:
# - Access tokens expire after 1 hour (3600 seconds)
# - The speaker must be on the same network and reachable on port 8200
# - After priming, Spotify presets on the speaker should work immediately
# - Re-run after each speaker reboot (or use a server like soundcork
# to automate this)
#
# How it works:
# The Bose SoundTouch speaker exposes a Spotify Connect ZeroConf API
# on port 8200. By sending an addUser request with a valid Spotify
# access token, the speaker activates its built-in Spotify Connect
# client. No encryption is needed — the token is sent as plain text,
# exactly like the Spotify desktop app does it.
#
# Related:
# - https://github.com/deborahgu/soundcork (replacement Bose cloud server)
# - https://github.com/deborahgu/soundcork/pull/185 (Spotify support PR)
# - https://github.com/deborahgu/soundcork/issues/107 (Spotify presets issue)
set -euo pipefail
# --- Argument parsing ---
if [ $# -lt 2 ]; then
echo "Usage: $0 SPEAKER_IP ACCESS_TOKEN"
echo ""
echo "Prime a Bose SoundTouch speaker for Spotify playback."
echo ""
echo "Arguments:"
echo " SPEAKER_IP IP address of the SoundTouch speaker"
echo " ACCESS_TOKEN Spotify access token (starts with BQ...)"
echo ""
echo "Get a token at https://developer.spotify.com or via a server's OAuth flow."
exit 1
fi
SPEAKER_IP="$1"
TOKEN="$2"
ZC_URL="http://${SPEAKER_IP}:8200/zc"
# --- Dependency check ---
for cmd in curl jq; do
if ! command -v "$cmd" &>/dev/null; then
echo "Error: $cmd is required but not installed." >&2
exit 1
fi
done
# --- Step 1: Discover Spotify username from token ---
echo "Discovering Spotify user from token..."
ME_RESPONSE=$(curl -sf -H "Authorization: Bearer ${TOKEN}" \
https://api.spotify.com/v1/me 2>&1) || {
echo "Error: Failed to call Spotify /me API. Is the token valid?" >&2
echo " (tokens expire after 1 hour)" >&2
exit 1
}
USER=$(echo "$ME_RESPONSE" | jq -r '.id // empty')
if [ -z "$USER" ]; then
echo "Error: Could not extract user ID from Spotify response." >&2
echo "$ME_RESPONSE" >&2
exit 1
fi
echo " Spotify user: $USER"
# --- Step 2: Check current speaker status ---
echo "Checking speaker at ${SPEAKER_IP}:8200..."
INFO=$(curl -sf "${ZC_URL}?action=getInfo" 2>&1) || {
echo "Error: Could not reach speaker at ${SPEAKER_IP}:8200." >&2
echo " Is the speaker on and on the same network?" >&2
exit 1
}
ACTIVE=$(echo "$INFO" | jq -r '.activeUser // empty')
DEVICE_NAME=$(echo "$INFO" | jq -r '.remoteName // empty')
if [ -n "$DEVICE_NAME" ]; then
echo " Speaker: $DEVICE_NAME"
fi
if [ -n "$ACTIVE" ]; then
echo " Already primed (activeUser=$ACTIVE)"
echo "Done — speaker is ready for Spotify playback."
exit 0
fi
echo " No active Spotify user — priming now..."
# --- Step 3: Send addUser ---
RESULT=$(curl -sf -X POST "${ZC_URL}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "action=addUser&userName=${USER}&blob=${TOKEN}&clientKey=&tokenType=accesstoken" \
2>&1) || {
echo "Error: addUser request failed." >&2
exit 1
}
STATUS=$(echo "$RESULT" | jq -r '.status // -1')
STATUS_STR=$(echo "$RESULT" | jq -r '.statusString // empty')
if [ "$STATUS" != "101" ]; then
echo "Error: Speaker returned status $STATUS ($STATUS_STR)" >&2
echo "$RESULT" | jq . >&2
exit 1
fi
echo " Speaker accepted the token (status 101)."
# --- Step 4: Verify ---
echo " Verifying (waiting 2 seconds)..."
sleep 2
ACTIVE=$(curl -sf "${ZC_URL}?action=getInfo" | jq -r '.activeUser // empty')
if [ -n "$ACTIVE" ]; then
echo "Done — speaker primed for Spotify (activeUser=$ACTIVE)"
else
echo "Warning: Speaker returned 101 but activeUser is still empty."
echo " The speaker may need more time. Try pressing a Spotify preset."
exit 1
fi
# /mnt/nv/spotify-primer.conf — soundcork connection for boot primer
# The speaker fetches a fresh Spotify token from soundcork at boot.
# No Spotify credentials needed on the device.
SOUNDCORK_URL=https://soundcork.example.com
SOUNDCORK_USER=admin
SOUNDCORK_PASS=secret
@timvw
Copy link
Author

timvw commented Feb 18, 2026

Good point about jq! I SSH'd into my SoundTouch 20 and explored what's available:

  • curl 7.50.3 with OpenSSL — HTTPS works fine
  • bash, grep, sed, awk — all present (via busybox)
  • No jq — but grep -o + sed can parse the JSON we need
  • Root filesystem is read-only (ubifs), but /mnt/nv is a persistent writable volume (24.6M free, survives reboots)

And the best part: shelby_local (init.d script at S97) already has a hook:

[ -x /mnt/nv/rc.local ] && /mnt/nv/rc.local

So we can drop a script in /mnt/nv/rc.local and it runs at boot — no rootfs modification needed. SoundTouch itself starts at S99, so the script needs to background and wait for port 8200 to come up before priming.

I'm going to try building a self-contained boot primer that:

  1. Reads stored Spotify credentials (client_id, client_secret, refresh_token) from /mnt/nv/
  2. Refreshes the access token via Spotify API
  3. Primes localhost:8200 via the ZeroConf addUser endpoint

Will report back whether it works. This could be a nice addition to the survival repo if it does.

@timvw
Copy link
Author

timvw commented Feb 18, 2026

Update: it works! Built and tested a self-contained boot primer that runs directly on the speaker. Here's the setup:

Three files on /mnt/nv (persistent, writable, survives reboots):

  1. /mnt/nv/rc.local — Boot hook (shelby_local at S97 already checks for this)
  2. /mnt/nv/spotify-boot-primer — Main script
  3. /mnt/nv/spotify-primer.conf — Credentials (client_id, client_secret, refresh_token), mode 600

Boot sequence:

shelby_local (S97) → rc.local → backgrounds spotify-boot-primer
  → waits ~18s for SoundTouch (S99) to start port 8200
  → refreshes access token via Spotify API (curl + HTTPS works fine)
  → gets username from /v1/me
  → addUser to localhost:8200
  → speaker primed

From the actual boot log:

spotify-primer[1766]: ZeroConf endpoint is up (waited 18s)
spotify-primer[1766]: Speaker 'Bose-Woonkamer' has no active Spotify user — priming...
spotify-primer[1766]: Refreshing Spotify token...
spotify-primer[1766]: Got access token (BQA0ycT_wR...)
spotify-primer[1766]: Spotify user: {redacted}

Key insights for anyone trying this:

  • No jq needed — grep -o + sed handles the JSON parsing
  • curl 7.50.3 on the speaker has full OpenSSL/HTTPS support
  • The shelby_local init script has a built-in hook: [ -x /mnt/nv/rc.local ] && /mnt/nv/rc.local
  • SoundTouch starts at S99, after shelby_local at S97, so the script needs to wait in a retry loop for port 8200
  • You need a Spotify refresh_token (from an OAuth flow) + client_id + client_secret stored on the speaker

Happy to share the full script for the survival repo if useful!

@timvw
Copy link
Author

timvw commented Feb 19, 2026

Done! Reorganized the layout per your suggestions:

/mnt/nv/
  rc.local                                      boot hook (unchanged location)
  .profile                                      PATH="/mnt/nv/bin:$PATH"
  bin/
    spotify-boot-primer                         main script
  BoseApp-Persistence/1/
    spotify-primer.conf                         soundcork credentials (mode 600)

Scripts in /mnt/nv/bin/, config alongside the speaker's own persistence files in .../1/. Tested end-to-end: reset active Spotify user, rebooted, primer ran from the new paths and primed successfully (~25s after boot).

Gist files are updated to reflect the new layout.

@gmuth
Copy link

gmuth commented Feb 19, 2026

Okay, does this now work without soundcork? I am a little bit confused because Install.md still says "fetches a token from soundcork"

@timvw
Copy link
Author

timvw commented Feb 20, 2026

No, it still requires (my forked) soundcork server — the speaker doesn't do the Spotify token exchange itself. It just fetches a ready-to-use access token from soundcork's management API (GET /mgmt/spotify/token), which handles all the OAuth refresh logic server-side.

The config on the speaker (spotify-primer.conf) only has the soundcork URL and management credentials — no Spotify client_id/secret/refresh_token on the device. I am currently thinking about another authentication/identification mechanism for speakers because I do not want to store credentials (at all) on each speaker...

@gesellix
Copy link

@timvw if I see correctly you already added the Spotify integration to your Bose-SoundTouch fork. Is that ready to give it a try (feel free to create a pull request)? I would then also like to check the install script on my device.

@gesellix
Copy link

I'm not sure if I understand the requirement of the device-local script. In my understanding Soundcork or other Bose-replacement services could prime a speaker by calling the device's /zc endpoint. Is there anything the speaker has to manage themself? In other words: how is the relationship between the scripts spotify-prime-speaker and spotify-boot-primer?

@gmuth
Copy link

gmuth commented Feb 21, 2026

Agree, I also expected one implementation only: A Soundcork add on or some other tool like a script.
What can soundcork (with add on) do a script couldn't do? Or what could a script do soundcork could't also do?

@timvw
Copy link
Author

timvw commented Feb 21, 2026

So, it started with my asking:

  • How does it work for the Spotify app?
  • When I noticed that it sends the token i figured I could set up a service to provision (and refresh) the token every 45 minutes..

Then I learned about the (builtin) token refresh in the speaker firmware so only when the device boots, we actually need to post/deliver a token on the Spotify Connect endpoint of the speaker..

I also realized that this requires that the backend server can connect to each speaker..
And that the first 60-120 seconds after a boot, the spotify presets do not work...

By running the script (during startup of the device), there is no need for the server to keep track of all devices + the spotify presets work immediately after booting..

@gesellix
Copy link

Wouldn't the speaker reach out to the Bose servers on boot? This would be the chance for Soundcork to perform the Spotify setup. I'm going to check that assumption, but I guess that's how it would work the official way.

@gesellix
Copy link

The speaker notifies Bose via POST /streaming/support/power_on with its ip address. This would suffice to prime the speaker only once and then rely on its built-in token refresh. Only when Soundcork is deployed outside the speaker's network the self-priming is actually necessary. I'm not entirly sure how the official Bose server primes the speaker (maybe with a meaningful response on .../power_on?).
I think both approaches (device-local boot primer and server side primer) have their advantages. I'm personally going to start with a server side variant and observer how reliable that is.

@timvw
Copy link
Author

timvw commented Feb 22, 2026

Can't remember but after boot or power down, simply starting by pressing a spotify preset, did not work.. that's why I prefer the on-device script.. (+ no complexity of having a backend that needs to connect to the speaker(s)).

Anyway, we're all learning here.. Let's keep sharing experiences :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment