About
Media Lyrics
A full-featured media player panel with time-synced lyrics for the Noctalia desktop shell. Karaoke-style lyric carousel (10/14/16 visible lines per size preset), album cover, transport controls, and a progress bar โ all in one floating panel. Pure Luau implementation: no playerctl, no python daemons, no GTK overlays โ runtime needs busctl (MPRIS) and curl (LRCLIB HTTPS + NetEase fallback).
| Light theme | Dark theme |
|---|---|
![]() |
![]() |
Plugin
| Field | Value |
|---|---|
| ID | tranzem/media-lyrics |
| Entries | Bar widget: now-playing; panels: panel (medium 520ร520), panel-compact (440ร440), panel-large (640ร640), panel-mini (360ร120); service: service; shortcut: toggle |
Requirements
- Noctalia v5 (plugin API 24+)
busctl(systemd, present on every Arch install)curlโ used for the HTTPS lyric fetches: LRCLIB primary + NetEase Cloud Music fallback (spawned ascurl -sSf -m 8 -4 <url>, argv-only, no shell; LRCLIB resolves IPv4 faster than the built-in HTTP client on some setups)- Outbound HTTPS access to
https://lrclib.net(primary) andhttps://music.163.com(NetEase fallback) for lyrics
No player-specific software. Any MPRIS-capable player works: Spotify, MPD, Cider, web players, VLC, and anything else that exposes MPRIS over D-Bus. sleep (coreutils) is used for a short refresh delay after transport commands.
Usage
Enable the plugin, then open the panel:
noctalia msg plugins enable tranzem/media-lyrics
noctalia msg panel-toggle tranzem/media-lyrics:panel
The panel opens at the size preset selected by the panel_size setting
(compact 440 / medium 520 / large 640). The now-playing bar widget and the
toggle control-center tile both open the selected preset; you can also open
a specific preset directly:
noctalia msg panel-toggle tranzem/media-lyrics:panel-compact
noctalia msg panel-toggle tranzem/media-lyrics:panel-large
noctalia msg panel-toggle tranzem/media-lyrics:panel-mini
panel-mini is a compact always-on surface (cover + the current lyric line)
intended for pinning to the desktop; it does not close on outside clicks.
Add the now-playing widget to your bar: a compact chip with the album
cover and Title - Artist of the active MPRIS player. Its gestures mirror
the shell's built-in media widget:
- Left click โ open the lyrics panel.
- Right click โ play/pause.
- Middle click โ this widget's display settings.
- Wheel / mouse back / forward โ previous / next track.
- On a vertical bar the chip collapses to the artwork only.
Display options are edited in the widget's own settings popup (middle click):
| Setting | Default | Effect |
|---|---|---|
album_art_only |
off | Show only the artwork, no text |
hide_album_art |
off | Hide the artwork and its fallback icon |
hide_artist |
off | Show only the track title |
artist_first |
off | Show Artist - Title instead of Title - Artist |
min_length |
80 | Minimum widget length (px) โ accepted for parity; plugin chips are sized by the host to their content |
max_length |
220 | Text area width (px); long titles truncate or scroll to fit |
art_size |
16 | Artwork size (px) |
title_scroll |
none | Scroll long titles: none, always, or on hover |
hide_when_no_media |
off | Hide the chip when no MPRIS player is active |
show_lyric_line |
off | Show Title ยท current line in the chip instead of Title - Artist while synced lyrics are ready (long lines scroll with the marquee; falls back to the artist line otherwise) |
A toggle shortcut (control-center tile) is also available. Bind it to a hotkey in Noctalia's shortcut settings, or from your compositor:
"Ctrl+Alt+M" = "spawn:noctalia msg panel-toggle tranzem/media-lyrics:panel"
The panel shows the active MPRIS player automatically; when nothing is playing it renders an empty state.
Features
- Karaoke lyric carousel โ 10/14/16 lines visible at once (compact/medium/large presets); the active line is bright, neighbours fade by distance (Clavis-style). Works with synced (LRC) and plain lyrics.
- Clickable lyric lines โ click a synced line to seek the player to that timestamp.
- Manual lyric scroll โ Up/Down step a line (the host's chord validator accepts only basic key names; PageUp/PageDown/Home/End are rejected).
- LRCLIB integration โ exact
/api/getlookup first,/api/searchfallback, LRC parsed in pure Luau. - Lyrics variants picker โ the header "list" button (always visible while a track plays) fetches the full LRCLIB search result on demand and lists alternative lyric versions: pick one to switch instantly (the playing lyrics are never interrupted while the list loads), pick Default to restore the automatic chain, or switch again at any time โ the candidate list stays in memory per track.
- NetEase Cloud Music fallback โ no-auth second source for LRCLIB misses (public endpoints, browser headers only): synced LRC wins, candidates ranked by title/artist + duration, metadata lines stripped; instrumental placeholders are filtered.
- Local
.lrcfiles โ dropArtist - Title.lrcinto the local lyrics folder; they take priority over the network. - Marquee titles โ long track/artist names hold for 2 s, then scroll slowly instead of wrapping or clipping. Overlap-free (per-slice node recreation).
- Album cover + progress bar โ interpolated progress between polls, transport controls (prev / play-pause / next), shuffle and repeat state.
- Live lyric line in the chip โ optional
show_lyric_linewidget setting: while synced lyrics are ready the chip showsTitle ยท current lineinstead of the artist (steps with playback, marquee for long lines). - Settings โ lyric timing offset in ms, on-disk cache, local lyrics folder. Translatable UI: strings go through Noctalia's i18n (
noctalia.tr, English ships in the plugin; other locales via Noctalia Translate).
Advantages over alternative lyric plugins
- Lean runtime. No playerctl, python daemons, pip packages, or GTK overlays to install and maintain โ just
busctlandcurl, present on virtually every Linux system. Enable โ works. - Player-agnostic. Reads MPRIS directly via Noctalia's D-Bus aggregator โ works with any player, not tied to a specific app.
- A real panel, not a 1โ3 line bar widget. Full-screen-height carousel with 10โ16 visible lines (per size preset) keeps whole verses in view.
- Overflow handled properly. Long titles get a marquee, single-line sanitizer strips embedded newlines, integer button heights prevent glyph overlap.
- Offline-friendly. LRCLIB responses are cached; local
.lrcfiles work without network at all.
Settings
| Setting | Type | Default | Description |
|---|---|---|---|
panel_size |
select |
medium |
Panel size preset: mini (360ร120 chip panel), compact (440ร440, 10 lyric lines), medium (520ร520, 14 lines), large (640ร640, 16 lines). The bar widget and the control-center tile open this preset. |
offset_ms |
int |
0 |
Shift lyric timing: positive shows lines earlier, negative later. |
use_cache |
bool |
true |
Cache fetched lyrics in the plugin data directory for offline reuse. |
local_lyrics_dir |
folder |
~/.local/share/media-lyrics |
Folder with local .lrc files named Artist - Title.lrc; searched before LRCLIB. |
player_allowlist |
string |
(empty) | Comma-separated identity/bus-name substrings; when set, only matching players are shown (e.g. spotify, mpd). |
player_blocklist |
string |
(empty) | Comma-separated substrings of players to exclude (e.g. firefox to ignore a browser's MPRIS). |
IPC
noctalia msg panel-toggle tranzem/media-lyrics:panel
Local development
Add the parent directory as a local Noctalia source:
noctalia msg plugins source add media-lyrics-dev path /path/to/media-lyrics-parent
noctalia msg plugins enable tranzem/media-lyrics
noctalia msg config-reload
To Do
Upcoming work, roughly in priority order:
- Album cover inside a capsule shape (panel info row โ the bar-widget chip already shows the artwork since 0.9.0)
- Additional lyric sources โ NetEase fallback DONE in 0.9.1 (no-auth,
last in the chain); embedded MPRIS
xesam:asTextDONE in 0.9.2 (zero-network, position 2 in the chain). Remaining: Musixmatch, Spotify โ most need API keys/tokens (see Notes) - Lyrics variants picker โ switch between alternative LRCLIB versions on the fly (DONE in 0.9.4: header button, on-demand search, Default row)
- Clickable lyric lines โ click a line to seek the track to that moment (DONE in 0.8.5: click + Return/Space)
- Seek on progress-bar click โ BLOCKED by host: click handlers do not report coordinates, so a click position cannot be mapped to a timestamp (only lyric-line clicks and the keyboard cursor can seek)
- Compact mode with a pinnable widget โ the bar chip + panel presets
cover the compact surface; a desktop-pinned view would need a new
[[desktop_widget]]entry (open question) - Preconfigured widget actions โ default gestures declared in the manifest (DONE in 0.8.1 and reworked in 0.9.0: now mirrors the built-in media widget โ right click = play/pause, back/forward + wheel = prev/next; middle click = widget settings)
- Widget size setting โ panel size presets (DONE in 0.8.7:
panel_sizeselect โ compact 440 / medium 520 / large 640) - Bar widget album cover + display settings (DONE in 0.9.0: artwork chip,
album_art_only/hide_album_art/hide_artist/artist_first/min_length/max_length/art_size/title_scroll/hide_when_no_media; vertical bars show the artwork only)
Notes
- The service polls MPRIS via
busctl(150 ms cadence) and publishes a snapshot tonoctalia.state; the panel animates from those publishes. - Lyrics are fetched from public services with
curlโ LRCLIB API primary, NetEase Cloud Music fallback on misses; nothing is uploaded. Cache and local lyrics live under the plugin data directory andlocal_lyrics_dir. - Spawned processes (all argv-form, no shell):
busctl(MPRIS poll),curl(LRCLIB + NetEase lyric fetches, IPv4, 8 s timeout),sleep(coreutils, 0.35 s refresh delay after transport commands). - Adapted from the Clavis shell media player text layer (karaoke render + LRCLIB provider), ported to pure Luau for Noctalia v5.
Versions
| Version | Plugin API | Updated |
|---|---|---|
| v0.9.4 latest | 30 | Sep 9, 2026 |
| v0.9.0 | 24 | Sep 5, 2026 |
Older versions stay installable on a Noctalia release whose plugin API is below the latest version's.

