refactor: rename soundtouch-web to soundtouch-player (transitional alias) (refs #451)

The web player is intrinsically LAN-resident: it reaches speakers directly
and only delegates cloud-only features (e.g. TTS) to a possibly-remote
AfterTouch service via --service-url. That is exactly what a cloud-hosted
soundtouch-service cannot do, so the standalone player binary stays useful
and is not being deprecated. Rename it to state its purpose, with a
transition window so existing downloads keep working.

- cmd/soundtouch-web -> cmd/soundtouch-player; CLI name is now
  soundtouch-player. When the binary is invoked under its old name it prints
  a one-line rename notice (filepath.Base(os.Args[0])).
- Build/release both names from the same source: Makefile (build-player +
  build-web alias, dev-player* targets), Dockerfile (soundtouch-player image
  + transitional soundtouch-web image), release.yml and ci.yml (player +
  web artifacts, checksums, Docker images; release notes announce the
  rename). The soundtouch-web binary, image, and install script remain a
  transitional alias to be dropped in a future release (which will break
  stale fetch scripts and nudge users to the release notes).
- scripts/raspberry-pi/install-player.sh is canonical; install-web.sh keeps
  working but warns.
- Sweep docs, code comments, user-facing strings, and assets
  (soundtouch-web-ui.png, soundtouch-web-tunein.png, soundtouch-web-roadmap.md)
  to soundtouch-player; README documents the rename and why the player
  remains separate from the embedded /app.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tobias Gesellchen
2026-06-07 16:33:39 +02:00
co-authored by Claude Opus 4.8
parent 2657e5411c
commit bd62fd6658
47 changed files with 639 additions and 189 deletions
+3 -3
View File
@@ -665,7 +665,7 @@ soundtouch --device 192.0.2.100 preset 1
soundtouch interactive
# Web interface
soundtouch-webapp --port 8080
soundtouch-playerapp --port 8080
```
### JavaScript/WASM Usage
@@ -727,10 +727,10 @@ client.startEventStream((event) => {
./soundtouch-linux-amd64 --device IP play
# Web Application (embedded assets)
./soundtouch-webapp-linux-amd64 --port 8080
./soundtouch-playerapp-linux-amd64 --port 8080
# Docker
docker run -p 8080:8080 soundtouch-webapp
docker run -p 8080:8080 soundtouch-playerapp
```
### Development Environment
+1 -1
View File
@@ -35,7 +35,7 @@ layout: hextra-home
>}}
{{< hextra/feature-card
title="Music Browsing"
subtitle="TuneIn, Internet Radio, RadioBrowser, and Spotify via soundtouch-web and soundtouch-cli."
subtitle="TuneIn, Internet Radio, RadioBrowser, and Spotify via soundtouch-player and soundtouch-cli."
icon="speakerphone"
>}}
{{< hextra/feature-card
+6 -6
View File
@@ -46,16 +46,16 @@ selection behave the same as before.
Your six preset buttons work. AfterTouch stores preset bindings locally and serves them
back to the speaker on request. You can also **save new presets** — via the API,
via `soundtouch-cli`, or through the soundtouch-web UI.
via `soundtouch-cli`, or through the soundtouch-player UI.
### ST-10 stereo pairing
**SoundTouch 10 stereo pairs** (and other ST pairing configurations) are supported
end-to-end: creation, management, and playback routing all go through AfterTouch.
### soundtouch-web — browser UI
### soundtouch-player — browser UI
**soundtouch-web** is an early-stage but functional browser UI bundled with AfterTouch.
**soundtouch-player** is an early-stage but functional browser UI bundled with AfterTouch.
It gives you:
- TuneIn and RadioBrowser browsing and playback
@@ -65,7 +65,7 @@ It gives you:
It runs as part of the AfterTouch service — no separate install needed.
![soundtouch-web UI showing Spotify playback, presets, sources, and zone management](/images/blog/soundtouch-web-ui.png)
![soundtouch-player UI showing Spotify playback, presets, sources, and zone management](/images/blog/soundtouch-player-ui.png)
### Automation with soundtouch-cli
@@ -110,9 +110,9 @@ right places to start.
## What's next
The soundtouch-web UI will gain richer preset management — browsing, editing, and
The soundtouch-player UI will gain richer preset management — browsing, editing, and
reordering presets directly from the browser. Longer term, merging
`soundtouch-service` and `soundtouch-web` into a single binary is on the table,
`soundtouch-service` and `soundtouch-player` into a single binary is on the table,
which would simplify deployment to a single process with no extra flags.
This blog will be updated monthly — or whenever something significant ships.
@@ -129,8 +129,8 @@ A Java-based middleware that hosts the original Bose Stockholm frontend (extract
---
### 8. jaas666/bose-soundtouch-web-api (Reference)
**[github.com/jaas666/bose-soundtouch-web-api](https://github.com/jaas666/bose-soundtouch-web-api)**
### 8. jaas666/bose-soundtouch-player-api (Reference)
**[github.com/jaas666/bose-soundtouch-player-api](https://github.com/jaas666/bose-soundtouch-player-api)**
Community-maintained Markdown conversion of the official Bose SoundTouch Web API PDF (v1.0, January 7, 2026). Useful as a developer reference. Not a deployable tool.
@@ -198,7 +198,7 @@ The web UI is already fully responsive — it has Bootstrap grid columns, `@medi
### Priority 2 — RadioBrowser as a first-class provider
AfterTouch can proxy and play any stream URL, but there is no built-in station search. OpenCloudTouch's RadioBrowser integration is the reference. Tasks:
- Wire the [RadioBrowser API](https://www.radio-browser.info/) into the `soundtouch-web` web UI as a browsable/searchable source.
- Wire the [RadioBrowser API](https://www.radio-browser.info/) into the `soundtouch-player` web UI as a browsable/searchable source.
- Make discovered stations directly presetable to hardware buttons.
- This is the most common replacement for TuneIn for users who listened to internet radio via presets.
@@ -242,7 +242,7 @@ These exist in soundcork but are deliberate architectural choices in AfterTouch,
| Area | soundcork | AfterTouch |
|--------------------------|---------------------------------------|-----------------------------------------------------------|
| Web UI | FastAPI + Jinja2 miniapp and admin UI | Separate `soundtouch-web` component (Go + plain HTML/JS) |
| Web UI | FastAPI + Jinja2 miniapp and admin UI | Separate `soundtouch-player` component (Go + plain HTML/JS) |
| Direct device management | SSH/SCP access into speakers | HTTP API only; no SSH |
| Device discovery client | Python `upnpclient` library | mDNS + UPnP in Go, with dedicated DNS interception server |
| Token delivery | Push (ZeroConf priming to port 8200) | Pull (device calls back to fetch) |
@@ -288,7 +288,7 @@ Bose's decision to release API documentation rather than simply shutting down is
- [Bose SoundTouch Plus (Home Assistant component)](https://github.com/thlucas1/homeassistantcomponent_soundtouchplus) — comprehensive HA integration by Todd Lucas, extensive API wiki
- [Bose SoundTouch Hook](https://github.com/CodeFinder2/bose-soundtouch-hook) — `LD_PRELOAD`-based reverse engineering framework used by AfterTouch for protocol research
- [Bose SoundTouch Web API (community Markdown)](https://github.com/jaas666/bose-soundtouch-web-api) — official API PDF converted to Markdown
- [Bose SoundTouch Web API (community Markdown)](https://github.com/jaas666/bose-soundtouch-player-api) — official API PDF converted to Markdown
- [Bose Wiki — SoundTouch App Alternatives](https://bose.fandom.com/wiki/SoundTouch_app_alternatives) — community-maintained living list of workarounds and projects
- [Reddit megathread — Bose alternatives](https://www.reddit.com/r/bose) — ongoing community discussion
- [Radio Browser](https://www.radio-browser.info/) — the free, community-maintained internet radio directory used as a TuneIn replacement
@@ -7,11 +7,11 @@ sidebar:
## Overview
SoundTouch devices support 6 preset slots that can store your favorite content for instant access. This guide shows you how to manage presets using the soundtouch-web UI, the CLI, or the Go library.
SoundTouch devices support 6 preset slots that can store your favorite content for instant access. This guide shows you how to manage presets using the soundtouch-player UI, the CLI, or the Go library.
## Via soundtouch-web (browser UI)
## Via soundtouch-player (browser UI)
**soundtouch-web** (default port **8080**) is the easiest way to manage presets without the command line. Two save paths are available whenever content is playing:
**soundtouch-player** (default port **8080**) is the easiest way to manage presets without the command line. Two save paths are available whenever content is playing:
### ★ Star button — save from Now Playing
@@ -1,9 +1,9 @@
---
title: "soundtouch-web: remaining features"
title: "soundtouch-player: remaining features"
sidebar:
exclude: true
---
Four features complete the parity gap between soundtouch-web and the Stockholm
Four features complete the parity gap between soundtouch-player and the Stockholm
app's local-control functionality. Everything else in Stockholm (OAuth flows,
setup wizard, service account linking, onboarding, analytics) is cloud
infrastructure that is either shut down or already handled by soundtouch-service.
@@ -48,7 +48,7 @@ func (c *Client) Seek(positionSeconds int) error {
> **Note:** This section is about the speaker's **built-in** `/favorites` API —
> a separate concept from the 6 preset slots. Preset-slot saving (★ star /
> **+** button) is already shipped; the native Favorites API is not yet
> surfaced in soundtouch-web.
> surfaced in soundtouch-player.
Mark or unmark the currently playing track as a device favourite directly from
the Now Playing card. Unlike presets (maximum 6, numbered slots), the device
@@ -103,7 +103,7 @@ rename and network/firmware info.
## 4. Render stereo pairs as a single device
Today soundtouch-web shows the two halves of a stereo pair (formed via
Today soundtouch-player shows the two halves of a stereo pair (formed via
`/addGroup` — see issue #252) as independent entries in the device list. The
Bose app collapsed a paired ST10 set into one "L+R" entry; restoring that
presentation closes the perception gap BirdyBA flagged at
@@ -139,7 +139,7 @@ end-to-end — `pkg/client` group endpoints + `cmd/soundtouch-cli/cmd_group.go`,
covered by tests in `cmd/soundtouch-cli/cmd_group_test.go` and exercisable
against the fake speaker's group routes
(`pkg/service/testing/fakespeaker/fakespeaker.go`). This task is purely about
presentation in soundtouch-web's device list — no protocol work required.
presentation in soundtouch-player's device list — no protocol work required.
---
@@ -2,17 +2,17 @@
title: "API Route Layout and Refactoring Plan"
---
> **Tracking issue:** [#451 "Merge soundtouch-web into soundtouch-service"](https://github.com/gesellix/Bose-SoundTouch/issues/451).
> **Tracking issue:** [#451 "Merge soundtouch-player into soundtouch-service"](https://github.com/gesellix/Bose-SoundTouch/issues/451).
> This document is the architectural reference for the staged API refactoring
> that precedes (and enables) that merge.
## Why this exists
`soundtouch-service` and `soundtouch-web` are two binaries with two routers.
`soundtouch-service` and `soundtouch-player` are two binaries with two routers.
We want to:
1. Restructure our own routes into a layout that can stay stable.
2. Eventually fold `soundtouch-web` into `soundtouch-service` (one binary).
2. Eventually fold `soundtouch-player` into `soundtouch-service` (one binary).
3. Stop leaking frontend (SPA) routes into the backend API.
4. Make **cloud / remote-host a first-class, clean deployment**, not just LAN /
on-device. This is a primary motivation: we consolidate the API *in a way
@@ -34,7 +34,7 @@ Classify by client audience, then by what pins the path:
| **(1a) Frozen, firmware-pinned** | Speaker firmware | No, ever. The path is hardcoded in the speaker (or relative to a base it fetches from us). |
| **(1b) Frozen, externally-pinned** | OAuth providers (Spotify/Amazon) | Only with provider re-registration + device re-priming. Treat as frozen unless that cost is paid deliberately. |
| **(2) Service-internal** | The admin/setup UI | Yes, freely. These are ours. |
| **(3) Web/control** | The control UI (soundtouch-web) | Yes, freely. |
| **(3) Web/control** | The control UI (soundtouch-player) | Yes, freely. |
| **(4) Frontend (SPA)** | Browser, client-side routing | Should not be enumerated in the backend at all (see `/app/*` below). |
| **(Infra)** | Humans, monitoring, the SPA shell | Conventionally stable; collision-prone at merge time. |
@@ -103,7 +103,7 @@ Grouped by prefix. The authoritative enumerated list is the router golden file
| `/web/*` (`HandleWeb`) | (4) frontend | Browser (admin SPA) | Yes; already the clean catch-all pattern |
| `/`<br>`/docs/*`<br>`/favicon.ico`<br>`/health` | (Infra) | Humans / monitoring | Keep stable by convention |
## Web routes (`soundtouch-web`)
## Web routes (`soundtouch-player`)
Defined in `pkg/service/soundtouchweb/mount.go`. Not currently mounted inside
the service; it is a separate binary.
@@ -166,7 +166,7 @@ deployments:
- **Speaker-direct (control plane):** the service opens a connection *to* the
speaker's local API (`:8090`) right now. Discovery, migration, reboot,
test-connection, peer-probe, and the entire `soundtouch-web`
test-connection, peer-probe, and the entire `soundtouch-player`
control/zone/volume/key/TTS-to-speaker surface. These only work where the host
shares the LAN with the speaker. **In a cloud deployment they are dead weight**,
and any UI that shows them is misleading.
@@ -386,7 +386,7 @@ diagnostic export, not leak into shared bundles.
# auth/authz middleware applies per group, not per route):
/api/setup/* (today: /setup/*) -> admin tier: auth required
/api/mgmt/* (today: /mgmt/*, no callbacks) -> admin tier: auth required
/api/control/* (today: soundtouch-web /api/*) -> player tier: auth optional
/api/control/* (today: soundtouch-player /api/*) -> player tier: auth optional
/api/devices ...
# OAuth provider callbacks (externally-pinned; freeze in place,
@@ -404,7 +404,7 @@ diagnostic export, not leak into shared bundles.
### The `/app/*` pattern
The service's admin UI already does the right thing: `/web/*` is one catch-all
(`HandleWeb`), not one route per page. The `soundtouch-web` SPA routes
(`HandleWeb`), not one route per page. The `soundtouch-player` SPA routes
(`mount.go`, the `/`, `/devices`, `/tunein`, ... block) are the legacy
anti-pattern. The target:
@@ -523,7 +523,7 @@ them.
step is about our movable routes only.
- **Exclude** `/mgmt/spotify/callback` and `/mgmt/amazon/callback` (1b):
freeze, or move only with a deliberate provider re-registration.
2. **First, migrate `soundtouch-web` in place to the target API shape.** Before
2. **First, migrate `soundtouch-player` in place to the target API shape.** Before
touching the service, restructure the standalone `-web` binary's own routes to
what they should be *after* the merge: the control API under `/api/control/*`
and the SPA under `/app/*` (with `/ws` as e.g. `/api/control/ws`). Unlike the
@@ -537,7 +537,7 @@ them.
routes already match the target and don't overlap the service's namespaces, so
the merge below is a near-additive mount.
3. **Fold `soundtouch-web` into the service.** Bring the (already target-shaped)
3. **Fold `soundtouch-player` into the service.** Bring the (already target-shaped)
control API in as `/api/control/*` and the UI under `/app/*` (one role-gated
app, see above).
The actual overlap to clean up (verified) is small: only **`/`** truly
@@ -556,7 +556,7 @@ them.
surface from being exposed unless an operator deliberately enables it. The
flag follows the same CLI/env/persisted precedence as `server-url`, and is
the seam the `deployment-mode` parameter later subsumes.
4. **Deprecate the `soundtouch-web` binary.** It keeps working in 0.x but prints
4. **Deprecate the `soundtouch-player` binary.** It keeps working in 0.x but prints
a startup deprecation warning (along the lines of "this binary is removed in
1.x, use soundtouch-service") so its removal is no surprise.
5. **Warn on old-route hits in the service, observably.** When a deprecated path
@@ -597,7 +597,7 @@ in a 0.x release first:
### 1.x cutover
Remove the obsolete routes and retire `soundtouch-web`. Per the versioning
Remove the obsolete routes and retire `soundtouch-player`. Per the versioning
section, this is the only point where anything is removed; the frozen
speaker/app routes stay.
@@ -156,7 +156,7 @@ Where today's surfaces fall short for this user:
**Goal.** Music plays. Pressing preset 3 gives them what preset 3 should give them. Skipping a station, adjusting volume, browsing for a new station — all fast, no friction.
**Surfaces.** Physical preset buttons (always there), `soundtouch-web` (today), mobile app (Journey 2 admin app's daily-use mode), WASM-served browser UI (planned), Bose app while it still functions, voice assistants where wired up.
**Surfaces.** Physical preset buttons (always there), `soundtouch-player` (today), mobile app (Journey 2 admin app's daily-use mode), WASM-served browser UI (planned), Bose app while it still functions, voice assistants where wired up.
### What this layer needs to be good at
@@ -168,14 +168,14 @@ Where today's surfaces fall short for this user:
### How surfaces map
- `soundtouch-web`: primary daily UI for desktop browsers and (responsively) for tablets. This is already shipped.
- `soundtouch-player`: primary daily UI for desktop browsers and (responsively) for tablets. This is already shipped.
- Mobile app: daily-use mode of the same Gio app that handles admin. Capability split — admin features only show up when the user is in admin mode.
- WASM: same Gio app, served from `soundtouch-service` to anyone on the LAN. The "I forgot which device my login is on, just open a browser" fallback.
- Physical preset buttons: handled at the agent level (the Bose firmware fires them; AfterTouch or the on-device agent reacts).
### Open decisions for this journey
- Do we keep `soundtouch-web` as a separate codebase (HTML/JS), or does it become a Gio WASM build sharing code with the admin app?
- Do we keep `soundtouch-player` as a separate codebase (HTML/JS), or does it become a Gio WASM build sharing code with the admin app?
- Mobile app store distribution: TestFlight for iOS (gated, slow), Play Store for Android (faster, AAB only), F-Droid as an open-source-friendly side path.
- Multi-user state: presets per-user vs per-household. Out of scope here, but the daily surface is where it gets felt.
@@ -199,7 +199,7 @@ Where today's surfaces fall short for this user:
### How surfaces map
- `soundtouch-cli`: the canonical surface for scripted control. Already covers most of the API.
- `soundtouch-service` REST endpoints: same surface, network-accessible. Used by `soundtouch-web` and by third-party automation.
- `soundtouch-service` REST endpoints: same surface, network-accessible. Used by `soundtouch-player` and by third-party automation.
- Home Assistant: external integration; track but do not own.
- Webhooks / MQTT: not present today; would let speakers participate in event-driven flows. Out of scope for a first pass; worth a separate design doc when demand surfaces.
@@ -217,7 +217,7 @@ Where today's surfaces fall short for this user:
|------------------------------------|---------------------|-------------------|-------------------|------------------------|
| `soundtouch-cli` | partial (today) | partial (today) | no | primary |
| `soundtouch-service` web UI | wizard portion | primary | partial | indirect (REST) |
| `soundtouch-web` | no | no | primary | no |
| `soundtouch-player` | no | no | primary | no |
| GUI admin app (Gio, planned) | primary | primary | mobile mode | no |
| Pre-flashed stick (hypothetical) | primary | recovery | no | no |
| Physical preset buttons | no | no | primary | no |
@@ -229,7 +229,7 @@ The diagonal isn't full because some journeys lack a polished surface today (Jou
The Gio admin app, if built, can target Windows / macOS / Linux / iOS / Android / WASM from one codebase. Each target has hard constraints:
- **WASM (browser).** Post-install REST control, device list and status, preset editing, station search. No mDNS (browsers cannot do raw multicast — fall back to manual IP entry or a backend bridge); no raw TCP, so no SSH and no install; no block-device access, so no stick writing. This is the "I just want to use my speakers" surface, equivalent to today's `soundtouch-web`.
- **WASM (browser).** Post-install REST control, device list and status, preset editing, station search. No mDNS (browsers cannot do raw multicast — fall back to manual IP entry or a backend bridge); no raw TCP, so no SSH and no install; no block-device access, so no stick writing. This is the "I just want to use my speakers" surface, equivalent to today's `soundtouch-player`.
- **Mobile iOS.** Everything WASM does, plus Bonjour-based mDNS, plus full SSH client (so app-driven install and recovery work). No FAT32 stick writing — iOS has no filesystem-level block device access for third-party apps. Best paired with a pre-flashed stick or a friend's desktop install for the bootstrap.
- **Mobile Android.** Same as iOS, plus FAT32 stick writing *if* the user grants USB-OTG host permission. UX caveat: most users will not know what USB host mode is.
- **Desktop (Gio).** Full capability set. mDNS, SSH-driven install, FAT32 stick writing via standard block-device APIs, post-install control, recovery. The primary onboarding surface.
+1 -1
View File
@@ -8,6 +8,6 @@ Architecture notes and analyses:
- [API Route Layout and Refactoring Plan](API-ROUTE-LAYOUT.md) - route
classification (frozen speaker contract vs our movable surface), the
actor / deployment / trust model, auth, and the staged plan toward the
`soundtouch-web` / `soundtouch-service` merge (issue #451).
`soundtouch-player` / `soundtouch-service` merge (issue #451).
- [Device-Local Install: Four User Journeys](DEVICE-LOCAL-INSTALL.md) - install
patterns and user journeys for on-device deployment.
@@ -167,16 +167,16 @@ curl -s http://192.0.2.1:8090/sources
## Step 7 — Set up preset buttons (optional)
### Via soundtouch-web
### Via soundtouch-player
The Radio Browser, TuneIn tabs, and preset saving live in
**soundtouch-web**, a separate binary from the service. Once running,
**soundtouch-player**, a separate binary from the service. Once running,
open **`http://<host-ip>:8080`** in your browser (default port 8080).
### Installing soundtouch-web on a Raspberry Pi
### Installing soundtouch-player on a Raspberry Pi
`install.sh` only installs `soundtouch-service`. Use the dedicated
`install-web.sh` script to add soundtouch-web:
`install-web.sh` script to add soundtouch-player:
```bash
curl -fsSL -o install-web.sh \
@@ -185,22 +185,22 @@ sudo bash install-web.sh
```
For configuration, service management, updates, and removal see the
[Raspberry Pi guide → soundtouch-web](RASPBERRY-PI.md#soundtouch-web).
[Raspberry Pi guide → soundtouch-player](RASPBERRY-PI.md#soundtouch-player).
### Installing soundtouch-web on other hosts
### Installing soundtouch-player on other hosts
Download the binary for your OS and architecture from the
[Releases page](https://github.com/gesellix/Bose-SoundTouch/releases)
and run it directly:
```bash
./soundtouch-web --port 8080
./soundtouch-player --port 8080
```
Or install it as a systemd service following the same unit-file pattern
described in [DEPLOYMENT.md](DEPLOYMENT.md).
soundtouch-web provides two ways to save what's currently playing to a
soundtouch-player provides two ways to save what's currently playing to a
preset slot:
**★ Star button in the Now Playing card**
+18 -18
View File
@@ -9,7 +9,7 @@ Two scripts are available, one per binary:
| Script | Binary | Role | Default port |
|------------------|----------------------|-------------------------------------|--------------|
| `install.sh` | `soundtouch-service` | Cloud-replacement relay — always-on | 80 / 443 |
| `install-web.sh` | `soundtouch-web` | Browser control panel | 8080 |
| `install-web.sh` | `soundtouch-player` | Browser control panel | 8080 |
Both auto-detect CPU architecture (armv7 / arm64 / amd64), create a `soundtouch`
system user, and install a systemd unit. They are safe to re-run for updates.
@@ -118,9 +118,9 @@ sudo systemctl daemon-reload
---
## soundtouch-web
## soundtouch-player
`soundtouch-web` is a stateless browser control panel — it holds no persistent
`soundtouch-player` is a stateless browser control panel — it holds no persistent
data and can be stopped or restarted at any time without data loss.
### Installation
@@ -151,7 +151,7 @@ Once running, open **`http://<pi-ip>:8080`** in a browser.
### Configuration
```
/etc/soundtouch-web/soundtouch-web.env
/etc/soundtouch-player/soundtouch-player.env
```
Example:
@@ -173,7 +173,7 @@ network:
SOUNDTOUCH_DEVICES=192.0.2.1,192.0.2.2
```
`SERVICE_URL` links `soundtouch-web` to your `soundtouch-service` instance,
`SERVICE_URL` links `soundtouch-player` to your `soundtouch-service` instance,
which is required for Text-to-Speech ("Speak"). When the service is served
over HTTPS with its own self-signed certificate (the default), also set
`SERVICE_CA` to that CA certificate, or the proxied TTS call fails with
@@ -192,7 +192,7 @@ be left empty.
After editing the env file:
```bash
sudo systemctl restart soundtouch-web
sudo systemctl restart soundtouch-player
```
### Port conflicts
@@ -210,19 +210,19 @@ the env file after installation and restart the service.
### Service management
```bash
systemctl status soundtouch-web
sudo systemctl enable soundtouch-web # start on boot
sudo systemctl disable soundtouch-web
sudo systemctl stop soundtouch-web
sudo systemctl start soundtouch-web
sudo systemctl restart soundtouch-web
systemctl status soundtouch-player
sudo systemctl enable soundtouch-player # start on boot
sudo systemctl disable soundtouch-player
sudo systemctl stop soundtouch-player
sudo systemctl start soundtouch-player
sudo systemctl restart soundtouch-player
```
### Logs
```bash
journalctl -u soundtouch-web -e --no-pager
journalctl -u soundtouch-web -f
journalctl -u soundtouch-player -e --no-pager
journalctl -u soundtouch-player -f
```
### Updates
@@ -235,10 +235,10 @@ sudo bash install-web.sh v0.107.0 # update to a specific version
### Removal
```bash
sudo systemctl disable --now soundtouch-web
sudo rm /etc/systemd/system/soundtouch-web.service
sudo rm -rf /etc/soundtouch-web
sudo rm /usr/local/bin/soundtouch-web
sudo systemctl disable --now soundtouch-player
sudo rm /etc/systemd/system/soundtouch-player.service
sudo rm -rf /etc/soundtouch-player
sudo rm /usr/local/bin/soundtouch-player
sudo systemctl daemon-reload
```
@@ -30,7 +30,7 @@ The service consists of several key components:
- **Service Registry**: Media service discovery and configuration
- **Playback Control**: Stream URL resolution and audio metadata
![soundtouch-web TuneIn search — browsing smooth jazz stations](/images/soundtouch-web-tunein.png)
![soundtouch-player TuneIn search — browsing smooth jazz stations](/images/soundtouch-player-tunein.png)
### Marge Services (Account & Device Management)
- **Account Management**: User account simulation and device association
+2 -2
View File
@@ -11,14 +11,14 @@ Bose shut down SoundTouch cloud services on **May 6, 2026**. Per the [official e
What **continues to work** regardless:
- The official SoundTouch app for local control (play/pause/volume/source selection)
- Local playback controls via `soundtouch-cli`, `soundtouch-web`, or any app that uses the local Web API
- Local playback controls via `soundtouch-cli`, `soundtouch-player`, or any app that uses the local Web API
- Bluetooth, AUX, and AirPlay inputs
- Multiroom zones (local, peer-to-peer)
**AfterTouch** — the `soundtouch-service` — restores the first three:
- **Presets** — full preset management including long-press assignment and recently-played sync; music service presets (Spotify, TuneIn, etc.) work once the service is linked (see [Connecting Music Services](MUSIC-SERVICES.md))
- **Music browsing and playback** — TuneIn, Internet Radio, and RadioBrowser via `soundtouch-web`; direct station/URL playback via `soundtouch-cli`; Spotify via Spotify Connect (speaker-native) or AfterTouch's OAuth integration; Amazon Music OAuth infrastructure is in place but streaming is not yet verified
- **Music browsing and playback** — TuneIn, Internet Radio, and RadioBrowser via `soundtouch-player`; direct station/URL playback via `soundtouch-cli`; Spotify via Spotify Connect (speaker-native) or AfterTouch's OAuth integration; Amazon Music OAuth infrastructure is in place but streaming is not yet verified
- **Stereo pairing** — via `soundtouch-cli`
Alexa voice commands are not currently supported.
+8 -8
View File
@@ -623,7 +623,7 @@ fmt.Printf("Current source: %s, status: %s\n",
nowPlaying.Source, nowPlaying.PlayStatus)
```
### ❌ soundtouch-web TTS fails with `certificate signed by unknown authority`
### ❌ soundtouch-player TTS fails with `certificate signed by unknown authority`
**Symptoms:**
```
@@ -632,17 +632,17 @@ tls: failed to verify certificate: x509: certificate signed by unknown authority
```
**Cause:** TTS synthesis and the Bose app key live in `soundtouch-service`,
so `soundtouch-web` proxies the "Speak" action to the service. When the
so `soundtouch-player` proxies the "Speak" action to the service. When the
service is served over HTTPS with its own self-signed certificate (the
default — see `GET /setup/ca.crt`), `soundtouch-web` doesn't trust that CA out
default — see `GET /setup/ca.crt`), `soundtouch-player` doesn't trust that CA out
of the box, so the proxied call fails verification.
**Solution:** start `soundtouch-web` with `--service-ca` pointing at the
**Solution:** start `soundtouch-player` with `--service-ca` pointing at the
service's CA certificate (its `<dataDir>/certs/ca.crt`, or the file served at
`/setup/ca.crt`):
```bash
soundtouch-web \
soundtouch-player \
--service-url https://soundtouch.fritz.box \
--service-ca /path/to/certs/ca.crt
```
@@ -651,7 +651,7 @@ soundtouch-web \
system trust store, so a service URL that uses a publicly trusted certificate
needs no flag.
### ❌ soundtouch-web TTS returns `host ... is not a known device`
### ❌ soundtouch-player TTS returns `host ... is not a known device`
**Symptoms:**
```
@@ -664,8 +664,8 @@ verbatim from the request).
**Solution:** make sure the target speaker is known to `soundtouch-service`
(discovered or manually added, and migrated to AfterTouch), not only to
`soundtouch-web`'s own discovery. Check with `GET /setup/devices` on the
service. (Recent `soundtouch-web` versions identify the speaker by its device
`soundtouch-player`'s own discovery. Check with `GET /setup/devices` on the
service. (Recent `soundtouch-player` versions identify the speaker by its device
ID and a bare IP, so this error otherwise indicates the speaker simply isn't
registered with the service.)
@@ -333,7 +333,7 @@ soundtouch-cli speaker tts-cloud \
--method speaker
```
Web UI: the TTS source view has a "Say something…" box. soundtouch-web proxies
Web UI: the TTS source view has a "Say something…" box. soundtouch-player proxies
it to the service, so it must be started with `--service-url` (the target is
server-configured, not entered in the browser, to avoid an SSRF proxy).

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 172 KiB

Before

Width:  |  Height:  |  Size: 214 KiB

After

Width:  |  Height:  |  Size: 214 KiB