Skip to content
Projects

KenanSalar/Melodia has 39 GitHub stars and 2 forks. GitHot measured 0 stars in 24 hours. Last checked 2026-11-15 06:58 UTC. Last push 2026-11-13.

How these counts are measured

What you can do

  • Bit-perfect exclusive output on Linux and Windows, with a Signal Path panel that grades every stage from the file to the device
  • Gapless playback and crossfade, a 10-band equalizer, ReplayGain, and playback speed from 0.25× to 2.0×
  • Timed lyrics from .lrc files, tags, or an opt-in online lookup, romanized for around a hundred scripts
  • Internet radio from a worldwide directory or your own stream URLs, off until you switch it on

Measured star growth

in 24h
0
in 7 days
Collecting history
in 15 days
Collecting history
in 1 month
Collecting history

Net star changes over overlapping periods, not daily totals. Missing measurements are left blank. Stars measure attention, not software quality.

About

Melodia is a fast, lightweight cross-platform desktop music player build in rust and slint

Creative & Media

README.md

Original

Melodia

A fast, lightweight cross-platform desktop music player built with Slint and pure Rust.

License: AGPL v3 Version Platforms Built with Rust

A playlist opened inside My Library


Highlights

  • Bit-perfect exclusive output on Linux and Windows, with a Signal Path panel that grades every stage from the file to the device
  • Gapless playback and crossfade, a 10-band equalizer, ReplayGain, and playback speed from 0.25× to 2.0×
  • Timed lyrics from .lrc files, tags, or an opt-in online lookup, romanized for around a hundred scripts
  • Internet radio from a worldwide directory or your own stream URLs, off until you switch it on
  • Six theme families in light and dark, and Material You colors drawn from the playing artwork
  • A library that keeps up: parallel scanning, live folder watching, full-text search, smart playlists, and tag editing written back to the files
  • A responsive mini-player the window collapses into as you shrink it
  • Last.fm and ListenBrainz scrobbling, Discord Rich Presence, and the OS media controls
  • No embedded browser engine under the UI, which keeps the memory footprint small (Footprint)
  • Sixteen languages, switchable without a restart

Installation

Linux (X11 and Wayland) and Windows, on both x86_64 and aarch64. Take the latest build from the Releases page.

Format Install
.rpm (Fedora/RHEL) sudo dnf install ./melodia-*.rpm
.deb (Debian/Ubuntu) sudo apt install ./melodia-*.deb
AppImage chmod +x melodia-*.AppImage && ./melodia-*.AppImage
Tarball Extract, then ./install-linux.sh, which installs into ~/.local/share/Melodia with no sudo, so the in-app updater can replace it
Windows Run the installer

Melodia updates itself in place, minisign-signed. Release artifacts also carry build-provenance attestations, verifiable with:

gh attestation verify <file> --repo KenanSalar/Melodia

Screenshots

The shots below are a handful of the themes, all on the default aurora backdrop; Themes under Features lists the rest.

Library

My Library on the Songs tab
My Library: one page and five tabs, here on Songs with sortable, toggleable columns.
My Library on the Albums tab
Albums: a virtualized cover grid, sorted by name, year, or artist.
A playlist opened inside My Library
Detail in place: opening a playlist grows the band into its banner, tabs still in reach.
Search view
Search: a top-result card over songs, albums, artists, and genres.

Now Playing

Now Playing with the Up Next list
Up Next: the queue beside the artwork, the file's format, and the visualizer.
Now Playing with a timed lyrics sheet
Lyrics: the header switch trades Up Next for a timed sheet that follows the song line by line.

Internet Radio and Settings

Radio browse view
Internet Radio: a worldwide directory, narrowed by country, language, genre, codec, or bitrate. Off until you switch it on, under Settings ▸ Radio.
Settings on the Appearance category
Settings: thirteen categories beside the cards, searched all at once, here on the theme, variant, accent, and color style.

Mini-player

Shrink the window and the full UI collapses into a mini-player that grows with it: a one-line strip, then a card, then a column with Up Next or lyrics below.

Mini-player as a one-line strip
Strip: the most compact form, the controls on the title's line.
Mini-player as a card with window buttons
Card: the controls under the title beside larger artwork, the window buttons above.
Mini-player column with the Up Next list
Up Next: taller still, the column opens the queue under the card.
Mini-player column with a timed lyrics sheet
Lyrics: the switch in the corner trades Up Next for the timed sheet.

Features

Library: scanning, search, playlists, and tag editing
  • A three-panel first-run card: add your Music folder or any other, pick the language, theme and accent, and see every feature that reaches the network before you switch it on. Settings ▸ About reopens it
  • Parallel folder scanning, live folder watching, and incremental re-scans
  • Cue sheets: a whole-disc rip with its .cue lists as the disc's tracks, each with its own title, artist and number, and a playlist holding the whole disc holds its tracks in its place. A FLAC carrying its cue sheet inside, as a CUESHEET tag or its own CUESHEET block, splits the same way. Opening the .cue, or dropping it on the queue, queues the disc in order, and Edit Tags on its tracks saves into the .cue itself, or into the FLAC's CUESHEET tag
  • A file or a .cue opened from outside your library folders plays without joining the library, and stays as long as a playlist or the queue holds it
  • Content hashing (BLAKE3), so a moved or renamed file keeps its play counts, favorites, and place in the queue
  • A duplicate finder under Settings ▸ Library that groups the songs held more than once, labels how sure each match is, and picks the best copy to keep. Remove takes the spares out of the library, moving their plays, rating, heart and playlist places onto that copy. Their files stay on disk, and later scans skip them until you bring them back from Files kept out of the library
  • Full-text search (SQLite FTS5) over tracks, albums, artists, genres, and the people credited on a track: accent-insensitive, relevance-ranked, with a top-result card and recent history. Every list's filter box searches the same fields
  • My Library gathers everything into one page with five tabs (Songs, Albums, Artists, Genres, Playlists); opening an entity grows the tab band into its banner rather than navigating away
  • Favorites and Recently Played, each a hero banner over sortable lists and browsable card grids
  • Browse by folder, as a detailed list or a grid of cards
  • Star ratings, play and skip counts, natural sort, resizable and toggleable columns
  • Multi-selection on every list and card grid: tick one to start, click to add, shift-click for a range, and right-click to queue, rate or tag the whole set. Esc clears it
  • Copy from any right-click menu: a song's title, artist, album, "Artist - Title" or file path, an album's name, or a station's name, stream URL or website, one line per selected item
  • Undo for removals: tracks taken out of a playlist or the queue, deleted playlists, a smart playlist's rules once it is converted, Clear queue, a play that replaces a queue you built, favorites, radio stations, the equalizer's Reset, and recent searches' Clear all. A notice names what went and offers Undo, or Ctrl+Z while it is up, and waits while the pointer is over it or Melodia is in the background. Settings ▸ Accessibility turns undo off altogether, per kind, or for single items, and sets how long the notice stays
  • Tag editing for one track or many, cover art included, written straight back to the files. Artists, genres and the ten studio credits are each an editable list, beside work and movement, key, mood, ISRC, label, catalog number, barcode and medium
  • Manual and smart playlists, the latter rule-based and resolved live until you convert one to a regular playlist that keeps the tracks it holds; .m3u8 import and export, several at once as one .zip that imports back without extracting, drag-and-drop import, and reordering that moves a whole selection
  • A database backup before every schema migration, three kept
Playback: gapless, crossfade, EQ, the queue, and the mini-player
  • Gapless, including the AAC encoder delay and padding read back from iTunSMPB or the MP4 edit list, and the trailing padding a Matroska file states
  • Crossfade (1–12 s) across two decks with a clip-safe ramp, optionally skipped between same-album tracks, and under exclusive output too wherever the next track needs no change of device format
  • 10-band equalizer (31 Hz – 16 kHz) with preamp, presets, and a soft-knee limiter, from the player bar's overflow menu or Settings ▸ Effects
  • ReplayGain in track or album mode, with preamp and peak-based clip prevention, reached the same two ways
  • A queue with shuffle and repeat in a resizable side panel, which floats over the page once the window is too narrow to dock it. Playing from any list queues that list behind your pick
  • Drag tracks, albums, artists, genres, playlists, or files from your file manager into the queue or a playlist where you let go; a selection reorders together in the queue, Up Next, and the mini-player
  • Hold Previous or Next to scan through a track in audible jumps that grow the longer you hold, and hold Play/Pause to stop
  • Full-screen Now Playing with an up-next list and a spectrum, mirrored, or waveform visualizer tinted to the album's own colors
  • Right-click the playing song in the player bar for the menu its row has in a list
  • Playback speed 0.25×–2.0×, a playback-linked sleep timer, resume on startup, media keys
  • Sample-rate conversion wherever a file's rate isn't the output's or the speed isn't 1×, band-limited or a CPU-light linear (the Windows default) under Settings ▸ Output. It carries across gapless track changes and is skipped where the rates already match
  • A responsive mini-player that rearranges as you resize, from a one-line strip to a column with Up Next or lyrics, and reopens as the mini-player if you closed Melodia from it
Bit-perfect output: exclusive ALSA and WASAPI output, graded stage by stage
  • Exclusive output on Linux and Windows, off until you choose it under Settings ▸ Output. Each file's own sample rate and bit depth go straight to the device with no system mixer in between: an ALSA hw: device on Linux, asked of the sound server so it is handed back cleanly, and WASAPI exclusive mode on Windows
  • A Signal Path panel grades every stage from the file to the device and sums it up as Bit-perfect, Enhanced (only effects you chose), Converted, Lossy, or Fallback (a refused claim). Make Bit-Perfect switches off whatever you chose that changes the sound
  • A quality chip in the player bar carries that verdict and the device's rate under exclusive output, and opens the panel in one click
  • Output Device (Exclusive Device on Linux) picks the sound card to claim, and on Windows routes shared output too. An unplugged device hands playback to the default and is taken back as soon as it returns
  • A device that refuses the claim never costs you the music: playback carries on shared, and a notification and the panel say why
  • Unsupported Sample Rates can resample a file to a rate the device has rather than give up the claim, staying gapless wherever the device's rate doesn't change
  • Dither wherever samples Melodia changed are narrowed to 16 or 24 bits, while untouched samples still pass bit-exact
  • Hardware Volume turns the device's own volume control instead of scaling the samples, so the slider keeps the sound bit-perfect and the system's volume keys move it too
  • Give the Device Back When Paused hands the device to other apps after five minutes paused; pressing play takes it again
  • A choosable buffer period, a short silence for DACs that mute while switching sample rates, and on Windows a polling mode for USB devices that stutter
  • In shared mode on Linux, Match the File's Sample Rate reopens the device at each track's own rate wherever the sound server allows it
  • Unplugging the device or restarting the sound server picks playback up on the new output at the same position
Lyrics: timed sheets, an opt-in online lookup, and romanization
  • A timed sheet in Now Playing, in place of Up Next, that follows the song line by line; click a line to seek to it. Switch it on from that view's header or Settings ▸ Lyrics
  • Off by default, and off means off: while lyrics are switched off, nothing looks a sheet up or keeps one in memory
  • Read from a .lrc beside the track or from the file's own lyrics tag, so a library that already carries them needs no online lookup
  • Online lookup is off until you switch it on: nothing contacts lrclib.net until you do, and its answers are cached under your data folder rather than written into your files
  • Romanization under a line in a script you don't read, around a hundred scripts in all, with engines matched to Korean and Japanese. On by default, and silent for a sheet already in Latin letters
  • A bilingual sheet's translation is drawn under the words it glosses
  • Look up again for a wrong match, Save to file to write the sheet into the track's tag, and Edit lyrics… to fix a stamp by hand
Internet Radio: a worldwide directory and your own streams, off by default
  • Off until you switch it on, under Settings ▸ Radio. Nothing contacts the directory until you do
  • A worldwide directory (radio-browser.info, no account and no API key) narrowed by country, language, genre, codec, or bitrate
  • Your own stream URLs, checked at the dialog rather than at the first click; .pls, .m3u, and .asx resolve to the audio behind them
  • Live titles reach the player bar, Now Playing, your desktop's media controls, and Discord, with buffering and reconnection handled underneath
  • Favorites, Recently Played, station pages, cached logos, and playlist-file import and export
  • Station cards select like any other card, with a right-click menu to play, favorite, copy, edit, or remove them
  • The titles a station announced this session, listed under it and copyable
  • Segmented (HLS) stations play like any other
Themes: six families in light and dark, and Material You
  • Six families, each with light and dark variants and configurable accents: Catppuccin (Latte, Frappé, Macchiato, Mocha), Material 3, GNOME Adwaita, KDE Breeze, Windows Fluent, and macOS
  • System dark/light is followed automatically and KDE color schemes are read from kdeglobals. A first launch starts on the desktop's own theme (Windows Fluent, KDE Breeze, or GNOME Adwaita, in the system's light or dark mode), and on Catppuccin Mocha anywhere else
  • Material You derives a palette from the current artwork in seven color styles, fading the window into each new cover's colors, and the accent and window outline can follow the artwork too. Material 3 and Material You follow Google's 2025 Material color spec wherever it defines the style
  • Headers paint an aurora of the album's own colors by default, or a blurred cover instead
  • A custom transparent titlebar, or native decorations, which KDE opens on
Formats and languages: MP3, FLAC, AAC, ALAC, Opus, and more, in sixteen locales

MP3, FLAC, M4A/M4B (AAC and ALAC), raw AAC (.aac), Ogg Vorbis (.ogg, .oga), Opus (.opus, up to 7.1), WAV (PCM and ADPCM), AIFF/AIFF-C, Matroska (.mka), and CAF. Matroska and CAF carry no tags Melodia can read, so those tracks list under their filename, as does anything whose tags are too damaged to parse.

Sixteen locales (English, German, French, Spanish, Turkish, Greek, Italian, Brazilian Portuguese, European Portuguese, Dutch, Polish, Indonesian, Russian, Ukrainian, Hungarian, Vietnamese), switchable at runtime with no restart under Settings ▸ Language.

System integration: scrobbling, Discord, media controls, the tray, and updates
  • Scrobbling to Last.fm and ListenBrainz, each independently, with loved-track sync that catches your existing favorites up on connect, and a durable offline queue. A ListenBrainz love needs the track's MusicBrainz recording ID in its tags
  • Discord Rich Presence (off by default): title, artist, album, and optionally a cover looked up on Deezer, sent to your running Discord client. Nothing leaves the machine while it is off
  • OS media controls (MPRIS2 on Linux, SMTC on Windows) and media keys
  • A system-tray icon with playback controls, on by default, and an optional close-to-tray; both under Settings ▸ Window
  • A daily update check, named on first run and switchable under Settings ▸ Updates. It asks GitHub for a signed manifest and nothing else; package-managed installs skip it entirely
  • Set Melodia as your default player and double-click a track; it runs as a single instance, so files open in the window you already have
  • Always-on-top on Windows, on any X11 desktop, and on Wayland under KDE, or GNOME with the Window Calls extension
  • On Linux, a self-deploying desktop entry and AppStream metadata for KDE Discover and GNOME Software
  • Window, queue, and navigation state persisted across sessions

Footprint

Release builds on one dual-boot PC, a Ryzen 7 9800X3D (8 cores, 16 threads) with an RTX 3080 and the window on a 144 Hz display. Melodia opened on a playlist's detail view, the visualizer in the Mirrored style, and each scenario is sampled every second for 60 s: memory is the median sample, CPU and GPU the total over that minute. With a 512-track library, the native titlebar, and each platform's default sample-rate conversion:

Scenario Linux, PSS Linux, CPU (1 core) Windows, Private WS Windows, CPU (1 core)
Idle 88.55 MiB 0.03% 59.96 MiB 0.10%
Playing, list view 91.10 MiB 0.72% 63.43 MiB 0.81%
Playing, visualizer live 94.92 MiB 2.60% 66.35 MiB 7.34%

Each memory column is what that platform's own monitor shows, KDE System Monitor's Memory column on Linux and Task Manager's on Windows. The two don't compare with each other: PSS counts a share of the file-backed pages, mostly the binary and the shared graphics stack, which Private WS leaves out. The full tables add startup, the Songs tab, the whole library queued, the custom titlebar, and a second library of 50,500 tracks beside the first, 51,012 in all.

Linux (Fedora): every scenario, both titlebars, both libraries

Measured with scripts/measure-footprint.py on KDE Plasma under Wayland, with the default Band-Limited sample-rate conversion. Startup is sampled from the moment Melodia launches, and every other scenario starts 90 s after the launch or 70 s after the switch into it, once the database connections either opened have closed. The Songs tab is My Library ▸ Songs, opened with the playlist still playing; double-clicking its first track queues the whole library, and the queue sheet opens over that queue.

Native titlebar

Scenario Anonymous PSS USS RSS GPU memory CPU (1 core) CPU (all cores) GPU
Startup 31.05 MiB 89.89 MiB 83.30 MiB 159.77 MiB 27.00 MiB 0.97% 0.06% 0.05%
Idle 30.10 MiB 88.55 MiB 81.92 MiB 156.79 MiB 27.00 MiB 0.03% 0.00% 0.00%
Playing, list view 31.44 MiB 91.10 MiB 84.48 MiB 159.34 MiB 24.00 MiB 0.72% 0.04% 0.00%
Playing, visualizer live 31.77 MiB 94.92 MiB 89.14 MiB 162.35 MiB 29.00 MiB 2.60% 0.16% 1.27%
Playing, Songs tab open 33.78 MiB 97.37 MiB 91.59 MiB 164.80 MiB 28.00 MiB 0.70% 0.04% 0.00%
Playing, whole library queued 34.38 MiB 98.21 MiB 92.43 MiB 165.64 MiB 25.00 MiB 0.65% 0.04% 0.00%
Playing, queue sheet open 35.64 MiB 99.54 MiB 93.76 MiB 166.97 MiB 27.00 MiB 0.52% 0.03% 0.00%

With both libraries, 51,012 tracks. The higher PSS and RSS at startup are the library's database, which every connection that read it keeps mapped until it closes; RSS counts it once per connection.

Scenario Anonymous PSS USS RSS GPU memory CPU (1 core) CPU (all cores) GPU
Startup 33.63 MiB 127.88 MiB 85.70 MiB 266.00 MiB 28.00 MiB 1.65% 0.10% 0.00%
Idle 32.78 MiB 91.30 MiB 84.68 MiB 159.48 MiB 28.00 MiB 0.05% 0.00% 0.00%
Playing, list view 34.48 MiB 94.09 MiB 87.48 MiB 162.28 MiB 24.00 MiB 0.68% 0.04% 0.00%
Playing, visualizer live 35.84 MiB 99.02 MiB 93.27 MiB 166.31 MiB 29.00 MiB 2.58% 0.16% 2.81%
Playing, Songs tab open 37.63 MiB 101.25 MiB 95.50 MiB 168.54 MiB 24.00 MiB 0.70% 0.04% 0.56%
Playing, whole library queued 39.41 MiB 103.28 MiB 97.53 MiB 170.57 MiB 25.00 MiB 0.45% 0.03% 0.00%
Playing, queue sheet open 40.62 MiB 104.55 MiB 98.80 MiB 171.84 MiB 27.00 MiB 0.53% 0.03% 0.00%

Custom titlebar

Scenario Anonymous PSS USS RSS GPU memory CPU (1 core) CPU (all cores) GPU
Startup 30.86 MiB 92.91 MiB 86.02 MiB 162.61 MiB 32.00 MiB 0.95% 0.06% 0.14%
Idle 29.76 MiB 91.26 MiB 84.51 MiB 159.41 MiB 32.00 MiB 0.05% 0.00% 0.00%
Playing, list view 31.23 MiB 94.71 MiB 88.79 MiB 161.98 MiB 29.00 MiB 0.67% 0.04% 0.00%
Playing, visualizer live 31.95 MiB 96.17 MiB 90.26 MiB 163.45 MiB 34.00 MiB 2.83% 0.18% 3.86%
Playing, Songs tab open 33.84 MiB 98.16 MiB 92.21 MiB 165.40 MiB 33.00 MiB 0.78% 0.05% 0.00%
Playing, whole library queued 33.99 MiB 98.63 MiB 92.67 MiB 165.86 MiB 30.00 MiB 0.55% 0.03% 0.00%
Playing, queue sheet open 35.14 MiB 99.78 MiB 93.82 MiB 167.02 MiB 30.00 MiB 0.60% 0.04% 0.00%

With both libraries, 51,012 tracks:

Scenario Anonymous PSS USS RSS GPU memory CPU (1 core) CPU (all cores) GPU
Startup 33.88 MiB 130.42 MiB 88.79 MiB 235.53 MiB 34.00 MiB 1.58% 0.10% 0.00%
Idle 33.12 MiB 94.32 MiB 87.88 MiB 163.00 MiB 34.00 MiB 0.05% 0.00% 0.00%
Playing, list view 34.74 MiB 97.40 MiB 90.64 MiB 165.77 MiB 29.00 MiB 0.73% 0.05% 0.00%
Playing, visualizer live 35.90 MiB 99.19 MiB 92.43 MiB 167.55 MiB 34.00 MiB 2.85% 0.18% 1.51%
Playing, Songs tab open 37.82 MiB 101.05 MiB 94.60 MiB 169.72 MiB 29.00 MiB 0.72% 0.04% 0.00%
Playing, whole library queued 39.70 MiB 103.48 MiB 96.73 MiB 171.85 MiB 30.00 MiB 0.48% 0.03% 0.00%
Playing, queue sheet open 40.86 MiB 105.53 MiB 99.64 MiB 173.01 MiB 30.00 MiB 0.53% 0.03% 0.00%

Linux keeps no commit charge per process, so Anonymous is the figure to compare: the memory Melodia allocated itself, in RAM or in swap, which nothing another process does can move. PSS is KDE System Monitor's Memory column. It adds a share of the file-backed pages, mostly the binary and the shared graphics stack rather than anything Melodia allocated, and that share shrinks whenever another program maps the same libraries. USS is the part no other process maps, what closing Melodia gives back, and System Monitor's Private column. RSS counts every shared page in full. GPU memory is the video memory the NVIDIA driver charges to Melodia, where FemtoVG keeps its textures and framebuffers, counted apart from the rest. CPU (1 core) counts one full core as 100%, and CPU (all cores) spreads that across all 16 threads, as System Monitor's CPU column does. GPU is the utilization the NVIDIA driver reports for Melodia, in whole percents each second.

Windows: every scenario, both titlebars, both libraries

Measured with scripts/measure-footprint.py, on an output device Windows mixes at 192 kHz, so every track passes through the sample-rate conversion. Startup is sampled from the moment Melodia launches, and every other scenario starts 90 s after the launch or 70 s after the switch into it, once the database connections either opened have closed. The Songs tab is My Library ▸ Songs, opened with the playlist still playing; double-clicking its first track queues the whole library, and the queue sheet opens over that queue.

Native titlebar

Scenario Commit Private WS Working set GPU dedicated GPU shared CPU (1 core) CPU (all cores) GPU
Startup 110.16 MiB 61.73 MiB 119.35 MiB 27.95 MiB 23.60 MiB 1.22% 0.08% 0.07%
Idle 105.15 MiB 59.96 MiB 116.68 MiB 24.64 MiB 23.60 MiB 0.10% 0.01% 0.00%
Playing, list view 110.21 MiB 63.43 MiB 121.23 MiB 24.64 MiB 23.60 MiB 0.81% 0.05% 0.03%
Playing, visualizer live 114.43 MiB 66.35 MiB 124.82 MiB 25.42 MiB 25.60 MiB 7.34% 0.46% 1.54%
Playing, Songs tab open 118.06 MiB 69.89 MiB 128.55 MiB 24.87 MiB 25.60 MiB 1.02% 0.06% 0.03%
Playing, whole library queued 120.80 MiB 71.84 MiB 130.76 MiB 25.01 MiB 25.60 MiB 0.99% 0.06% 0.02%
Playing, queue sheet open 123.09 MiB 72.56 MiB 131.60 MiB 26.84 MiB 25.60 MiB 0.73% 0.05% 0.03%

With both libraries, 51,012 tracks. The higher commit and working set at startup are the library's database: every connection that read it holds a page cache of its own, which commit counts, and maps the file, which the working set counts, until it closes.

Scenario Commit Private WS Working set GPU dedicated GPU shared CPU (1 core) CPU (all cores) GPU
Startup 153.27 MiB 98.80 MiB 329.58 MiB 28.09 MiB 25.72 MiB 9.35% 0.58% 0.04%
Idle 130.64 MiB 79.75 MiB 136.50 MiB 24.77 MiB 25.72 MiB 0.10% 0.01% 0.00%
Playing, list view 135.55 MiB 83.02 MiB 140.92 MiB 24.64 MiB 25.72 MiB 0.78% 0.05% 0.01%
Playing, visualizer live 141.44 MiB 87.05 MiB 144.78 MiB 25.42 MiB 25.72 MiB 7.32% 0.46% 0.44%
Playing, Songs tab open 145.96 MiB 91.85 MiB 150.02 MiB 24.87 MiB 25.72 MiB 0.68% 0.04% 0.01%
Playing, whole library queued 148.62 MiB 93.48 MiB 151.90 MiB 25.01 MiB 25.72 MiB 0.89% 0.06% 0.01%
Playing, queue sheet open 151.34 MiB 94.29 MiB 152.83 MiB 26.84 MiB 25.72 MiB 0.73% 0.05% 0.02%

Both tables use the default Linear sample-rate conversion. Band-Limited costs more CPU while playing: with the 512-track library, about 1.9% of one core in the list view and about 7.9% with the visualizer live.

Custom titlebar

Scenario Commit Private WS Working set GPU dedicated GPU shared CPU (1 core) CPU (all cores) GPU
Startup 116.78 MiB 63.29 MiB 121.07 MiB 33.64 MiB 23.72 MiB 0.96% 0.06% 0.08%
Idle 108.92 MiB 61.27 MiB 118.04 MiB 27.94 MiB 23.72 MiB 0.13% 0.01% 0.00%
Playing, list view 113.91 MiB 64.70 MiB 122.51 MiB 27.94 MiB 23.72 MiB 0.70% 0.04% 0.05%
Playing, visualizer live 117.59 MiB 66.27 MiB 124.74 MiB 29.21 MiB 23.72 MiB 7.16% 0.45% 2.30%
Playing, Songs tab open 121.30 MiB 70.21 MiB 128.86 MiB 28.68 MiB 25.72 MiB 0.83% 0.05% 0.06%
Playing, whole library queued 123.26 MiB 72.20 MiB 130.25 MiB 28.82 MiB 25.73 MiB 0.86% 0.05% 0.06%
Playing, queue sheet open 127.91 MiB 74.75 MiB 132.94 MiB 30.65 MiB 25.73 MiB 0.65% 0.04% 0.06%

With both libraries, 51,012 tracks:

Scenario Commit Private WS Working set GPU dedicated GPU shared CPU (1 core) CPU (all cores) GPU
Startup 152.41 MiB 97.69 MiB 294.46 MiB 33.64 MiB 23.72 MiB 8.78% 0.55% 0.06%
Idle 127.62 MiB 78.46 MiB 135.63 MiB 27.94 MiB 23.72 MiB 0.08% 0.00% 0.00%
Playing, list view 133.61 MiB 83.11 MiB 140.17 MiB 27.94 MiB 23.72 MiB 0.47% 0.03% 0.01%
Playing, visualizer live 140.72 MiB 87.61 MiB 145.27 MiB 29.22 MiB 25.72 MiB 5.68% 0.35% 0.38%
Playing, Songs tab open 143.78 MiB 92.89 MiB 150.74 MiB 28.68 MiB 25.72 MiB 0.73% 0.05% 0.01%
Playing, whole library queued 146.12 MiB 94.24 MiB 152.35 MiB 28.82 MiB 25.72 MiB 0.68% 0.04% 0.01%
Playing, queue sheet open 149.47 MiB 95.34 MiB 153.57 MiB 30.65 MiB 25.72 MiB 0.49% 0.03% 0.01%

Both tables use the default Linear sample-rate conversion. Band-Limited costs more CPU while playing: with the 512-track library, about 2.1% of one core in the list view and about 6.2% with the visualizer live.

Windows keeps no PSS, so Commit is the figure to compare: the private memory Windows has set aside for Melodia, in RAM or paged out, which doesn't fall when Windows trims the process. Private WS is Task Manager's Memory column, the private memory in RAM at that moment. Working set adds the pages Melodia shares with other processes, mostly system DLLs. GPU dedicated and GPU shared are the video memory Task Manager lists per process, where FemtoVG keeps its textures and framebuffers, counted apart from commit. CPU (1 core) counts one full core as 100%, and CPU (all cores) spreads that across all 16 threads, as Task Manager's Details tab does. GPU is the busiest GPU engine, Task Manager's per-process figure.

Keyboard Shortcuts

Space, the arrow keys and single letters cover playback, the queue and navigation, and the OS media keys (play/pause, next, previous, stop) are handled too. Stop takes the track back to its start, as holding the Play/Pause button does.

All shortcuts
Action Shortcut
Play / Pause Space
Seek backward / forward 5s ← / →
Seek backward / forward 30s Shift+← / Shift+→
Previous / Next track Ctrl+← / Ctrl+→, or P / N
Volume up / down 5% ↑ / ↓, or the mouse wheel over the volume control
Volume up / down 1% Ctrl+↑ / Ctrl+↓, or Ctrl+wheel over the volume control
Seek to 0–90% 0–9
Mute M
Favorite current track L
Shuffle S
Repeat mode R
Queue panel Q
Select all in the queue, after clicking it Ctrl+A
Remove the queue's selected tracks, after clicking it Delete or Backspace
Undo a removal, while its notice is up Ctrl+Z
Now Playing view F
Maximize F11
Toggle sidebar Ctrl+B
Settings Ctrl+,
New playlist Ctrl+N
Close dialog / close Now Playing or the queue overlay / clear selection Esc
Navigate back / forward through history Mouse-4 / Mouse-5

Building from Source

Rust 1.97.0, edition 2024, pinned by rust-toolchain.toml and installed by rustup on its own. Linux additionally needs the development packages for Slint's FemtoVG renderer (no WebKitGTK); Windows needs nothing extra.

# Debian/Ubuntu
sudo apt install libfontconfig1-dev libfreetype6-dev libasound2-dev \
                 libxkbcommon-dev mesa-vulkan-drivers libwayland-dev

# Fedora
sudo dnf install fontconfig-devel freetype-devel alsa-lib-devel \
                 libxkbcommon-devel vulkan-loader wayland-devel
git clone https://github.com/KenanSalar/Melodia.git
cd Melodia

cargo run -p melodia                                     # debug build, runs the app
cargo build --release -p melodia                         # release → target/release/Melodia
cargo clippy --all-targets --workspace -- -D warnings    # lint
cargo test --workspace                                   # tests
Build notes: the dev data folder, the vendored winit, and API keys

A source build keeps its own library under Melodia-dev, beside an installed copy's folder rather than inside it, so a schema migration still on a branch can't leave an installed Melodia unable to open its database, and the two can run at once. MELODIA_DATA_DIR points either build at a directory of your choosing.

winit/ is a checked-in copy of winit 0.30.13 plus an unmerged Wayland file drag-and-drop fix (winit#1881) and drag events that say where the pointer is, which is how a dropped file finds the queue or the open playlist. It is wired by Cargo.toml's [patch.crates-io], so a fresh clone builds with no setup.

Last.fm scrobbling needs an API application's key and shared secret, which identify the app rather than any account. They are read at compile time from LASTFM_API_KEY / LASTFM_SHARED_SECRET, so nothing secret lives in the repo; for local builds, copy .env.example to .env and build.rs bakes them in. A build without them is fully functional, ListenBrainz included, and the Last.fm Connect button reports "not configured in this build". A fork wanting its own Discord presence sets MELODIA_DISCORD_APP_ID.

Architecture

The Slint UI runs on the main thread and a single multi-threaded Tokio runtime handles the database, scanner, watcher, player control, and HTTP. There is no WebView and no IPC boundary: UI callbacks spawn async work, state flows back over watch and mpsc channels consumed by UI-thread tasks, and cpal's device callback, or an exclusive claim's own writer thread, pulls the mixer directly, so decoding, the DSP chain, and the mix stay off the runtime entirely.

Fourteen crates, layered so the compiler enforces the direction rather than a convention: the UI names no database or socket, the decoders name no mixer, the tag writer names no state machine. Slint 1.18 on FemtoVG, Tokio, Symphonia and cpal (with ALSA and WASAPI directly for exclusive output), SQLite via rusqlite with WAL and FTS5, Lofty for tags, Rayon, BLAKE3, and minisign for the updater.

The doc comments are the architecture reference, CLAUDE.md holds the repo-wide rules and commands for a coding agent, and docs/adr/ records why each piece was chosen over the alternatives.

Data and Logs

Everything lives under the OS application-data directory, ~/.local/share/Melodia on Linux and %APPDATA%\Melodia on Windows, and MELODIA_DATA_DIR moves the whole folder somewhere else.

What the folder holds
File / folder Purpose
melodia.db The music library (SQLite, WAL + FTS5)
settings.json, views.json, queue.json Preferences, per-view UI state, and the queue with the station tuned over it
scrobble_*.json Last.fm session key and ListenBrainz token (0600 on Unix), plus the offline queue
artwork/, artists/, radio-logos/ Cached album, artist, and station images. A deleted cover is put back from your music files on the next scan
lyrics/ Sheets the online lookup found, and a marker for the tracks it found none for
backups/ Database copies taken before each schema migration
logs/ Rolling logs and crash reports

Melodia writes a log on every run, with no environment variable and no terminal needed, and leaves a crash report beside it if it ever panics. The current log is melodia_rCURRENT.log; it rotates at 2 MiB and keeps the 7 most recent, so logs/ stays under about 16 MiB.

Settings → About → Diagnostics opens that folder, saves a single melodia-diagnostics-*.txt to attach to a bug report, and toggles verbose logging. The report carries your version, OS, desktop session and install method, your library's size, a short fixed list of settings, recent crash reports, and the tail of the logs. Home directory paths are shortened to ~, and no credentials, tokens or session keys are ever included; those live in a separate file the report doesn't read.

If Melodia won't start at all, melodia --logs prints the log directory and exits. That covers Linux and macOS: a Windows build runs with no console attached, so use %APPDATA%\Melodia\logs\ directly. For finer control than the verbose switch, RUST_LOG=debug melodia overrides the filter for both the log file and the terminal.

Contributing and Support

Contributions are welcome. CONTRIBUTING.md has the setup, the checks to run before pushing, and how pull requests are handled.

Melodia is free, open source, and built in my spare time, with nothing gated behind payment. If it's useful to you, you can support me on GitHub Sponsors or Ko-fi, the same two links the app carries at Settings → About.

License

Copyright (C) 2026 Kenan Salar. Melodia is free software under the GNU Affero General Public License, version 3 or, at your option, any later version, and is distributed without any warranty.

The AGPL covers Melodia itself. Two fonts, a patched winit fork and several crates on copyleft terms (the UI toolkit, the audio decoders and the Japanese romanization engine) are compiled into the binary under their own terms; every one of those licenses ships in licenses/, which every package carries alongside this file.

Acknowledgments

Built on the work of the Slint, cpal, Symphonia, and rusqlite projects, the Catppuccin palette, and Material Foundation's color utilities, along with the many other crates listed in Cargo.toml. The station directory is radio-browser.info (CC0 data, no account), and the lyrics directory is LRCLIB (also no account). Romanization is uroman-rs for most scripts and kakasi for Japanese.

Melodia's interface is set in Vazirmatn (SIL Open Font License 1.1), with its Greek, Russian, Ukrainian and Vietnamese letters taken from Roboto (Apache License 2.0), and draws its icons from Material Symbols Rounded (Apache License 2.0). All three are modified, as is the vendored winit fork (Apache License 2.0) that gives Wayland its drag-and-drop events and says where a drag is on every platform Melodia ships for. What changed in each ships in licenses/.