Kopuz is a modern, lightweight, music player application built with Rust and the Dioxus framework. It provides a clean and responsive interface for managing and enjoying your local music collection.
The kopuz is an ancient Turkic string instrument and is often considered the ancestor of many Central Asian lutes. It was traditionally used by bards and shamans.
The Kyrgyz komuz is not the same instrument, but likely a descendant of the kopuz. The Kazakh kobyz is also related, though it is bowed rather than plucked. In contrast, the Tuvan/Yakut xomus (jaw harp) is unrelated, despite the similar name.
In Turkic legend, the kopuz is linked to Dede Korkut, a legendary bard, though this is mythological rather than historical.
Kopuz allows you to scan your local directories for audio files, stream from your Jellyfin or Subsonic (Navidrome, etc.) server, or connect YouTube Music as a streaming backend — automatically organizing everything into a browsable library. You can navigate by artists, albums, genres, or explore your custom playlists. The application is built for performance and desktop integration, utilizing the power of Rust.
- Theming: Includes dynamic theming support to customize the visual appearance. You can also build your own custom theme from scratch with full color variable control.
- Native Integration: Integrates with system media controls on Linux (MPRIS), macOS (Now Playing / Remote Command Center), and Windows (System Media Transport Controls).
- Discord RPC: Embedded RPC included!!!
- Multiple Backends: Stream from your Jellyfin or Subsonic-compatible server (Navidrome works great), connect YouTube Music, or just point it at a local folder. Mix and match as you like.
- YouTube Music: Full streaming backend with a Spotify-style Discover page (recommended songs, playlists, albums, artists, and moods), rich artist profiles (banner, top songs, albums, singles, related artists), album/playlist browsing, and mix radio ("start radio" from any track). Sign in with your account for your library, Liked Music, and playlists — or run it anonymously (no sign-in) for browse, search, and playback of public tracks. See YouTube Music Setup.
- Lyrics Support: Enjoy real-time synced and plain lyrics, complete with auto-scrolling to follow along with your music.
- Favorites: Star tracks locally or sync favorites with your Jellyfin/Subsonic server.
- Playlists: Create and manage your own playlists, add individual tracks or whole albums at once, and sync playlists to your server.
- Genre Browsing: Browse your library by genre for both local and server music.
- Search: Search across artists, albums, and tracks with real-time results.
- Listening Logs: Tracks play counts locally so you can see what you actually listen to most.
- Scrobbling: Scrobble to ListenBrainz. For Jellyfin users, jellyfin-plugin-listenbrainz is recommended if you use multiple clients.
- Language Support: UI available in English, Russian, German, French, Spanish, Turkish, Ukrainian, Polish, Arabic, Greek, Hebrew, Hungarian, Indonesian, Japanese, Korean, Romanian, Brazilian Portuguese, Toki Pona, and Simplified Chinese with a streamlined experience for adding new languages.
- High Performance: Heavy background processing and an optimized library scanner ensure the app opens instantly, runs smoothly, and skips previously indexed files quickly.
- Auto-Cleanup: Automatically removes missing or deleted tracks from your library when rescanning.
- Smooth Navigation: Enjoy a polished interface where scroll positions reset properly as you browse different views and pages.
- Reduce Animations: Accessibility setting to tone down motion effects if you prefer a calmer UI.
- Equalizer: Built-in 5-band equalizer with presets and custom settings to fine-tune your sound.
- Crossfade: Blend track transitions for smoother automatic playback between songs on native desktop builds. Browser playback currently uses normal track switching.
- Channel Mode: Switch between
Stereo,Mono,Left only,Right only, andSwap L/Routput modes. - yt-dlp Integration: Download audio directly from YouTube and other
supported sites via yt-dlp. Choose your output format (Best Audio, MP3, FLAC,
WAV, or MP4 video). FLAC is not recommended since yt-dlp remuxes lossy audio
rather than decoding from a lossless source. Supports SponsorBlock, chapter
splitting, cookies, rate limiting, and more. Requires
yt-dlpinstalled on your system. - Metadata Settings: A dedicated Metadata section in Settings lets you control how artist images are sourced. Choose between Album Cover (uses the first album artwork as the artist photo, default) or Artist Photo (fetches actual artist images directly from your Jellyfin or Subsonic server). When switching to Artist Photo mode, images are fetched from the server in the background as soon as you open the Artists page. If an artist has no dedicated photo on your server, their first album cover is used as a fallback so nothing ever shows blank.
Run directly without installing:
nix run github:temidaradev/kopuzInstall to your profile:
nix profile add github:temidaradev/kopuzOn NixOS, using the flake:
Tip
This is recommended over nix profile as it installs Kopuz as a proper system
app with icon & .desktop entry.
Add Kopuz to your flake.nix inputs:
{
inputs.kopuz.url = "github:temidaradev/kopuz";
}Then pass it through to your system config and add the Cachix substituter so it downloads the pre-built binary instead of compiling:
{
nix.settings = {
substituters = ["https://kopuz.cachix.org" ];
trusted-public-keys = ["kopuz.cachix.org-1:J2X3AnAYhKTJW5S3aCLoA1ckonQXVNZMQvhZA0YAufw="];
};
}Then install the package:
{pkgs, kopuz, ...}: let
kopuzPkg = kopuz.packages.${pkgs.stdenv.hostPlatform.system}.default
in {
environment.systemPackages = [kopuzPkg];
}Install from the AUR using your preferred helper:
yay -S kopuz
# or
paru -S kopuzNote:
dioxus-climust be installed first at the version matching dioxus 0.7.x:cargo install dioxus-cli --version "^0.7"
Kopuz is soon available on Flathub. To install from source manifest:
git clone https://github.com/temidaradev/kopuz
cd kopuz
flatpak-builder --user --install --force-clean build-dir packaging/flatpak/com.temidaradev.kopuz.json
flatpak run com.temidaradev.kopuzYou can also click on the file and open it with an app provider, for example KDE discover
Important
The AppImage requires webkit2gtk-4.1 and gtk3 installed on your system.
Those dependencies are not bundled.
On most distros with a modern desktop environment, these are already present. You will need to install them manually if they are not yet installed.
On Arch-based distros, if the AppImage crashes with a WebKitNetworkProcess
error, either run it with:
LD_LIBRARY_PATH=/usr/lib ./kopuz_*.AppImageOr create symlinks once (requires sudo):
sudo mkdir -p /usr/libexec/webkit2gtk-4.1
sudo ln -s /usr/lib/webkit2gtk-4.1/WebKitNetworkProcess /usr/libexec/webkit2gtk-4.1/
sudo ln -s /usr/lib/webkit2gtk-4.1/WebKitWebProcess /usr/libexec/webkit2gtk-4.1/
sudo ln -s /usr/lib/webkit2gtk-4.1/WebKitGPUProcess /usr/libexec/webkit2gtk-4.1/Using Nix
Tip
Nix is the primary means of development for Kopuz, and it is the recommended method for getting build dependencies in a pure, reproducible environment consistent across systems.
# Using Nix3 CLI
nix developIf you are a Direnv user, use the provided .envrc:
# Using Direnv
direnv allowDirenv is recommended if you want to keep using your usershell within the development environment.
Arch Linux Based Systems
sudo pacman -S rust cargo dioxus-cli base-devel cmake pkgconf opus alsa-lib xdotool webkit2gtk-4.1 gtk3 libsoup3 opensslDebian Based Systems
sudo apt install rustc cargo build-essential cmake pkg-config libopus-dev libasound2-dev libxdo-dev libwebkit2gtk-4.1-dev libgtk-3-dev libsoup-3.0-dev libssl-dev
cargo install dioxus-cliFedora Based Systems
sudo dnf groupinstall "Development Tools" "Development Libraries"
sudo dnf install rust cargo cmake pkgconf-pkg-config opus-devel alsa-lib-devel libxdo-devel webkit2gtk4.1-devel gtk3-devel libsoup3-devel openssl-devel
cargo install --locked dioxus-cliopenSUSE Based Systems
sudo zypper install rust cargo cmake pkg-config libopus-devel alsa-devel xdotool webkit2gtk3-soup2-devel gtk3-devel libsoup3-devel libopenssl-devel
cargo install --locked dioxus-cli# Clone the repository
$ git clone https://github.com/Kopuz-org/kopuz
# Move to the cloned directory
cd kopuz
# Install npm dependencies
npm install
# Serve project with Dioxus CLI
dx serve --package kopuzQuarantine note: If you downloaded a .dmg instead, macOS may block it. Run
once to clear the quarantine flag:
xattr -d com.apple.quarantine /Applications/Kopuz.appOn macOS everything lives under your Library folders:
~/Library/Application Support/com.temidaradev.kopuz/config.json- your settings~/Library/Caches/com.temidaradev.kopuz/library.json- the scanned library~/Library/Caches/com.temidaradev.kopuz/playlists.json- your playlists~/Library/Caches/com.temidaradev.kopuz/covers/- cached album art~/Library/Caches/com.temidaradev.kopuz/offline_tracks/- downloaded tracks
On Linux it follows the XDG spec like you'd expect:
~/.config/kopuz/config.json- your settings~/.cache/kopuz/library.json- the scanned library~/.cache/kopuz/playlists.json- your playlists~/.cache/kopuz/covers/- cached album art~/.cache/kopuz/offline_tracks/- downloaded tracks
On Windows it uses your AppData folder:
%APPDATA%\temidaradev\kopuz\config\config.json- your settings%LOCALAPPDATA%\temidaradev\kopuz\cache\library.json- the scanned library%LOCALAPPDATA%\temidaradev\kopuz\cache\playlists.json- your playlists%LOCALAPPDATA%\temidaradev\kopuz\cache\covers\- cached album art%LOCALAPPDATA%\temidaradev\kopuz\cache\offline_tracks\- downloaded tracks
If covers aren't showing or the library looks off, just delete the cache folder and hit rescan.
Kopuz can use YouTube Music as a streaming backend. Add it from Settings → Media servers → Add → YouTube Music.
Playback (in both signed-in and anonymous modes) needs the
rustypipe-botguard helper to
mint the PO token YouTube requires for stream URLs. Install it once:
cargo install rustypipe-botguard --version 0.1.2The Add-server dialog has a Check rustypipe-botguard button to confirm it's
on your PATH. Without it, tracks resolve but fail to play.
The setup dialog offers two methods:
-
Sign in with a browser — kopuz opens the Google sign-in page in an isolated browser profile (a fresh, separate session; your normal browsing is never touched), waits for you to log in, and extracts the session cookies. Pick which installed Chromium-family browser to use (Chrome, Chromium, Brave, Edge, or Vivaldi). This unlocks your library, Liked Music, playlists, and followed artists.
-
Continue without signing in (anonymous) — no sign-in, no cookies. You can browse, search, open artist/album/playlist pages, start mix radio, and play public tracks. Liked Music, library playlists, and following/liking are disabled (those views show a "sign in to enable" prompt). Music Premium-only tracks can't be played anonymously.
Note
On Windows, browser sign-in is currently disabled — the Google accounts
page renders blank inside the isolated profile. Windows users get anonymous
mode automatically. Sign-in works on Linux and macOS. (Tracked as
TODO(windows-signin) in crates/server/src/ytmusic/isolated_profile.rs.)
Music Premium-locked tracks fall back to a local
yt-dlp resolve when the primary path
returns UNPLAYABLE, so having yt-dlp installed helps for those. Anonymous
mode can't play Premium-only content at all.
Kopuz is built to feel snappy even with large libraries. Here's what we do under the hood:
-
Skip what's already indexed - the scanner keeps a
HashSetof every path it's already seen, so rescans only process new files. If you have 10,000 tracks, and then add 5 new ones, Kopuz will not re-read the other 9995. This makes a huge difference, especially on HDDs. -
Parallel startup loading - on launch, library, config, playlists, and favorites all load in parallel with
tokio::join!. Before this change, everything loaded sequentially and you'd stare at a blank window for a bit. Now it's near-instant. -
Album art caching - cover images get extracted once and saved to disk (
~/.cache/kopuz/covers/on Linux,~/Library/Caches/on macOS). We also cache the macOS now-playing artwork object in memory so it doesn't re-decode the image every time the progress bar updates. -
Lazy loading images - album covers in search results, track rows, and genre views all use
loading="lazy"so we're not loading hundreds of images at once when you scroll through a big library. -
Non-blocking I/O - all the heavy stuff (metadata parsing, file scanning, saving library state) runs on
spawn_blockingthreads so the UI never freezes. The main thread stays responsive even during a full library scan. -
Smarter sorting - we use
sort_by_cached_keyinstead of regularsort_by_keyfor library views, which avoids recalculating the sort key (like.to_lowercase()) on every comparison. Small thing perhaps, but it adds up with thousands of tracks. -
HTTP caching for artwork - the custom
artwork://protocol serves images withCache-Control: public, max-age=31536000so the Webview doesn't re-request covers it already has.
Overall, these changes brought the rescan time down significantly and the app feels much more responsive, especially with libraries over 5000 tracks. Memory usage stays reasonable too since we're not holding decoded images in memory longer than needed.
- Dioxus: UI Framework
- Symphonia: Audio decoding library
- Cpal: Audio I/O library
- Lofty: Metadata parsing
- TailwindCSS: Styling framework based on CSS
- Solana: "BK84dVEMnGBP5Tya2mEaB1BQgcSBjngf1NBmRCqefxGg"
- Bitcoin: "bc1qz94yz9xvufa6hxlvjzaajgd2zyfu86arn68hu4"
- Monero: "86mz3HxTrKyYpuvx78m6pufbXdwAnoyoZBztz6HyYrnM1XP5YVrMy9jTVRY5vzgGtkizACLpFwHEdafKTMoj6y8mAVgvWMz"
- Ethereum: "0xa490D50470cdFf837B6663F7f6cBe50B157224e5"
- USDT on Solana Chain: "GYmnAcrA5MbF6cUxT2m5d5cwdfr14qSY9WFYRwXxaibW"
- Logo design by: Lucas Amorim - His Instagram Account