Commit Graph

4 Commits

Author SHA1 Message Date
Tha.Les da93c5ee44 feat: export as MP4 (karaoke video) for MP4 uploads and YouTube (#226)
* feat: export as MP4 (karaoke video) for MP4 uploads and YouTube (#219)

Add an MP4 export that muxes the current mixer state (e.g. vocals muted)
with the source video, producing a karaoke-style video.

Backend:
- Preserve a silent video.mp4 from .mp4 uploads (stream-copy, no re-encode).
- YouTube jobs do a best-effort video-only download (H.264/avc1, <=720p)
  to video.mp4, decoupled from the audio source so failures degrade to
  audio-only. New STEMDECK_VIDEO_MAX_HEIGHT config.
- GET /api/jobs/{id}/video.mp4 streams a fragmented MP4: the amix audio
  graph encoded as AAC, video stream-copied.
- has_video flag on Job, surfaced in state and persisted to metadata.

Frontend:
- MP4 added as a fourth export format (WAV/MP3/FLAC/MP4), shown only for
  jobs with a preserved video track. In MP4 mode, Export Mix produces the
  karaoke video and the audio-only Stems/Region rows are hidden.

SoundCloud and plain audio uploads are audio-only (no MP4 option).

* feat: bundle FFmpeg on Linux via first-launch download

Linux no longer requires `sudo apt install ffmpeg`. The desktop shell now
downloads a static FFmpeg build into the user data dir on first launch
(like Windows/macOS), falling back to a system ffmpeg on PATH when present.
This also fixes Demucs failing to decode compressed sources, since the
download lands in data_dir/ffmpeg which config.json already adds to PATH.

- ensure_ffmpeg: prefer a system ffmpeg, else download_linux_ffmpeg.
- download_linux_ffmpeg: fetch the .tar.xz, extract with system tar,
  copy ffmpeg + ffprobe into data_dir/ffmpeg. STEMDECK_FFMPEG_URL overrides.
- Widen download_file and make_executable from macos to unix so Linux
  reuses them.
- Not bundled in the tarball, so we don't redistribute FFmpeg.
- Update Linux README/notices/packaging comment to drop the ffmpeg apt step.

* style: apply ruff format to MP4 export code

---------

Co-authored-by: Thales <>
2026-06-25 22:46:23 +01:00
Tha.Les 3995e9236f fix: remove orphaned nvidia-* CUDA packages from Linux bundle (#225)
Both Linux tarballs were 2.5 GB (over GitHub's 2 GiB asset limit) even
with CPU torch. Root cause: 'uv pip install <project>' pulls the default
Linux torch, which is the CUDA build, dragging in nvidia-* runtime
packages (cuDNN/cuBLAS/NCCL/...) and triton (~2.5 GB). The CPU torch swap
uses --force-reinstall --no-deps, so torch becomes CPU but those CUDA
packages stay installed and orphaned, bloating the tarball.

Uninstall the nvidia-* packages and triton after the swap. CPU torch does
not use them and the NVIDIA variant re-downloads CUDA at first run.

Co-authored-by: Thales <>
2026-06-24 20:47:01 +01:00
Tha.Les 421f2b344c fix: ship CPU torch in Linux NVIDIA variant; download CUDA at first run (#222)
The Linux NVIDIA tarball baked the full CUDA torch wheel, producing an
asset >2 GiB that GitHub release uploads reject (size must be < 2147483648).

On Linux the default PyPI torch wheel bundles the CUDA runtime (~2.5 GB),
unlike Windows where the default wheel is CPU-only. The Windows NVIDIA
package therefore never baked CUDA -- it ships CPU torch and downloads the
CUDA wheel at first run via the desktop shell (install_cuda_torch, which is
cfg(not(macos)) and already covers Linux). Mirror that on Linux: bake the
small CPU torch in both variants; the NVIDIA variant differs only by
omitting the cpu-only marker, so the shell detects the GPU and downloads
CUDA on first launch. Keeps both tarballs well under the 2 GiB limit.

Co-authored-by: Thales <>
2026-06-24 19:17:37 +01:00
Tha.Les 8131900d0a feat: Linux portable builds (CPU + NVIDIA) and release workflow (#220)
* feat: add CPU-only Linux portable build and release workflow

Adds a Linux .tar.gz portable package mirroring the existing Windows/macOS
build paths. Bundles a python-build-standalone runtime (CPU torch + demucs)
plus the Tauri binary so users extract and run ./StemDeck.

- scripts/linux/make-portable.sh: stages PBS Python, force-installs CPU-only
  torch, builds the Tauri binary, and produces StemDeck-Linux-x64.tar.gz with
  the backend/app + python/ layout find_repo_root resolves at runtime.
- .github/workflows/linux-release.yml: builds on hosted ubuntu-latest on
  release publish; installs Tauri v2 apt deps + uv, ClamAV-scans, uploads.
- packaging/linux/{README-LINUX,THIRD_PARTY_NOTICES}.txt: extract-and-run
  instructions noting ffmpeg + WebKitGTK are system (apt) prerequisites.

FFmpeg is not bundled: the Linux shell expects ffmpeg on PATH. NVIDIA/CUDA
and AppImage variants are intentionally deferred to later phases.

* fix: don't set PYTHONHOME on Linux (breaks PBS stdlib resolution)

The Linux backend failed to start with 'ModuleNotFoundError: No module
named encodings'. PYTHONHOME was being set to python/bin instead of the
prefix python/, so CPython looked for its stdlib under python/bin/lib and
could not boot.

Linux bundles python-build-standalone exactly like macOS, which detects
its own prefix by walking up from bin/ and must NOT have PYTHONHOME set.
The two PYTHONHOME sites were gated #[cfg(not(target_os = "macos"))],
wrongly including Linux alongside Windows. Only Windows -- whose portable
venv keeps the stdlib under base/Lib -- needs PYTHONHOME, so gate both
sites (start_backend and python_stdlib_ok) to #[cfg(windows)].

This also fixes the latent inconsistency where probe_runtime reported
Python ready (python_stdlib_ok set PYTHONHOME=python, the correct prefix)
while start_backend set PYTHONHOME=python/bin and failed.

* feat: add NVIDIA/CUDA Linux portable variant

Adds a second Linux package, StemDeck-Linux-x64.NVIDIA.tar.gz, with
CUDA-enabled torch baked in (mirrors the Windows NVIDIA variant).

- make-portable.sh: CPU_ONLY toggle (default 1). CPU_ONLY=0 keeps the
  project's default torch wheel, which on Linux x86_64 is the CUDA build,
  and omits the cpu-only marker so the desktop shell detects the GPU and
  uses CUDA at runtime. No app-side changes needed -- the CUDA detection/
  install path in main.rs is already cfg(not(macos)) and covers Linux.
- linux-release.yml: builds both variants in one job. CPU first (full Tauri
  build), then NVIDIA with SKIP_TAURI_BUILD=1 reusing the same binary. Adds
  a free-disk-space step (CUDA bundle is several GB) and drops each
  uncompressed stage after taring to stay within the hosted runner's disk.
- README-LINUX.txt: documents both variants and the NVIDIA driver
  prerequisite (nvidia-smi must work; CUDA runtime is bundled, no toolkit
  install needed; falls back to CPU when no GPU).

* ci: run Linux release on self-hosted linux/x64 runner

Targets the org's self-hosted wsl2 runner ([self-hosted, linux, x64])
instead of hosted ubuntu-latest, matching the Windows/macOS release
jobs. Drops the free-disk-space step: it was a hosted-runner workaround
and would needlessly rm system directories on a persistent self-hosted
box (WSL2's virtual disk has ample room for the CUDA bundle).

* ci: add workflow_dispatch test build for Linux release

Lets you run the full two-variant build + ClamAV scan on the self-hosted
runner without publishing a release, to validate the runner toolchain and
the CUDA build. Resolves the version from a manual input (default 0.0.0,
must be valid PEP 440) instead of the branch ref, and skips the upload
step on non-release events.

---------

Co-authored-by: Thales <>
2026-06-24 18:07:34 +01:00