BearTeddy/nightingale-vocal-studio

Nightingale fork with Vocal Studio, pitch coaching, karaoke recording, and YouTube import

0

stars

174

commits

TypeScript

primary language

Sep 8, 2026

updated

README

Nightingale

Karaoke from any song in your music library, powered by neural networks.

Build Docker Pulls Stars License Patreon Ko-fi


[!IMPORTANT] This repository is an independently modified fork of rzru/nightingale. It keeps the upstream GPL-3.0-or-later license and adds the Nightingale Vocal Studio, local YouTube importing, melody extraction and correction, strict pitch coaching, and vocal recording/export workflows. See FORK.md for attribution, branding, and packaging details.

Nightingale scans your music folder, Plex Media Server, Jellyfin server, Navidrome server, or self-hosted web library; separates lead vocals from instrumentals using the UVR Karaoke model (or Demucs); transcribes lyrics with word-level timestamps via WhisperX; and plays it all back with synchronized highlighting, pitch scoring, key/tempo controls, profiles, and dynamic backgrounds.

The standard installer ships as a small desktop app and bootstraps Python, ffmpeg, and ML packages automatically on first launch. An offline installer build can embed the already-provisioned analyzer runtime in the installer, so Python and package setup does not need a network connection.

Features

Vocal Studio fork additions

  • YouTube and playlist import with highest-quality media selection, Unicode-safe metadata, and automatic library naming.
  • JOYSOUND-style pitch highway with strict octave-aware scoring, phrase feedback, Coach and Game modes, and editable melody maps.
  • Vocal Studio with microphone checkup, full vocal-range references, adaptive pitch and ear-training exercises, song-phrase loops, and practice history.
  • Local vocal recording with 24-bit dry masters, synchronized performance mixes, recoverable sessions, and optional M4A or MP4 export.
  • Windows-first setup with a configurable data directory, Desktop shortcuts, and automatic first-run provisioning of the analyzer runtime.

Library & sources

๐Ÿ“ Folder library โ€” point at any folder and Nightingale scans supported audio, video, and UltraStar files inside.

๐ŸŸ  Plex โ€” connect to a local, remote, or LAN-only Plex Media Server, select one or more music libraries, and import tracks, associated music video clips, covers, and read-only playlists. Hosted Plex sign-in discovers servers; an advanced PMS URL + token flow works without plex.tv during normal operation.

๐ŸŽฌ Jellyfin โ€” play straight from your Jellyfin library. Songs cache locally on first play so karaoke runs the same as a folder library.

๐Ÿ’ฟ Navidrome โ€” connect to Navidrome for audio libraries. Login details are kept encrypted on disk.

๐ŸŒ Self-hosted web mode โ€” run Nightingale on a Linux box on your home network and open it from phones, laptops, tablets, and TVs at <hostname>.local. See docs/self-hosted. Also runs in Docker (CPU or CUDA/GPU).

๐Ÿงญ Sidebar + library filters โ€” browse by quick filters, metadata cleanup buckets, artists, albums, and existing playlists from Plex, Jellyfin, Navidrome, or folder-library .m3u / .m3u8 / .pls files. Analyze All and optional auto-analysis help queue your library faster, and the sidebar/song list remember scroll position when you come back.

๐Ÿ—‚๏ธ Flexible storage โ€” choose the main data folder during setup, then split cache, models, videos, and vendor tools into separate folders from Settings when needed.

๐Ÿ“ฆ Self-contained โ€” ffmpeg, uv, Python, PyTorch, and ML packages are downloaded automatically during setup. Video backgrounds are pre-downloaded so the first session is ready to go.

Lyrics & audio

๐ŸŽค Stem separation โ€” isolates lead vocals from instrumentals using the UVR Karaoke model (default) or Demucs, with adjustable guide vocal volume. The karaoke model preserves backing vocals in the instrumental for a more natural sound.

๐Ÿ“ Word-level lyrics โ€” automatic transcription with alignment, or fetched from LRCLIB when available.

โœ๏ธ Lyrics editor with LRCLIB browser โ€” edit lyrics, browse LRCLIB matches, or paste your own LRC / Enhanced LRC from a song's Actions button. Timed LRC is used as-is (optionally skipping stem separation to sing over the original mix); plain lyrics run alignment.

๐Ÿˆฏ CJK lyric support โ€” Japanese, Chinese, Cantonese, and Korean songs get per-character forced alignment and romanized readings (Hepburn / pinyin / Jyutping / Revised Romanization) shown above each token.

๐Ÿ—ฃ๏ธ Pluggable ASR engines โ€” choose Whisper (default, broad language coverage) or Parakeet v3 (experimental) for ~25 European languages, with NeMo on CUDA and ONNX Runtime everywhere else.

โšก Pluggable forced alignment โ€” keep WhisperX's aligner (default) or switch on an experimental backend: GPU forced alignment (torchaudio forced_align) for faster word timestamps on CUDA and Apple Silicon, or the Qwen aligner (Qwen3-ForcedAligner-0.6B) which timestamps 11 languages incl. CJK in a single pass on CUDA/MPS/CPU. Both fall back to WhisperX automatically.

๐ŸŽผ UltraStar Deluxe songs (experimental) โ€” drop USDX song folders (.txt or .usdx plus sibling audio/vocals/instrumental/video) into your library; pitch and lyric data come from the file directly, no analyzer pass needed. See docs/usdx.

Playback & visuals

๐ŸŽฏ Pitch scoring โ€” real-time microphone input with pitch detection, star ratings, and per-song scoreboards.

๐ŸŽš๏ธ Key & tempo shifts โ€” adjust song key and tempo after analysis, with cached playback variants for quick retries.

๐ŸŽฌ Video files โ€” drop video files (.mp4, .mkv, etc.) into your music folder; vocals are separated from the audio track and the original video plays as a synchronized background.

๐ŸŒŒ Audio-reactive backgrounds โ€” 10 GPU shaders that react to your microphone in real time (Plasma, Waves, Nebula, Starfield, Sonar, Voronoi, Vortex, Metaballs, Spectrum, Oscilloscope), Pixabay video loops in 5 flavors (Nature, Underwater, Space, City, Countryside), plus source-video playback for video files.

๐ŸŽ™๏ธ Mic monitoring + latency test โ€” optionally route your live mic into playback, adjust monitor gain (0โ€“200%), and run a beep-based latency test from Settings so scoring lines up with your room.

Quality of life

๐Ÿ‘ค Profiles โ€” create and switch between player profiles; scores are tracked per profile.

๐ŸŽฎ Gamepad support โ€” full navigation and control via gamepad (D-pad, sticks, face buttons).

๐Ÿ“บ Adaptive + touch-friendly UI โ€” scales from phones/tablets to 4K TVs, with on-screen playback controls on touch devices.

โฌ†๏ธ In-app updates โ€” on macOS and Windows, auto-checks for new releases at launch, badges the sidebar avatar when one is available, and downloads and installs signed updates with one click. Linux is manual: the Update entry opens GitHub Releases for you to grab the new build.

Quick start

Download the latest release for your platform from the Releases page and run it. On first launch, Nightingale shows setup steps, lets you pick a data folder, then installs the Python environment and ML models automatically.

Updates

On macOS and Windows, Nightingale checks for new releases once at launch. When one is available, the sidebar avatar grows a small green dot and the Update entry in the dropdown menu opens a dialog with the release notes. Click Install & Restart and the app downloads the signed bundle, installs it, and relaunches. On Windows the installer runs in passive mode โ€” a small progress window flashes and the app comes back automatically once the install finishes.

Linux

Auto-update is not supported on Linux โ€” the app ships without the updater plugin. The Update entry still appears in the sidebar menu, but it just opens a dialog explaining this with a one-click button to the Releases page so you can grab the new .deb or .rpm and install it the usual way for your distro.

macOS

The manual Installer builds workflow creates separate .dmg installers for Apple Silicon and Intel Macs without requiring release-signing secrets. Open the workflow in GitHub Actions, choose Run workflow, then download the artifact matching the Mac's processor.

macOS quarantines files downloaded from the internet. Since Nightingale isn't signed with an Apple Developer ID, Gatekeeper will block it with a message like "app is damaged and can't be opened". To fix this, remove the quarantine attribute after moving the Nightingale.app to Applications:

xattr -cr /Applications/Nightingale.app

Supported formats

Audio: .mp3, .flac, .ogg, .opus, .wav, .m4a, .aac, .wma. Video: .mp4, .mkv, .avi, .webm, .mov, .m4v. UltraStar: .usdx, plus .txt files whose contents look like USDX.

Controls

ActionKeyboardGamepad
MoveArrow keysD-pad / Left stick
Confirm / SelectEnterA (South)
Back / CancelEscapeB (East) / Start
Switch panelTabโ€”
Search songsType to filterโ€”

Playback

ActionKeyboardGamepad
Pause / ResumeSpaceStart
Exit to menuEscapeB (East)
Toggle guide vocalsGโ€”
Guide volume up/down+ / -โ€”
Cycle background themeTโ€”
Cycle video flavorFโ€”
Toggle microphoneMโ€”
Next microphoneNโ€”
Toggle mic monitoringRโ€”
Toggle fullscreenF11โ€”
Skip Intro / Skip OutroOn-screen buttonsA (South)

How it works

flowchart TD
    A["Audio or video file"] --> B["UVR Karaoke / Demucs"]
    A2["USDX bundle (.txt / .usdx)"] --> E["Tauri App (Rust + React)"]
    B -->|"vocals + instrumental"| C["LRCLIB"]
    C -->|"synced lyrics if available"| D["WhisperX or Parakeet v3 (exp.)"]
    D -->|"word-level alignment, CJK reading"| E
    E --> F["Plays instrumental + synced lyrics with pitch scoring, key/tempo, mic monitoring, audio-reactive backgrounds"]

The analyzer runs as a persistent local process: Nightingale starts it once and talks to it over a token-authenticated loopback TCP socket using newline-delimited JSON, so per-song startup overhead (model load, CUDA init) is paid only once.

Analysis results are cached using blake3 file hashes. Re-analysis only happens if the source file changes, the user triggers it manually, or you choose to shift key/tempo and create playback variants. USDX songs skip stem separation entirely when #VOCALS and #INSTRUMENTAL are provided.

Hardware

The Python analyzer uses PyTorch and auto-detects the best backend:

BackendDeviceNotes
CUDANVIDIA GPUFastest
MPSApple SiliconmacOS; WhisperX alignment falls back to CPU
CPUAnySlowest but always works

The UVR Karaoke model uses ONNX Runtime and enables CUDA acceleration automatically on NVIDIA GPUs, or CoreML on Apple Silicon.

A song typically takes 2โ€“5 minutes on GPU, 10โ€“20 minutes on CPU.

Data storage

During setup, you can choose where Nightingale stores data (default: ~/.nightingale). Most runtime data is stored in that selected data folder, while config.json and nightingale.log remain in ~/.nightingale.

Typical selected data folder layout:

<selected-data-folder>/
โ”œโ”€โ”€ cache/               # Stems, transcripts, lyrics, shifted variants, covers, playable videos
โ”œโ”€โ”€ songs.db             # SQLite song library and analysis metadata
โ”œโ”€โ”€ profiles.json        # Player profiles and scores
โ”œโ”€โ”€ videos/              # Cached Pixabay video backgrounds
โ”œโ”€โ”€ sounds/              # Sound effects (celebration)
โ”œโ”€โ”€ vendor/
โ”‚   โ”œโ”€โ”€ ffmpeg           # Downloaded ffmpeg binary
โ”‚   โ”œโ”€โ”€ uv               # Downloaded uv binary
โ”‚   โ”œโ”€โ”€ python/          # Python 3.10 installed via uv
โ”‚   โ”œโ”€โ”€ venv/            # Virtual environment with ML packages
โ”‚   โ”œโ”€โ”€ analyzer/        # Extracted analyzer Python scripts
โ”‚   โ””โ”€โ”€ .ready           # Marker indicating setup is complete
โ””โ”€โ”€ models/
    โ”œโ”€โ”€ torch/           # Demucs model cache
    โ”œโ”€โ”€ huggingface/     # WhisperX model cache
    โ””โ”€โ”€ audio_separator/ # UVR Karaoke model cache

~/.nightingale/config.json stores app settings, including the selected data folder path.

Video backgrounds

Pixabay video backgrounds use the Pixabay API. The API key is embedded in release builds. For development, create a .env file at the project root:

PIXABAY_API_KEY=your_key_here

Building from source

Prerequisites

ToolVersion
Rust1.85+ (workspace uses edition 2024)
Node.js20+
pnpmlatest
Linux onlylibwebkit2gtk-4.1-dev, libssl-dev, libayatana-appindicator3-dev, librsvg2-dev, libxdo-dev, libasound2-dev

Development

git clone <repo-url> nightingale
cd nightingale
cargo desktop dev

Release build

cargo desktop build

Offline analyzer installer

After completing setup once on the build machine, create a dependency-complete installer from that exact vendor environment and model cache:

cargo desktop offline-build \
  --vendor /path/to/nightingale-data/vendor \
  --models /path/to/nightingale-data/models

On Windows, the analyzer-only build produces one *-offline-setup.exe. When model weights would push that executable above Windows' 4 GB PE limit, the complete build automatically produces a *-complete-offline-setup/ media folder containing a runnable launcher, offline-models/ sidecars, a short README, and a sorted SHA256SUMS.txt covering every distributed file. Keep the folder together and run the .exe inside it; installation is still one command and requires no downloads. The launcher expands models directly into the configured model cache, including for upgrades that have already completed first-run setup. macOS defaults to a DMG with bundled resources. The packager excludes Python bytecode caches and transient model locks/downloads, creates deterministic tar.zst payloads, splits them into installer-safe parts, and writes SHA-256 manifests. First-run setup verifies every part's size and checksum plus the app version, operating system, architecture, and payload type before atomically extracting into the selected data folder. Interrupted atomic swaps restore the previous verified directory on retry, and a failed verification leaves an existing analyzer or model environment untouched while first-run setup can fall back to online provisioning.

Publish the normal *-setup.exe for downloads. Complete offline media is intended for local or air-gapped transfer and is deliberately excluded from GitHub installer artifacts because model weights make it several gigabytes.

Omit --models to produce the smaller analyzer-only *-offline-setup.exe; model weights will then download when an analysis backend is first used.

Use offline-stage to create and inspect the payload without building an installer:

cargo desktop offline-stage --vendor /path/to/nightingale-data/vendor

Stage and inspect model weights independently:

cargo desktop offline-models-stage --models /path/to/nightingale-data/models

To migrate a previously staged single archive into multipart form without recompressing it:

cargo desktop offline-split

Wrap an existing standard Windows setup executable and staged payload without rebuilding either:

cargo desktop offline-wrap \
  --bundle target/offline-vendor/windows-x86_64 \
  --models-bundle target/offline-models/windows-x86_64

The completed Windows launcher can verify its embedded analyzer and adjacent model payload without changing the system:

Nightingale_1.0.0_x64-complete-offline-setup\Nightingale_1.0.0_x64-complete-offline-setup.exe --verify-only

Verify the complete archive by extracting it to a disposable folder and starting its relocated Python imports and ffmpeg binary:

cargo desktop offline-verify

Verify the staged model cache with the same full extraction and hash checks:

cargo desktop offline-models-verify

The analyzer environment can exceed 6 GB before compression and the model cache can add several more gigabytes. Keep enough free space for the source data, staged payloads, verification extraction, and final installer at the same time.

Local builds omit signed updater archives when TAURI_SIGNING_PRIVATE_KEY is unavailable, so the installer command still exits successfully. Tagged GitHub releases keep updater artifacts enabled and sign them with the repository secret.

Supported platforms

PlatformTarget
Linux x86_64x86_64-unknown-linux-gnu
Linux aarch64aarch64-unknown-linux-gnu
macOS ARMaarch64-apple-darwin
macOS Intelx86_64-apple-darwin
Windows x86_64x86_64-pc-windows-msvc

Releasing

Releases are cut by .github/workflows/release.yml on any v* tag push. The workflow:

  1. Verifies the tag matches the version in client/src-tauri/tauri.conf.json, client/src-tauri/Cargo.toml, and client/package.json.
  2. Extracts the matching ## [<version>] section from CHANGELOG.md as the release body.
  3. Creates a draft release and, in parallel, builds and uploads:
    • Linux x86_64: .deb, .rpm (on ubuntu-22.04)
    • Linux aarch64: .deb, .rpm (on ubuntu-24.04-arm)
    • macOS ARM / Intel: .dmg + .app.tar.gz (+ .sig) for the in-app updater
    • Windows x86_64: *-setup.exe (NSIS, + .sig), *_en-US.msi (+ .sig)
    • latest.json covering darwin-aarch64, darwin-x86_64, and windows-x86_64 โ€” Linux is intentionally absent since the updater plugin isn't compiled in for Linux.
  4. Leaves the release as a draft. Smoke-test the artifacts from the draft, then flip it to Published with the "Set as the latest release" checkbox in the GitHub Releases UI to make https://github.com/rzru/nightingale/releases/latest/download/latest.json (the URL hard-coded in tauri.conf.json) resolve to it and start rolling out the in-app update.

For test installers without updater or Apple signing keys, run .github/workflows/installers.yml manually. It uploads Apple Silicon and Intel .dmg files plus a Windows NSIS .exe, each with a SHA-256 checksum.

Cutting a release:

# bump versions in client/src-tauri/tauri.conf.json, client/src-tauri/Cargo.toml, client/package.json
# add a `## [<version>] - YYYY-MM-DD` section to CHANGELOG.md
git tag v<version>
git push origin v<version>

Required repository secrets:

SecretPurpose
TAURI_SIGNING_PRIVATE_KEYMinisign private key whose public counterpart is the pubkey in tauri.conf.json. Generate once with pnpm tauri signer generate.
TAURI_SIGNING_PRIVATE_KEY_PASSWORDPassword for the signing key. Omit the secret entirely if the key was generated passwordless โ€” GitHub rejects empty-string secrets, and a missing one resolves to empty at workflow runtime, which is what minisign expects.
PIXABAY_API_KEYEmbedded at compile time so release builds can fetch video backgrounds.

Contributing

Contributions are welcome, but Nightingale follows a discussion-first process: before writing any code for a new feature or change, please start a discussion thread so we can agree on whether it fits the app. Only once a discussion reaches approved status will a corresponding pull request be accepted.

See CONTRIBUTING.md for the full workflow.

Support the project

Nightingale is open-source, free, and built by one person in their spare time. If it brings you joy and you want to help keep development going, you can chip in:

  • Patreon โ€” recurring monthly support.
  • Ko-fi โ€” one-off tip, no account required.

Every bit helps cover site hosting, hardware for testing, and the time spent shipping new features. Thank you.

License

GPL-3.0-or-later โ€” see LICENSE.

Contributors

rzru

151 commits

BearTeddy

16 commits

Velheor9001

5 commits

josx

1 commits

BearTeddy/nightingale-vocal-studio

Nightingale fork with Vocal Studio, pitch coaching, karaoke recording, and YouTube import

0

stars

174

commits

TypeScript

primary language

Sep 8, 2026

updated

README

Nightingale

Karaoke from any song in your music library, powered by neural networks.

Build Docker Pulls Stars License Patreon Ko-fi


[!IMPORTANT] This repository is an independently modified fork of rzru/nightingale. It keeps the upstream GPL-3.0-or-later license and adds the Nightingale Vocal Studio, local YouTube importing, melody extraction and correction, strict pitch coaching, and vocal recording/export workflows. See FORK.md for attribution, branding, and packaging details.

Nightingale scans your music folder, Plex Media Server, Jellyfin server, Navidrome server, or self-hosted web library; separates lead vocals from instrumentals using the UVR Karaoke model (or Demucs); transcribes lyrics with word-level timestamps via WhisperX; and plays it all back with synchronized highlighting, pitch scoring, key/tempo controls, profiles, and dynamic backgrounds.

The standard installer ships as a small desktop app and bootstraps Python, ffmpeg, and ML packages automatically on first launch. An offline installer build can embed the already-provisioned analyzer runtime in the installer, so Python and package setup does not need a network connection.

Features

Vocal Studio fork additions

  • YouTube and playlist import with highest-quality media selection, Unicode-safe metadata, and automatic library naming.
  • JOYSOUND-style pitch highway with strict octave-aware scoring, phrase feedback, Coach and Game modes, and editable melody maps.
  • Vocal Studio with microphone checkup, full vocal-range references, adaptive pitch and ear-training exercises, song-phrase loops, and practice history.
  • Local vocal recording with 24-bit dry masters, synchronized performance mixes, recoverable sessions, and optional M4A or MP4 export.
  • Windows-first setup with a configurable data directory, Desktop shortcuts, and automatic first-run provisioning of the analyzer runtime.

Library & sources

๐Ÿ“ Folder library โ€” point at any folder and Nightingale scans supported audio, video, and UltraStar files inside.

๐ŸŸ  Plex โ€” connect to a local, remote, or LAN-only Plex Media Server, select one or more music libraries, and import tracks, associated music video clips, covers, and read-only playlists. Hosted Plex sign-in discovers servers; an advanced PMS URL + token flow works without plex.tv during normal operation.

๐ŸŽฌ Jellyfin โ€” play straight from your Jellyfin library. Songs cache locally on first play so karaoke runs the same as a folder library.

๐Ÿ’ฟ Navidrome โ€” connect to Navidrome for audio libraries. Login details are kept encrypted on disk.

๐ŸŒ Self-hosted web mode โ€” run Nightingale on a Linux box on your home network and open it from phones, laptops, tablets, and TVs at <hostname>.local. See docs/self-hosted. Also runs in Docker (CPU or CUDA/GPU).

๐Ÿงญ Sidebar + library filters โ€” browse by quick filters, metadata cleanup buckets, artists, albums, and existing playlists from Plex, Jellyfin, Navidrome, or folder-library .m3u / .m3u8 / .pls files. Analyze All and optional auto-analysis help queue your library faster, and the sidebar/song list remember scroll position when you come back.

๐Ÿ—‚๏ธ Flexible storage โ€” choose the main data folder during setup, then split cache, models, videos, and vendor tools into separate folders from Settings when needed.

๐Ÿ“ฆ Self-contained โ€” ffmpeg, uv, Python, PyTorch, and ML packages are downloaded automatically during setup. Video backgrounds are pre-downloaded so the first session is ready to go.

Lyrics & audio

๐ŸŽค Stem separation โ€” isolates lead vocals from instrumentals using the UVR Karaoke model (default) or Demucs, with adjustable guide vocal volume. The karaoke model preserves backing vocals in the instrumental for a more natural sound.

๐Ÿ“ Word-level lyrics โ€” automatic transcription with alignment, or fetched from LRCLIB when available.

โœ๏ธ Lyrics editor with LRCLIB browser โ€” edit lyrics, browse LRCLIB matches, or paste your own LRC / Enhanced LRC from a song's Actions button. Timed LRC is used as-is (optionally skipping stem separation to sing over the original mix); plain lyrics run alignment.

๐Ÿˆฏ CJK lyric support โ€” Japanese, Chinese, Cantonese, and Korean songs get per-character forced alignment and romanized readings (Hepburn / pinyin / Jyutping / Revised Romanization) shown above each token.

๐Ÿ—ฃ๏ธ Pluggable ASR engines โ€” choose Whisper (default, broad language coverage) or Parakeet v3 (experimental) for ~25 European languages, with NeMo on CUDA and ONNX Runtime everywhere else.

โšก Pluggable forced alignment โ€” keep WhisperX's aligner (default) or switch on an experimental backend: GPU forced alignment (torchaudio forced_align) for faster word timestamps on CUDA and Apple Silicon, or the Qwen aligner (Qwen3-ForcedAligner-0.6B) which timestamps 11 languages incl. CJK in a single pass on CUDA/MPS/CPU. Both fall back to WhisperX automatically.

๐ŸŽผ UltraStar Deluxe songs (experimental) โ€” drop USDX song folders (.txt or .usdx plus sibling audio/vocals/instrumental/video) into your library; pitch and lyric data come from the file directly, no analyzer pass needed. See docs/usdx.

Playback & visuals

๐ŸŽฏ Pitch scoring โ€” real-time microphone input with pitch detection, star ratings, and per-song scoreboards.

๐ŸŽš๏ธ Key & tempo shifts โ€” adjust song key and tempo after analysis, with cached playback variants for quick retries.

๐ŸŽฌ Video files โ€” drop video files (.mp4, .mkv, etc.) into your music folder; vocals are separated from the audio track and the original video plays as a synchronized background.

๐ŸŒŒ Audio-reactive backgrounds โ€” 10 GPU shaders that react to your microphone in real time (Plasma, Waves, Nebula, Starfield, Sonar, Voronoi, Vortex, Metaballs, Spectrum, Oscilloscope), Pixabay video loops in 5 flavors (Nature, Underwater, Space, City, Countryside), plus source-video playback for video files.

๐ŸŽ™๏ธ Mic monitoring + latency test โ€” optionally route your live mic into playback, adjust monitor gain (0โ€“200%), and run a beep-based latency test from Settings so scoring lines up with your room.

Quality of life

๐Ÿ‘ค Profiles โ€” create and switch between player profiles; scores are tracked per profile.

๐ŸŽฎ Gamepad support โ€” full navigation and control via gamepad (D-pad, sticks, face buttons).

๐Ÿ“บ Adaptive + touch-friendly UI โ€” scales from phones/tablets to 4K TVs, with on-screen playback controls on touch devices.

โฌ†๏ธ In-app updates โ€” on macOS and Windows, auto-checks for new releases at launch, badges the sidebar avatar when one is available, and downloads and installs signed updates with one click. Linux is manual: the Update entry opens GitHub Releases for you to grab the new build.

Quick start

Download the latest release for your platform from the Releases page and run it. On first launch, Nightingale shows setup steps, lets you pick a data folder, then installs the Python environment and ML models automatically.

Updates

On macOS and Windows, Nightingale checks for new releases once at launch. When one is available, the sidebar avatar grows a small green dot and the Update entry in the dropdown menu opens a dialog with the release notes. Click Install & Restart and the app downloads the signed bundle, installs it, and relaunches. On Windows the installer runs in passive mode โ€” a small progress window flashes and the app comes back automatically once the install finishes.

Linux

Auto-update is not supported on Linux โ€” the app ships without the updater plugin. The Update entry still appears in the sidebar menu, but it just opens a dialog explaining this with a one-click button to the Releases page so you can grab the new .deb or .rpm and install it the usual way for your distro.

macOS

The manual Installer builds workflow creates separate .dmg installers for Apple Silicon and Intel Macs without requiring release-signing secrets. Open the workflow in GitHub Actions, choose Run workflow, then download the artifact matching the Mac's processor.

macOS quarantines files downloaded from the internet. Since Nightingale isn't signed with an Apple Developer ID, Gatekeeper will block it with a message like "app is damaged and can't be opened". To fix this, remove the quarantine attribute after moving the Nightingale.app to Applications:

xattr -cr /Applications/Nightingale.app

Supported formats

Audio: .mp3, .flac, .ogg, .opus, .wav, .m4a, .aac, .wma. Video: .mp4, .mkv, .avi, .webm, .mov, .m4v. UltraStar: .usdx, plus .txt files whose contents look like USDX.

Controls

ActionKeyboardGamepad
MoveArrow keysD-pad / Left stick
Confirm / SelectEnterA (South)
Back / CancelEscapeB (East) / Start
Switch panelTabโ€”
Search songsType to filterโ€”

Playback

ActionKeyboardGamepad
Pause / ResumeSpaceStart
Exit to menuEscapeB (East)
Toggle guide vocalsGโ€”
Guide volume up/down+ / -โ€”
Cycle background themeTโ€”
Cycle video flavorFโ€”
Toggle microphoneMโ€”
Next microphoneNโ€”
Toggle mic monitoringRโ€”
Toggle fullscreenF11โ€”
Skip Intro / Skip OutroOn-screen buttonsA (South)

How it works

flowchart TD
    A["Audio or video file"] --> B["UVR Karaoke / Demucs"]
    A2["USDX bundle (.txt / .usdx)"] --> E["Tauri App (Rust + React)"]
    B -->|"vocals + instrumental"| C["LRCLIB"]
    C -->|"synced lyrics if available"| D["WhisperX or Parakeet v3 (exp.)"]
    D -->|"word-level alignment, CJK reading"| E
    E --> F["Plays instrumental + synced lyrics with pitch scoring, key/tempo, mic monitoring, audio-reactive backgrounds"]

The analyzer runs as a persistent local process: Nightingale starts it once and talks to it over a token-authenticated loopback TCP socket using newline-delimited JSON, so per-song startup overhead (model load, CUDA init) is paid only once.

Analysis results are cached using blake3 file hashes. Re-analysis only happens if the source file changes, the user triggers it manually, or you choose to shift key/tempo and create playback variants. USDX songs skip stem separation entirely when #VOCALS and #INSTRUMENTAL are provided.

Hardware

The Python analyzer uses PyTorch and auto-detects the best backend:

BackendDeviceNotes
CUDANVIDIA GPUFastest
MPSApple SiliconmacOS; WhisperX alignment falls back to CPU
CPUAnySlowest but always works

The UVR Karaoke model uses ONNX Runtime and enables CUDA acceleration automatically on NVIDIA GPUs, or CoreML on Apple Silicon.

A song typically takes 2โ€“5 minutes on GPU, 10โ€“20 minutes on CPU.

Data storage

During setup, you can choose where Nightingale stores data (default: ~/.nightingale). Most runtime data is stored in that selected data folder, while config.json and nightingale.log remain in ~/.nightingale.

Typical selected data folder layout:

<selected-data-folder>/
โ”œโ”€โ”€ cache/               # Stems, transcripts, lyrics, shifted variants, covers, playable videos
โ”œโ”€โ”€ songs.db             # SQLite song library and analysis metadata
โ”œโ”€โ”€ profiles.json        # Player profiles and scores
โ”œโ”€โ”€ videos/              # Cached Pixabay video backgrounds
โ”œโ”€โ”€ sounds/              # Sound effects (celebration)
โ”œโ”€โ”€ vendor/
โ”‚   โ”œโ”€โ”€ ffmpeg           # Downloaded ffmpeg binary
โ”‚   โ”œโ”€โ”€ uv               # Downloaded uv binary
โ”‚   โ”œโ”€โ”€ python/          # Python 3.10 installed via uv
โ”‚   โ”œโ”€โ”€ venv/            # Virtual environment with ML packages
โ”‚   โ”œโ”€โ”€ analyzer/        # Extracted analyzer Python scripts
โ”‚   โ””โ”€โ”€ .ready           # Marker indicating setup is complete
โ””โ”€โ”€ models/
    โ”œโ”€โ”€ torch/           # Demucs model cache
    โ”œโ”€โ”€ huggingface/     # WhisperX model cache
    โ””โ”€โ”€ audio_separator/ # UVR Karaoke model cache

~/.nightingale/config.json stores app settings, including the selected data folder path.

Video backgrounds

Pixabay video backgrounds use the Pixabay API. The API key is embedded in release builds. For development, create a .env file at the project root:

PIXABAY_API_KEY=your_key_here

Building from source

Prerequisites

ToolVersion
Rust1.85+ (workspace uses edition 2024)
Node.js20+
pnpmlatest
Linux onlylibwebkit2gtk-4.1-dev, libssl-dev, libayatana-appindicator3-dev, librsvg2-dev, libxdo-dev, libasound2-dev

Development

git clone <repo-url> nightingale
cd nightingale
cargo desktop dev

Release build

cargo desktop build

Offline analyzer installer

After completing setup once on the build machine, create a dependency-complete installer from that exact vendor environment and model cache:

cargo desktop offline-build \
  --vendor /path/to/nightingale-data/vendor \
  --models /path/to/nightingale-data/models

On Windows, the analyzer-only build produces one *-offline-setup.exe. When model weights would push that executable above Windows' 4 GB PE limit, the complete build automatically produces a *-complete-offline-setup/ media folder containing a runnable launcher, offline-models/ sidecars, a short README, and a sorted SHA256SUMS.txt covering every distributed file. Keep the folder together and run the .exe inside it; installation is still one command and requires no downloads. The launcher expands models directly into the configured model cache, including for upgrades that have already completed first-run setup. macOS defaults to a DMG with bundled resources. The packager excludes Python bytecode caches and transient model locks/downloads, creates deterministic tar.zst payloads, splits them into installer-safe parts, and writes SHA-256 manifests. First-run setup verifies every part's size and checksum plus the app version, operating system, architecture, and payload type before atomically extracting into the selected data folder. Interrupted atomic swaps restore the previous verified directory on retry, and a failed verification leaves an existing analyzer or model environment untouched while first-run setup can fall back to online provisioning.

Publish the normal *-setup.exe for downloads. Complete offline media is intended for local or air-gapped transfer and is deliberately excluded from GitHub installer artifacts because model weights make it several gigabytes.

Omit --models to produce the smaller analyzer-only *-offline-setup.exe; model weights will then download when an analysis backend is first used.

Use offline-stage to create and inspect the payload without building an installer:

cargo desktop offline-stage --vendor /path/to/nightingale-data/vendor

Stage and inspect model weights independently:

cargo desktop offline-models-stage --models /path/to/nightingale-data/models

To migrate a previously staged single archive into multipart form without recompressing it:

cargo desktop offline-split

Wrap an existing standard Windows setup executable and staged payload without rebuilding either:

cargo desktop offline-wrap \
  --bundle target/offline-vendor/windows-x86_64 \
  --models-bundle target/offline-models/windows-x86_64

The completed Windows launcher can verify its embedded analyzer and adjacent model payload without changing the system:

Nightingale_1.0.0_x64-complete-offline-setup\Nightingale_1.0.0_x64-complete-offline-setup.exe --verify-only

Verify the complete archive by extracting it to a disposable folder and starting its relocated Python imports and ffmpeg binary:

cargo desktop offline-verify

Verify the staged model cache with the same full extraction and hash checks:

cargo desktop offline-models-verify

The analyzer environment can exceed 6 GB before compression and the model cache can add several more gigabytes. Keep enough free space for the source data, staged payloads, verification extraction, and final installer at the same time.

Local builds omit signed updater archives when TAURI_SIGNING_PRIVATE_KEY is unavailable, so the installer command still exits successfully. Tagged GitHub releases keep updater artifacts enabled and sign them with the repository secret.

Supported platforms

PlatformTarget
Linux x86_64x86_64-unknown-linux-gnu
Linux aarch64aarch64-unknown-linux-gnu
macOS ARMaarch64-apple-darwin
macOS Intelx86_64-apple-darwin
Windows x86_64x86_64-pc-windows-msvc

Releasing

Releases are cut by .github/workflows/release.yml on any v* tag push. The workflow:

  1. Verifies the tag matches the version in client/src-tauri/tauri.conf.json, client/src-tauri/Cargo.toml, and client/package.json.
  2. Extracts the matching ## [<version>] section from CHANGELOG.md as the release body.
  3. Creates a draft release and, in parallel, builds and uploads:
    • Linux x86_64: .deb, .rpm (on ubuntu-22.04)
    • Linux aarch64: .deb, .rpm (on ubuntu-24.04-arm)
    • macOS ARM / Intel: .dmg + .app.tar.gz (+ .sig) for the in-app updater
    • Windows x86_64: *-setup.exe (NSIS, + .sig), *_en-US.msi (+ .sig)
    • latest.json covering darwin-aarch64, darwin-x86_64, and windows-x86_64 โ€” Linux is intentionally absent since the updater plugin isn't compiled in for Linux.
  4. Leaves the release as a draft. Smoke-test the artifacts from the draft, then flip it to Published with the "Set as the latest release" checkbox in the GitHub Releases UI to make https://github.com/rzru/nightingale/releases/latest/download/latest.json (the URL hard-coded in tauri.conf.json) resolve to it and start rolling out the in-app update.

For test installers without updater or Apple signing keys, run .github/workflows/installers.yml manually. It uploads Apple Silicon and Intel .dmg files plus a Windows NSIS .exe, each with a SHA-256 checksum.

Cutting a release:

# bump versions in client/src-tauri/tauri.conf.json, client/src-tauri/Cargo.toml, client/package.json
# add a `## [<version>] - YYYY-MM-DD` section to CHANGELOG.md
git tag v<version>
git push origin v<version>

Required repository secrets:

SecretPurpose
TAURI_SIGNING_PRIVATE_KEYMinisign private key whose public counterpart is the pubkey in tauri.conf.json. Generate once with pnpm tauri signer generate.
TAURI_SIGNING_PRIVATE_KEY_PASSWORDPassword for the signing key. Omit the secret entirely if the key was generated passwordless โ€” GitHub rejects empty-string secrets, and a missing one resolves to empty at workflow runtime, which is what minisign expects.
PIXABAY_API_KEYEmbedded at compile time so release builds can fetch video backgrounds.

Contributing

Contributions are welcome, but Nightingale follows a discussion-first process: before writing any code for a new feature or change, please start a discussion thread so we can agree on whether it fits the app. Only once a discussion reaches approved status will a corresponding pull request be accepted.

See CONTRIBUTING.md for the full workflow.

Support the project

Nightingale is open-source, free, and built by one person in their spare time. If it brings you joy and you want to help keep development going, you can chip in:

  • Patreon โ€” recurring monthly support.
  • Ko-fi โ€” one-off tip, no account required.

Every bit helps cover site hosting, hardware for testing, and the time spent shipping new features. Thank you.

License

GPL-3.0-or-later โ€” see LICENSE.

Contributors

rzru

151 commits

BearTeddy

16 commits

Velheor9001

5 commits

josx

1 commits

Languages

TypeScript

53.2%

Rust

33.6%

Python

6.2%

Shell

2.4%

Astro

2.3%

GLSL

1.5%