Skip to content

Releases: stemdeckapp/stemdeck

v0.5.0 Alpha 1

Choose a tag to compare

@thcp thcp released this 18 May 20:26

Before you install

If you have a previous version of StemDeck installed, delete these folders first using Finder before opening the new DMG:

  • ~/Library/Application Support/StemDeck
  • ~/Library/WebKit/app.stemdeck.desktop
  • ~/Library/WebKit/stemdeck

In Finder, press ⌘ Shift G, paste each path, and move the folder to Trash. Then empty the Trash before installing.


What's new in 0.5.0 Alpha 1

A proper DAW look

The whole interface has been rebuilt around a flat dark DAW aesthetic. The mixer and waveform lanes now sit side by side in a two-column layout, with rows that dynamically fill the full available height no empty black gap when you load a track with fewer stems. Non-extracted stems are grayed out in both the mixer and waveform. Loop regions are shown as a full-height overlay so they're easy to spot.

Track info lives in the footer now

The album art, title, time position, stem count, and favorite button have moved to the footer always visible while the transport is running. Below that sits a scrub bar spanning the full width of the footer, plus elapsed / total time. When no track is loaded, the footer shows a decorative placeholder waveform.

Export Mix actually works

You can now export your current stem mix as a WAV or MP3 directly from the footer. The file lands as {title}_exported_mix.wav (or .mp3) no spaces, no special characters, just clean underscores. In the Tauri desktop app, exporting hands off to the system browser since WKWebView doesn't support standard download links. Export button stays grayed out until a track is loaded.

A subtle but important pipeline fix: previously, selecting all 6 stems meant no mix file was produced at all, so export would silently fail. That's fixed a mix is always built regardless of stem selection.

Footer waveform shows the real signal

The waveform in the footer used to pull from the first available stem (often vocals). On an instrumental section that meant a flat line. It now uses the full reconstructed mix, so what you see actually matches what you hear.

Tag search with autocomplete

Type # in the library search box to filter by tag. As you type, a dropdown shows up to 8 matching suggestions click one or navigate with arrow keys and Enter. Tags are extracted automatically from YouTube metadata.

Library sidebar

New sidebar sections: Recent, Stem Collections, Tags, and Favorites. Folders support subfolder nesting via drag-and-drop (circular nesting is blocked). Track cards show Extracted, Source, and Quality details. Purged tracks are remembered across reloads and never reappear.

Sections bar

An interactive sections bar sits above the waveform. You can add, rename, drag, and resize sections. Changes persist across restarts. A live saving indicator shows when a section edit is in-flight.

Analysis panel

The analysis cards now include Dynamic Range (DR) score with a label (Compressed / Moderate / High / Wide), Tempo Stability as a percentage, and a Key Confidence meter.


This is a pre-release alpha. Things may break. If you hit something, please open an issue.

Artifact scan

  • Windows portable packages were scanned with ClamAV in CI before upload.

Artifact build

  • macOS arm64 and x64 DMGs and runtime packs were built and inspected on a macOS Woodpecker agent before upload.

v0.4.0-alpha.3

Choose a tag to compare

@thcp thcp released this 16 May 09:39

v0.4.0-alpha.3

Important

macOS users run this after installing:

xattr -dr com.apple.quarantine /Applications/StemDeck.app

macOS Gatekeeper will block the app on launch without this step. Proper code signing is planned for a future release.


What's new in alpha.3

This release applies the papaya improvement cycle ÔÇö 11 fixes across the backend pipeline, frontend, and desktop setup flow.

Backend

Download retries on transient network errors

yt-dlp downloads now retry up to 3 with exponential backoff (2 / 4 / 8 s) on transient failures ÔÇö SSL errors, connection resets, DNS blips, timeouts. Non-retriable errors (404, private video, geo-block, age-restricted) still fail immediately with no retry.

Pipeline timeout constants

Hardcoded timeouts scattered across pipeline files (300 s for FFmpeg, 120 s for analysis, 1800 s for Demucs stall detection) are now named constants in config.py, overridable via environment variables (STEMDECK_TIMEOUT_FFMPEG, STEMDECK_TIMEOUT_ANALYZE, STEMDECK_TIMEOUT_DEMUCS_STALL).

Registry schema migration

The job registry now runs a _migrate() function on load that upgrades persisted schemas incrementally. The existing "version" field is now acted on ÔÇö adding or changing schema fields in future releases will not break already-completed jobs on restart.

Job correlation in logs

Every pipeline log line is now prefixed with [job_id], making it straightforward to trace a single job across the download  analyze  separate stages in log output.

Frontend

Client-side upload validation

File size and type are now validated in the browser before the upload begins. Files over 100 MB or with unsupported formats are rejected immediately with a toast ÔÇö no round-trip to the server needed.

Stem names from API

STEM_NAMES is no longer hardcoded in JavaScript. The frontend fetches the authoritative list from GET /api/config on startup, so adding or renaming a stem in the backend is reflected in the UI without a separate frontend change.

SSE race condition guard

SSE-driven state updates are now deferred by one tick (setTimeout(..., 0)) so in-progress user interactions (mixer moves, stem toggles) are not clobbered by a concurrent server-sent event.

localStorage error visibility

localStorage reads and writes that fail (e.g. quota exceeded) now emit a console.warn instead of being silently swallowed, making persistence failures visible during debugging.

Removed debug console.log

A leftover console.log call in player.js has been removed.

Replaced alert() with toast

Unsupported file type errors that previously used alert() now use the in-app showError() toast ÔÇö accessible, mobile-friendly, and consistent with the rest of the UI.

Desktop setup

Actionable error messages

Each terminal error state in the setup flow now includes a specific recovery hint and a working Retry button ÔÇö e.g. "Check that your disk has at least 2 GB free and click Retry" instead of a bare error string.

Artifact scan

  • Windows portable packages were scanned with ClamAV in CI before upload.

Artifact build

  • macOS arm64 and x64 DMGs and runtime packs were built and inspected on a macOS Woodpecker agent before upload.

v0.4.0-alpha.2

Choose a tag to compare

@thcp thcp released this 14 May 18:40
5628963

What's fixed in alpha.2

Important

macOS users run this after installing:

xattr -dr com.apple.quarantine /Applications/StemDeck.app

macOS Gatekeeper will block the app on launch without this step. Proper code signing is planned for a future release.


Python runtime (ModuleNotFoundError: No module named 'encodings')

The backend failed to start on any user machine because the bundled Python runtime was missing its standard library. The root cause was using python -m venv to build the runtime pack venvs only create site-packages/ and borrow stdlib from the build machine's Python prefix, which doesn't exist on user machines.

Fix: The runtime pack now bundles the full python-build-standalone (UV PBS) Python installation, which already contains the complete stdlib at lib/python3.12/. PYTHONHOME is set at launch to point Python to this bundled location.

Stale/broken runtime no longer blocks upgrade

If a broken runtime from a previous install was on disk, the app would detect the Python binary as "ready", skip re-extraction, and crash. probe_runtime now runs python -c "import encodings" to validate the stdlib is actually working before declaring the runtime healthy. A broken install triggers re-extraction automatically.

Native zstd extraction (fixes macOS Tahoe issue #31)

macOS ships bsdtar compiled without zstd support, causing runtime pack extraction to fail with Can't initialize filter; unable to run program 'zstd -d -qq'. Extraction now uses native Rust crates (zstd, tar, flate2) with no dependency on system tar or zstd binaries.

Setup retries stale cached archive

If a previously downloaded runtime archive fails SHA256 verification, the app now deletes it and re-downloads instead of showing a permanent error.

Artifact scan

  • Windows portable packages were scanned with ClamAV in CI before upload.

Artifact build

  • macOS arm64 and x64 DMGs and runtime packs were built and inspected on a macOS Woodpecker agent before upload.

v0.4.0-alpha.1

Choose a tag to compare

@thcp thcp released this 12 May 11:27

macOS Native App

StemDeck is now available as a native macOS application (.dmg) for both Apple Silicon and Intel Macs.

What's new

  • Native macOS app
    Built with Tauri 2, including a first-launch setup wizard that automatically downloads and installs a self-contained backend runtime. No Python or system dependencies required.

  • Apple Silicon acceleration (MPS)
    Stem separation uses Metal Performance Shaders on M1 and newer Macs for significantly improved performance.

  • arm64 + x64 builds
    Separate native builds are available for both Apple Silicon and Intel architectures.

  • Backend watchdog
    The Python backend process is automatically terminated if the desktop shell exits unexpectedly.


Downloads

File Platform Acceleration
StemDeck-macOS-arm64.dmg macOS Apple Silicon (M1/M2/M3/M4) Metal (MPS)
StemDeck-macOS-x64.dmg macOS Intel CPU
StemDeck-Windows-x64.zip Windows CPU
StemDeck-Windows-x64.NVIDIA.zip Windows + NVIDIA GPU CUDA

The .tar.zst files are internal runtime packages and are not required for normal installation.


Installation

macOS

  1. Download the correct .dmg file for your Mac
  2. Open the DMG
  3. Drag StemDeck.app into the Applications folder
  4. Launch StemDeck

On first launch, StemDeck automatically downloads:

  • Backend runtime
  • FFmpeg
  • Demucs model files

Approximate first-time download size: ~170 MB

Subsequent launches start in seconds.


Gatekeeper Warning (macOS)

Because the application is currently unsigned, macOS may display a security warning on first launch.

To open the app:

  • Right click StemDeck.app
  • Select Open
  • Confirm by clicking Open again

Alternatively:

  • Open System Settings → Privacy & Security
  • Click Open Anyway

CI / Build Pipeline

  • macOS arm64 and x64 packages were built and validated on a macOS Woodpecker CI agent before release upload.
  • Windows packages were scanned with ClamAV during CI before publication.

v0.3.0-alpha.1

Choose a tag to compare

@thcp thcp released this 10 May 10:07
5849990

What's changed

Local MP3 and WAV file import

You can now process local audio files directly. Drag and drop an .mp3 or .wav file onto the import bar, or use the file picker — no YouTube URL required. The file goes through the same pipeline as a URL: stem separation, BPM and key analysis, LUFS measurement, and the full DAW player. Files up to 100 MB are accepted. Stem selection chips and all mixer and download features work identically.

URL and filename persist after app restart

When you load a track from the library, the original URL or filename now appears in the import bar. Previously this was lost on every Windows restart because the source address was stored only in session memory. It is now stored server-side and survives restarts. YouTube tracks show the full URL so you can change the stem selection and reprocess; local file tracks show the filename as a reference.

Fix release notes being overwritten with "System.Object[]"

The Windows release pipeline was reading the existing release body into a PowerShell variable. PowerShell captured the output as a String[] array, and converting it to a string produced the literal text System.Object[], replacing hand-written notes. Fixed by joining the array before string operations.

Artifact scan

Windows portable packages were scanned with ClamAV in CI before upload.

v0.2.0-alpha.7

Choose a tag to compare

@thcp thcp released this 09 May 23:35
93678b9

What's changed

Store user data in %LocalAppData%\StemDeck (#25)

The Windows desktop app now keeps all mutable data (models, jobs, FFmpeg, logs) in %LocalAppData%\StemDeck instead of the install folder. This means your library and downloaded models survive across releases — no more copying a data/ folder when you unzip a new version.

On first launch after upgrading from alpha.6, existing data is automatically migrated via a same-volume move (instant, no copying).

Fix drag-and-drop to folders on Windows (#24)

Tracks could not be dragged to library folders in the Windows desktop app. Two issues were fixed:

  • dragDropEnabled: false is now set in tauri.conf.json so WebView2 no longer intercepts OS-level drag events at the Win32 layer, allowing HTML5 dragover/drop to fire correctly.
  • The catalog rail panel background was not filling the full panel height in the collapsed state, causing catalog-main to wrap to an implicit grid row. Fixed with explicit grid-template-rows: 1fr and grid placement.
  • dropOnFolder and getDraggedTrackId now accept an explicit trackId parameter and a text/plain dataTransfer fallback for cross-origin drag in WebView2.
  • Tracks can now be dragged from the trash back to the Library rail button.

Artifact scan

  • Windows portable packages were scanned with ClamAV in CI before upload.

v0.2.0-alpha.6

Choose a tag to compare

@thcp thcp released this 09 May 20:38
55af86a

What's changed

Fix drag-and-drop to folders on Windows (#23)

Tracks could not be dragged to library folders in the Windows desktop app. On WebView2, the dragover handler was gating e.preventDefault() behind a module-level dragId variable that can be null mid-drag — causing the browser to reject the drop. Fixed by checking e.dataTransfer.types for the custom MIME type instead, which is reliably populated during dragover on all browsers including WebView2.

Fix SSL errors when downloading model weights on macOS (#22)

Demucs failed with CERTIFICATE_VERIFY_FAILED on first run when using a Python.org install on macOS, which does not link to the system SSL store. Fixed by injecting SSL_CERT_FILE and REQUESTS_CA_BUNDLE pointing to certifi's CA bundle into the demucs subprocess environment before spawning it.

Artifact scan

  • Windows portable packages were scanned with ClamAV in CI before upload.

v0.2.0-alpha.5

Choose a tag to compare

@thcp thcp released this 09 May 15:23
a9d2302

Summary

  • Appbar collapses to a compact horizontal icon strip on double-click (same grid-template-rows animation as widget sections); auto-collapses when a track finishes processing
  • Collapsed strip shows: SD monogram · URL icon · per-stem colored squares (active/inactive state) · Process button — all clickable
  • Clicking stem squares toggles selection; Process submits if URL is already set, otherwise expands; SD/URL icon always expands
  • Brand subtitle shortened to "AI stem separation"
  • Version label (v0.1.0) added to brand area with optional green "New release available" chip that fetches the latest tag from the GitHub releases API on load
  • Fixed footer button underline and icon sizing

Artifact scan

  • Windows portable packages were scanned with ClamAV in CI before upload.

v0.2.0-alpha.4

Choose a tag to compare

@thcp thcp released this 09 May 09:21
ba05a7a

Summary

  • Appbar collapses to a compact horizontal icon strip on double-click (same grid-template-rows animation as widget sections); auto-collapses when a track finishes processing
  • Collapsed strip shows: SD monogram · URL icon · per-stem colored squares (active/inactive state) · Process button — all clickable
  • Clicking stem squares toggles selection; Process submits if URL is already set, otherwise expands; SD/URL icon always expands
  • Brand subtitle shortened to "AI stem separation"
  • Version label (v0.1.0) added to brand area with optional green "New release available" chip that fetches the latest tag from the GitHub releases API on load
  • Fixed footer button underline and icon sizing

Artifact scan

  • Windows portable packages were scanned with ClamAV in CI before upload.

v0.2.0-alpha.3

Choose a tag to compare

@thcp thcp released this 09 May 00:37

This release is a major UI overhaul — new DAW-style mixer, song catalog panel, collapsible appbar, and a large number of UX fixes across the player, transport, and import flow.

What's new

DAW-style mixer

The stem mixer has been completely redesigned. Each stem row now uses a horizontal DAW layout: waveform icon → stem name → fader → VU meter → dB value → Mute → Solo → Download.

  • Fader renders as a styled range input with stem-colored fill and a circular thumb. Boost above 0 dB works — each stem routes through a Web Audio GainNode instead of HTMLAudioElement.volume, which is capped at 1.0 by the browser.
  • VU meter shows a real-time level bar driven by a pre-computed RMS envelope — no AnalyserNode or requestAnimationFrame needed. The bar fills left-to-right with a gradient that tips into red on loud passages.
  • Solo button lights up gold when active; soloing any stem silences the rest.
  • Mute button turns red and stays fully visible when active (previously it faded out along with the dimmed row, making it hard to see the muted state).
  • Download button opens the stem file in the system browser, including in the Tauri desktop app where native <a download> was previously silently blocked.

Song catalog

A new catalog panel on the left sidebar shows the history of processed tracks.

  • Tracks are listed with thumbnail, title, duration, and stem count.
  • Click any entry to instantly reload that track into the player without re-processing.
  • Tracks can be organised into colour-coded folders via drag-and-drop.
  • A search bar filters by title.
  • The panel collapses to a thumbnail strip to save space.

Collapsible appbar

The import bar at the top now collapses to a compact icon strip on double-click, using the same grid-template-rows: 0fr ↔ 1fr animation as the widget sections. It auto-collapses when a track finishes processing so the waveform gets full vertical space.

The collapsed strip contains:

  • SD monogram — expands the appbar
  • URL icon — expands the appbar
  • Per-stem coloured squares — show active/inactive state; click to toggle stem selection without expanding
  • Process button — submits the job if a URL or file is set; otherwise expands the appbar

Version badge and update chip

The brand area now shows the current version. If a newer release is available on GitHub, a green "New release available" chip appears next to the version and links to the releases page.

Transport improvements

  • AudioContext.resume() fires before multitrack.play() in the same gesture handler (Safari requires this to unblock autoplay).
  • Loop region and playhead state reset cleanly on new track load; playhead snaps to loop start on play.
  • Keyboard shortcut L toggles loop; I/O set loop in/out points at the current playhead position.

Import flow

  • File drop onto the URL bar — drag an MP3 or WAV directly onto the input area. A pill shows the filename and size; a clear button removes it.
  • Stem choice chips use Spotify-style filter semantics: first click on a chip while all are selected switches to "only this stem"; subsequent clicks add to the selection; deselecting the last chip wraps back to "all selected".

Diagnostics

  • Global window.error and unhandledrejection handlers log to the console with file, line, and stack trace.
  • Per-stem <audio> elements attach an error listener that logs the MediaError code and message.

CI

  • Fixed: all pipeline steps now carry backend: kubernetes, ensuring they run on the k3s agent and not the local Windows agent on main-branch pushes and releases.

Setup (macOS / Linux)

Unchanged — ./run.sh setup && ./run.sh start.

Known limitations

Same as previous alphas. The Windows app is ALPHA — expect rough edges.