SideB is a retro cassette-style music player for TrimUI Brick with Spotify Connect, offline favorites, and local MP3 playback.
Latest release: v1.0.6
- Major performance optimization: 3x faster rendering (87ms โ 25ms per frame at 30 FPS)
- Eliminated CPU busy-waiting in network thread, reduced idle polling overhead
- Fast alpha blending with bit-shift approximation for ARM, optimized drawing primitives
- Reduced device temperature by ~25ยฐC during playback
![]() Spotify connecting |
![]() FAV LIST |
![]() Offline playback |
![]() Waiting screen |
- Turns the TrimUI Brick into a Spotify Connect receiver on your local network
- Shows cover art, playback state, and cassette animation directly on
/dev/fb0 - Supports hardware controls for play, pause, skip, volume, favorites, and list navigation
- Save the current track with
X - Browse and manage favorites in the fullscreen
FAV LIST - Play downloaded favorites locally with shuffle, previous, and next track controls
- Drop MP3 files into
data/imports/ - SideB imports tags and cover art automatically
- Imported tracks are added to
FAV LISTand behave like local favorites
The app consists of two components:
- go-librespot: Spotify Connect backend โ handles authentication, audio streaming, and exposes a local HTTP/WebSocket API on port
3678 - spotify-ui-rs (this repo): Rust framebuffer UI โ reads input from
/dev/input, renders the cassette scene to/dev/fb0, and communicates withgo-librespotvia its local API
When a user marks a track as a favorite, the app searches for multiple matching candidates on YouTube using yt-dlp, scores them by duration match against Spotify metadata, title similarity, and channel quality, then downloads the best match as an MP3 file on the SD card. After download, the actual file duration is validated against the Spotify track length to reject mismatched results. Downloads use a bundled FFmpeg-compatible audio transcoder with MP3 encoder support. Cached audio is played back through the device's built-in ffmpeg โ aplay subprocess pipeline. Cover art is fetched from the Spotify CDN or copied from the local cover cache. Incomplete downloads are automatically resumed on the next app launch.
For manual local playback, users can also drop MP3 files into data/imports/. SideB scans that folder automatically, reads MP3 metadata, moves the file into data/music/, extracts embedded cover art with the device's system ffmpeg when available, and adds the track to FAV LIST as a managed local item.
Important: The app does not intercept, decrypt, or extract audio from Spotify streams. Spotify playback and offline caching use entirely separate audio paths.
This project provides an offline caching mechanism strictly for personal, non-commercial use. By using this feature, you acknowledge and agree to the following:
- No content is hosted or distributed by this project. All audio files are cached locally on the user's own device and are never uploaded, shared, or made available to third parties.
- The project does not circumvent any DRM or copy protection. Spotify audio streams are not intercepted or recorded. Offline caching relies on publicly available content retrieved via yt-dlp from YouTube.
- Users are solely responsible for ensuring their use complies with applicable copyright laws and the terms of service of any third-party platform (including YouTube and Spotify). The authors and contributors of this project assume no liability for how the software is used.
- If you are a rights holder and believe this project facilitates infringement of your rights, please open an issue and we will address it promptly.
This software is provided as-is for educational and personal use. It is not intended to promote or facilitate unauthorized copying or distribution of copyrighted material.
- TrimUI Brick
- NextUI, Stock OS, or CrossMix OS
1.1.1+ - Spotify Premium account
- Wi-Fi on the same network as your Spotify client (for streaming mode)
| Button | Action |
|---|---|
| A | Play / Pause |
| โ / โ | Previous / Next track |
| โ / โ | Volume up / down |
| X | Favorite, or press twice to remove a favorite |
| Y | Open / close playlist |
| B / MENU | Exit app |
- Launch SideB from the TrimUI app menu.
- Open Spotify on your phone, desktop, or tablet.
- Pick TrimUI Brick from Spotify Connect.
- Use the hardware buttons on the device for playback, volume, favorites, and list access.
- Start playback from Spotify Connect.
- Press X to add the current track to favorites.
- Wait for the background download to finish.
- Press A on the device to start local playback from the downloaded library, or press Y to pick a downloaded track from
FAV LIST.
Copy .mp3 files into the data/imports/ folder inside the app directory:
NextUI -> /mnt/SDCARD/Tools/tg5040/SideB.pak/data/imports/
Stock -> /mnt/SDCARD/Apps/SideB/data/imports/
CrossMix -> /mnt/SDCARD/Apps/SideB/data/imports/
SideB scans that folder automatically at startup and while running. Imported files are moved into data/music/, then added to FAV LIST and treated like downloaded local tracks.
Notes:
- Current manual import support is
MP3only. - Embedded cover art is preferred. If no embedded cover exists, SideB will try to use a same-name sidecar image next to the MP3 during import.
- Press X once to show the remove confirmation, then press X again to actually remove the track from favorites.
- If you remove the track that is currently playing locally, SideB keeps the managed file until playback moves away from that track. If you favorite it again before switching tracks, the cached file is preserved.
If downloads fail with Sign in to confirm you're not a bot in the log (/tmp/sideb.log), YouTube needs valid cookies.
Use Firefox (recommended โ Chrome rotates cookies on export, making them expire immediately):
- Install Firefox and log into YouTube
- Install yt-dlp (
brew install yt-dlp/winget install yt-dlp) - Export cookies and copy to the device:
yt-dlp --cookies-from-browser firefox --cookies cookies.txt -s "https://www.youtube.com/watch?v=dQw4w9WgXcQ" - Copy
cookies.txtto the device SD card asdata/yt-dlp-cookies.txt
Restart SideB and pending downloads will resume automatically.
Why not Chrome? Since late 2024, Chrome automatically invalidates exported cookies as a security measure. Firefox does not have this limitation.
git clone https://github.com/CharlexH/SideB.git
cd SideB/spotify-ui-rs
cargo build --release --target aarch64-unknown-linux-musl
cp target/aarch64-unknown-linux-musl/release/sideb ../package/SideB.pak/sidebpackage/SideB.pak/go-librespotโ Spotify Connect backend binarypackage/SideB.pak/ffmpeg-liteโ bundled FFmpeg-compatible audio transcoder with MP3 encoder support; a minimal audio-focused build is sufficientpackage/SideB.pak/yt-dlpโ YouTube audio downloader (aarch64 binary)package/SideB.pak/resources/ca-certificates.crtโ TLS root certificatespackage/SideB.pak/resources/font_mono.ttfโ UI font
Build all release archives:
./scripts/package.shThis produces:
dist/SideB-<version>-nextui.zipdist/SideB-<version>-stock.zipdist/SideB-<version>-crossmix.zip
Each archive already contains the correct SD-card root layout:
nextui:Tools/tg5040/SideB.pak/...stock:Apps/SideB/...crossmix:Apps/SideB/...
Supported in this release:
NextUIโ validated on deviceStockโ package layout and launcher verifiedCrossMixโ package layout and launcher verified
Manual install paths:
NextUI -> /mnt/SDCARD/Tools/tg5040/SideB.pak/
Stock -> /mnt/SDCARD/Apps/SideB/
CrossMix -> /mnt/SDCARD/Apps/SideB/
Launch SideB from the TrimUI app menu, then select TrimUI Brick from Spotify Connect on another device.
Public releases attach three installable archives:
SideB-<version>-nextui.zipSideB-<version>-stock.zipSideB-<version>-crossmix.zip
The NextUI Pak Store consumes the nextui archive via pak.json.
Current release tag: v1.0.6
spotify-ui-rs/ Rust UI source
package/SideB.pak/ Local runtime staging folder and source assets
package/SideB.pak/data/ Runtime config copied into release packages
package/SideB.pak/resources/ UI images, icons, and fonts
packaging/ Platform wrappers and release metadata
scripts/package.sh Multi-platform release packager
Main config: package/SideB.pak/data/config.yml
device_name: "TrimUI Brick"
device_type: "speaker"
audio_backend: "alsa"
audio_device: "default"
bitrate: 160
volume_steps: 100
initial_volume: 80
zeroconf_enabled: trueThe UI communicates with go-librespot at http://127.0.0.1:3678.
This project builds upon the following open-source projects:
| Project | License | Usage |
|---|---|---|
| go-librespot | GPL-3.0 | Spotify Connect backend |
| yt-dlp | Unlicense | YouTube audio search and download for offline caching |
| FFmpeg | LGPL-2.1+ / GPL-2.0+ | Audio decoding and playback pipeline |
| CrossMix OS | โ | Firmware base for TrimUI devices |
Hardware: TrimUI Brick
Release archives also include:
LICENSES/NOTICE.mdLICENSES/THIRD_PARTY_SOURCES.md- Full upstream license texts for bundled binaries
Before publishing a GitHub release, record the exact upstream versions and checksums of the bundled third-party binaries in LICENSES/THIRD_PARTY_SOURCES.md.
Apache-2.0. See LICENSE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. THE AUTHORS ARE NOT RESPONSIBLE FOR ANY MISUSE OF THIS SOFTWARE OR FOR ANY VIOLATION OF THIRD-PARTY TERMS OF SERVICE OR APPLICABLE LAWS. USE AT YOUR OWN RISK.



