https://github.com/vicrodh/qbz
QBZ is a Qobuz native desktop player for Linux - No, it is not a wrapper for the webplayer.
https://github.com/vicrodh/qbz
linux opensource qobuz qobuz-desktop-player rust
Last synced: 2 months ago
JSON representation
QBZ is a Qobuz native desktop player for Linux - No, it is not a wrapper for the webplayer.
- Host: GitHub
- URL: https://github.com/vicrodh/qbz
- Owner: vicrodh
- License: mit
- Created: 2026-01-09T14:46:50.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2026-01-16T06:36:42.000Z (6 months ago)
- Last Synced: 2026-01-16T13:43:28.350Z (6 months ago)
- Topics: linux, opensource, qobuz, qobuz-desktop-player, rust
- Language: Svelte
- Homepage: https://qbz.lol/
- Size: 9.02 MB
- Stars: 20
- Watchers: 1
- Forks: 1
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# QBZ
QBZ is a free and open source high-fidelity streaming client for Linux (with experimental macOS support) with native playback. It is a real desktop application — not a web wrapper — with DAC passthrough, per-track sample rate switching, exclusive mode, and bit-perfect audio delivery.
No API keys needed. No telemetry. No tracking. Just music.
## Legal / Branding
- This application uses the Qobuz API but is not certified by Qobuz.
- Qobuz is a trademark of Qobuz. QBZ is not affiliated with, endorsed by, or certified by Qobuz.
- **Offline cache** is a temporary playback store for listening without an internet connection while you have a valid subscription. If your subscription becomes invalid, QBZ will remove all cached content after 3 days.
- **Local library** is a "bring your own music" feature — play your own files with bit-perfect audio and the full QBZ interface, no streaming subscription required.
- Qobuz Terms of Service: https://www.qobuz.com/us-en/legal/terms
## Why QBZ
Browsers cap audio output at 48 kHz and resample everything through WebAudio. QBZ uses a native playback pipeline with direct device control so your DAC receives the original resolution — up to 24-bit / 192 kHz — with no forced resampling.
## Installation
### Arch Linux (AUR)
```bash
yay -S qbz-bin # or paru -S qbz-bin
```
### Flatpak (Flathub)
```bash
flatpak install flathub com.blitzfc.qbz
```
> **Audiophiles:** Flatpak sandboxing limits PipeWire bit-perfect. Use ALSA Direct backend for guaranteed bit-perfect in Flatpak, or install via native packages for full PipeWire support.
### Snap
```bash
sudo snap install qbz-player
sudo snap connect qbz-player:alsa
sudo snap connect qbz-player:pipewire
```
> **Note:** After installing, connect ALSA and PipeWire interfaces for full audio support. MPRIS media keys work out of the box.
### APT Repository (Debian/Ubuntu/Mint)
```bash
curl -fsSL https://vicrodh.github.io/qbz-apt/qbz-archive-keyring.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/qbz-archive-keyring.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/qbz-archive-keyring.gpg arch=$(dpkg --print-architecture)] https://vicrodh.github.io/qbz-apt stable main" | sudo tee /etc/apt/sources.list.d/qbz.list
sudo apt update && sudo apt install qbz
```
> Requires glibc 2.38+ (Ubuntu 24.04+, Debian 13+). For older releases use Flatpak, Snap, or AppImage.
### RPM (Fedora/openSUSE)
Download from [Releases](https://github.com/vicrodh/qbz/releases): `sudo dnf install ./qbz-*.rpm`
> Requires glibc 2.38+ (Fedora 39+, openSUSE Tumbleweed).
### Gentoo
```bash
eselect repository add qbz-overlay git https://github.com/vicrodh/qbz-overlay.git
emerge --sync qbz-overlay
emerge media-sound/qbz-bin # prebuilt binary
# or
emerge media-sound/qbz # build from source
```
### NixOS / Nix
Add the flake input to your `flake.nix`:
```nix
inputs.qbz.url = "github:vicrodh/qbz";
```
**NixOS (system-wide):**
```nix
{pkgs, inputs, ...}:
{
environment.systemPackages = [
inputs.qbz.packages.${pkgs.system}.default
];
}
```
**Home Manager:**
```nix
{pkgs, inputs, ...}:
{
home.packages = [
inputs.qbz.packages.${pkgs.system}.default
];
}
```
> QBZ is also available in [nixpkgs](https://github.com/NixOS/nixpkgs) as `qbz`.
### AppImage
Download from [Releases](https://github.com/vicrodh/qbz/releases): `chmod +x QBZ.AppImage && ./QBZ.AppImage`
### macOS (Experimental)
> **QBZ is a Linux-first application.** macOS support is experimental and limited. Features like PipeWire, ALSA Direct, casting, and device control are unavailable.
Download the unsigned DMG from [Releases](https://github.com/vicrodh/qbz/releases).
Since the DMG is unsigned, you may need to allow it in System Settings > Privacy & Security after first launch.
## Features
### Audio and Playback
- **Bit-perfect playback** with DAC passthrough and per-track sample rate switching (44.1–192 kHz)
- **Four audio backends:** PipeWire, ALSA, ALSA Direct (hw: bypass), PulseAudio
- **HiFi Wizard** — guided bit-perfect configuration with real DAC capability detection
- Native decoding: FLAC, MP3, AAC, ALAC, WavPack, Ogg Vorbis, Opus (Symphonia)
- Gapless playback on all backends
- **Loudness normalization** (EBU R128) with ReplayGain support
- Two-level audio cache with next-track prefetching
- Streaming playback — start listening before download completes
### Queue and Library
- Queue with shuffle, repeat (track/queue/off), and history
- Favorites and playlists from your Qobuz account
- **Qobuz playlist follow/unfollow** — subscribe natively, syncs across all Qobuz clients
- **Local library** — directory scanning, metadata extraction, CUE sheets, SQLite indexing
- Tag editor with sidecar storage (preserves original files)
- Virtualized lists for large libraries
### Qobuz Connect
Multi-device playback control using Qobuz's real-time streaming protocol.
- **Renderer mode** — receive playback commands from your phone, tablet, or web player
- **Controller mode** — control remote devices from QBZ
- Server-authoritative queue sync across all devices
- Bidirectional transport: play, pause, skip, seek, shuffle, repeat, volume
### Casting
- **Chromecast** and **DLNA/UPnP** discovery and streaming
- Seamless playback handoff to network devices
### Integrations
- **MPRIS** media controls and media keys
- **Last.fm** scrobbling and now-playing
- **ListenBrainz** scrobbling with offline queue
- **MusicBrainz** artist enrichment, musician credits, relationships (no telemetry — one-way pull)
- **Discogs** artwork for local library
- Playlist import from Spotify, Apple Music, Tidal, Deezer
- Desktop notifications with artwork
### Immersive Player
- Full-screen player with tabbed panel system
- **17+ visualization panels:** spectrum, oscilloscope, spectrogram, Linebed (3D terrain), Laser, Tunnel, Comet, coverflow, and more
- Synchronized lyrics with line-by-line display
- Queue, track info, history, and suggestions panels
### Discovery
- **Scene Discovery** — explore artists by location and musical scene (MusicBrainz-powered)
- **3-tab Home:** customizable Home, Editor's Picks, personalized For You
- Genre filtering, artist similarity engine, radio stations
- Musician pages, label pages, album credits
### Interface
- 26+ themes (Dark, OLED, Nord, Dracula, Tokyo Night, Catppuccin, Breeze, Adwaita...)
- Auto-theme from DE, wallpaper, or custom image
- Focus mode, mini player, PDF booklet viewer
- Configurable keyboard shortcuts, UI zoom 80–200%
- **5 languages:** English, Spanish, German, French, Portuguese
- Offline mode with automatic reconnection
## Tech Stack
| Layer | Technology |
|-------|-----------|
| **Desktop shell** | Rust + Tauri 2.0 |
| **Frontend** | SvelteKit + Svelte 5 (runes) + TypeScript + Vite |
| **Audio decoding** | Symphonia (all codecs) via rodio 0.22 |
| **Audio backends** | PipeWire, ALSA (alsa-rs), ALSA Direct (hw:), PulseAudio |
| **Networking** | reqwest (rustls-tls), axum (local API server) |
| **Database** | rusqlite (bundled SQLite, WAL mode) |
| **PDF** | MuPDF 0.6 (native rendering) |
| **Desktop** | souvlaki (MPRIS), ashpd (XDG notifications), keyring |
| **Casting** | rust_cast (Chromecast), rupnp (DLNA/UPnP), mdns-sd |
| **i18n** | svelte-i18n (5 locales) |
### Multi-Crate Architecture
```
crates/
qbz-models/ Shared domain types
qbz-audio/ Audio backends, loudness, device management
qbz-player/ Playback engine, streaming, queue
qbz-qobuz/ Qobuz API client and auth
qbz-core/ Orchestrator (player + audio + API)
qbz-library/ Local library scanning and metadata
qbz-integrations/ Last.fm, ListenBrainz, MusicBrainz, Discogs
qbz-cache/ L1 memory + L2 disk audio caching
qbz-cast/ Chromecast, DLNA/UPnP
qconnect-protocol/ Qobuz Connect protobuf wire format
qconnect-core/ Queue and renderer domain models
qconnect-app/ Application logic and concurrency
qconnect-transport-ws/ WebSocket transport with qcloud framing
```
## Building from Source
### Prerequisites
- Rust (latest stable), Node.js 20+, Linux or macOS with audio support
### System Dependencies
**Debian/Ubuntu:**
```bash
sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libasound2-dev \
libayatana-appindicator3-dev librsvg2-dev libssl-dev pkg-config
```
**Fedora:**
```bash
sudo dnf install webkit2gtk4.1-devel gtk3-devel alsa-lib-devel \
libappindicator-gtk3-devel librsvg2-devel openssl-devel pkg-config
```
**Arch Linux:**
```bash
sudo pacman -S webkit2gtk-4.1 gtk3 alsa-lib libappindicator-gtk3 \
librsvg openssl pkg-config
```
**Gentoo:**
```bash
sudo emerge net-libs/webkit-gtk:4.1 x11-libs/gtk+:3 media-libs/alsa-lib \
dev-libs/libayatana-appindicator gnome-base/librsvg dev-libs/openssl virtual/pkgconfig
```
### Build
```bash
git clone https://github.com/vicrodh/qbz.git && cd qbz
npm install
npm run tauri dev # development
npm run tauri build # production (DEB, RPM, AppImage)
```
### API Proxy
Last.fm, Discogs, Tidal, Spotify-import, and MusicBrainz traffic goes through a hosted Cloudflare Workers proxy (`qbz-api-proxy.blitzkriegfc.workers.dev`) that holds all credentials server-side. Both pre-built releases and source builds use it out of the box — **no API keys or `.env` file required**.
If you want to run against your own proxy (for development, or if you fork QBZ), the proxy source lives at [`vicrodh/qbz-api-proxy`](https://github.com/vicrodh/qbz-api-proxy). Deploy it with `wrangler deploy` and then edit the `*_PROXY_URL` constants in `src-tauri/src/lastfm/mod.rs`, `discogs/mod.rs`, `playlist_import/providers/tidal.rs`, and `musicbrainz/client.rs` to point at your worker before rebuilding.
### Environment Variables
| Variable | Effect |
|----------|--------|
| `QBZ_HARDWARE_ACCEL=0` | Disable GPU rendering (crash recovery) |
| `QBZ_FORCE_X11=1` | Use XWayland (NVIDIA Wayland issues) |
| `QBZ_SOFTWARE_RENDER=1` | Force Mesa llvmpipe (VMs) |
| `QBZ_DISABLE_DMABUF=1` | Disable DMA-BUF (Intel Arc EGL crashes) |
If QBZ crashes on startup: `qbz --reset-graphics`
## Known Issues
- **Hi-Res seeking** — seeking in tracks >96kHz can take 10-20s (decoder must scan from start). Use prev/next for instant navigation.
- **ALSA Direct** — exclusive access blocks other apps. Use DAC/amplifier physical volume control.
- **PipeWire bit-perfect in Flatpak** — limited by sandbox. Use ALSA Direct or native packages.
## Documentation
User guides, audio configuration, integrations, and troubleshooting: **[QBZ Wiki](https://github.com/vicrodh/qbz/wiki)** (work in progress).
## Diagram
```mermaid
flowchart TD
subgraph group_frontend["Frontend"]
node_ui_shell["Svelte UI
sveltekit app"]
node_ui_state["Stores & Services
ui orchestration"]
node_ui_views["Views
screen layer"]
node_ui_remote["Remote Runtime
qconnect client
[qconnectRuntime.ts]"]
end
subgraph group_tauri["Desktop App"]
node_tauri_backend["Tauri Backend
native backend"]
node_cmd_v2["Commands v2
backend api"]
node_cmd_legacy["Legacy Commands
compat api"]
node_app_audio["App Audio
backend audio"]
node_app_player["App Player
playback engine"]
node_app_library["App Library
library service"]
node_app_cache["Offline Cache
local cache"]
node_app_cast["Casting
device handoff"]
node_app_connect["Qconnect Service
remote control bridge"]
end
subgraph group_crates["Rust Crates"]
node_rust_player["qbz-player
playback core"]
node_rust_audio["qbz-audio
audio backend"]
node_rust_cache["qbz-cache
audio cache"]
node_rust_qobuz["qbz-qobuz
api client"]
node_rust_library["qbz-library
library index"]
node_rust_cast["qbz-cast
cast stack"]
node_rust_connect["qconnect stack
protocol stack"]
node_rust_integrations["qbz-integrations
external services"]
end
subgraph group_service["Daemon"]
node_daemon["qbzd
local daemon"]
end
subgraph group_packaging["Packaging"]
node_packaging_ci["Packaging & CI
release automation
[workflows]"]
end
node_ui_shell -->|"uses"| node_ui_state
node_ui_shell -->|"renders"| node_ui_views
node_ui_state -->|"calls"| node_cmd_v2
node_ui_state -->|"syncs"| node_ui_remote
node_ui_remote -->|"bridges"| node_app_connect
node_tauri_backend -->|"exposes"| node_cmd_v2
node_tauri_backend -.->|"keeps"| node_cmd_legacy
node_cmd_v2 -->|"drives"| node_app_player
node_cmd_v2 -->|"queries"| node_app_library
node_cmd_v2 -->|"reads/writes"| node_app_cache
node_cmd_v2 -->|"controls"| node_app_cast
node_cmd_v2 -->|"syncs"| node_rust_integrations
node_app_player -->|"uses"| node_rust_player
node_app_audio -->|"uses"| node_rust_audio
node_app_player -->|"prefetches"| node_rust_cache
node_app_library -->|"indexes"| node_rust_library
node_app_library -->|"enriches"| node_rust_qobuz
node_app_cast -->|"delegates"| node_rust_cast
node_app_connect -->|"implements"| node_rust_connect
node_daemon -->|"coordinates"| node_app_player
node_daemon -->|"serves"| node_app_library
node_daemon -->|"hosts"| node_app_connect
node_packaging_ci -.->|"builds"| node_tauri_backend
node_packaging_ci -.->|"packages"| node_daemon
node_packaging_ci -.->|"bundles"| node_ui_shell
click node_ui_shell "https://github.com/vicrodh/qbz/tree/main/src"
click node_ui_state "https://github.com/vicrodh/qbz/tree/main/src/lib/stores"
click node_ui_views "https://github.com/vicrodh/qbz/tree/main/src/lib/components/views"
click node_ui_remote "https://github.com/vicrodh/qbz/blob/main/src/lib/services/qconnectRuntime.ts"
click node_tauri_backend "https://github.com/vicrodh/qbz/tree/main/src-tauri/src"
click node_cmd_v2 "https://github.com/vicrodh/qbz/tree/main/src-tauri/src/commands_v2"
click node_cmd_legacy "https://github.com/vicrodh/qbz/tree/main/src-tauri/src/commands"
click node_app_audio "https://github.com/vicrodh/qbz/tree/main/src-tauri/src/audio"
click node_app_player "https://github.com/vicrodh/qbz/tree/main/src-tauri/src/player"
click node_app_library "https://github.com/vicrodh/qbz/tree/main/src-tauri/src/library"
click node_app_cache "https://github.com/vicrodh/qbz/tree/main/src-tauri/src/offline_cache"
click node_app_cast "https://github.com/vicrodh/qbz/tree/main/src-tauri/src/cast"
click node_app_connect "https://github.com/vicrodh/qbz/blob/main/src-tauri/src/qconnect_service.rs"
click node_rust_player "https://github.com/vicrodh/qbz/tree/main/crates/qbz-player/src"
click node_rust_audio "https://github.com/vicrodh/qbz/tree/main/crates/qbz-audio/src"
click node_rust_cache "https://github.com/vicrodh/qbz/tree/main/crates/qbz-cache/src"
click node_rust_qobuz "https://github.com/vicrodh/qbz/tree/main/crates/qbz-qobuz/src"
click node_rust_library "https://github.com/vicrodh/qbz/tree/main/crates/qbz-library/src"
click node_rust_cast "https://github.com/vicrodh/qbz/tree/main/crates/qbz-cast/src"
click node_rust_connect "https://github.com/vicrodh/qbz/tree/main/crates/qconnect-protocol/src"
click node_rust_integrations "https://github.com/vicrodh/qbz/tree/main/crates/qbz-integrations/src"
click node_daemon "https://github.com/vicrodh/qbz/tree/main/crates/qbzd/src"
click node_packaging_ci "https://github.com/vicrodh/qbz/blob/main/.github/workflows"
classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_ui_shell,node_ui_state,node_ui_views,node_ui_remote toneBlue
class node_tauri_backend,node_cmd_v2,node_cmd_legacy,node_app_audio,node_app_player,node_app_library,node_app_cache,node_app_cast,node_app_connect toneAmber
class node_rust_player,node_rust_audio,node_rust_cache,node_rust_qobuz,node_rust_library,node_rust_cast,node_rust_connect,node_rust_integrations toneMint
class node_daemon toneRose
class node_packaging_ci toneIndigo
```
## Open Source
QBZ is MIT-licensed. No telemetry, no tracking, no hidden services. Built for Linux audio enthusiasts, with experimental macOS support.
## Contributing
Contributions welcome. Please read `CONTRIBUTING.md` before submitting issues or pull requests.
### Contributors
- [@vorce](https://github.com/vorce)
- [@boxdot](https://github.com/boxdot)
- [@arminfelder](https://github.com/arminfelder)
- [@afonsojramos](https://github.com/afonsojramos) — macOS port
- [@GwendalBeaumont](https://github.com/GwendalBeaumont) — i18n
- [@AdamArstall](https://github.com/AdamArstall)
## License
MIT
## Fancy charts
