Repository navigation
Releases: vynulldev/vynull
Release list
v0.6.0
Vynull v0.6.0
This release focuses on matching rekordbox on the wire and documenting
the HTTP API.
- dbserver menu and metadata responses now match rekordbox 7.2.19 across
the browse surface: the root menu, category drill-downs
(genre/artist/album/label/remixer/original artist with ALL rows),
track rows, playlists, search, the 24-key wheel, and harmonic matching.
Verified response by response against the link-spec conformance suite;
this corrects a range of wire-format differences from real rekordbox. - OpenAPI spec for the full HTTP API, served at
/api/openapi.yaml, with a
self-hosted Swagger UI at/api/docs(available even when headless). - Uniform CORS headers on every API response, plus a live Server-Sent
Events stream at/api/events, so external frontends can build against
the API. - master.db import no longer requires a hand-built Python environment;
the sqlcipher venv is provisioned automatically on first use. - Web audio player: play library tracks in the browser.
- Analysis BPM range (
--bpm-range, or Settings > Library Source) keeps
fast genres from analyzing at half or a third of their true tempo. - Overlay waveform style: bottom-anchored bars or a centre-mirrored full
look, plus an optional full-height band. - History playlists exported to a USB now use rekordbox's exact row
format.
Hardware-verified on a CDJ-2000NXS2.
Thanks to this releases contributors:
- Evan Purkhiser (@evanpurkhiser) - the link-spec conformance suite
Vynull's dbserver was validated against. - kayrozen (@kayrozen) - the master.db importer's automatic sqlcipher
venv and the web audio player. - Unkown607 (@Unkown607) - reported, with a fix, that the History table
(0x13) export row format did not match real rekordbox.
What's Changed
- pdb: write History rows in rekordbox's inline-string layout (#53) by @vynulldev in #54
- api: web audio player for library tracks by @kayrozen in #56
- overlay: half/full waveform style + optional full-height band by @vynulldev in #59
- dbserver: match rekordbox's menu protocol against the link-spec suite by @vynulldev in #62
- api: serve the OpenAPI spec and a self-hosted Swagger UI by @vynulldev in #58
- api: uniform CORS + an SSE event stream for frontends by @vynulldev in #63
- library: auto-provision sqlcipher3 venv for master.db import by @kayrozen in #60
- analysis: optional BPM range to fix half/third-tempo detection by @vynulldev in #55
- docs: v0.6.0 pre-release audit by @vynulldev in #64
New Contributors
Full Changelog: v0.5.0...v0.6.0
v0.5.0
Vynull v0.5.0
This release is shaped by the first round of community hardware reports. Shoutouts to @kayrozen, @przemeklo82, and @hdelplan!
Thank you to everyone who answered the call for testers!
Changes
Plugging a rekordbox USB into Vynull now serves everything rekordbox wrote to it (#36 (comment)). Point --music-dir at a stick and your playlists appear on the decks and in the web UI, tracks carry rekordbox's own beat grids, waveforms and hot/memory cues, and the web UI and the players finally agree on which track is which - the web, the deck and the stick share one track-ID space. Startup is faster too: a stick's own database replaces the tag scan entirely.
A crash reported on the XDJ-AZ is fixed (Issue #37 PR #38): Vynull's colour waveforms could carry values real rekordbox never emits, and the AZ's firmware hard-restarts on them. Credit to the reporter, who isolated the exact bytes against a live deck - the fix is byte-for-byte what they validated, confirmed against two thousand rekordbox-analyzed tracks.
The stream overlay's scrolling waveform no longer drifts and jumps. The playhead is now anchored to the deck's beat packets - the ones that fire exactly on the beat - and small corrections glide instead of snapping, so the waveform tracks the music at any BPM and pitch.
Beat grids get a calibration fix that triples sub-10ms agreement with rekordbox's grids on our reference library, and - important for anyone who fixes a grid by hand - manual beat-grid edits now survive analysis cache upgrades instead of being silently reverted.
The web UI can now create memory cues, not just hot cues (Issue #46 PR #48) - a + MEM button next to + CUE, numbered the way rekordbox numbers them, so they flow to decks and USB exports like imported ones.
Upgrading re-analyzes your library once (lazily, as tracks are touched). The DIAG tab now captures the full startup log, so if
something goes wrong you can copy it straight from the browser - no more photographing terminals.
Hardware-verified on a CDJ-2000NXS2; the XDJ-AZ fix verified by its reporter on the affected hardware.
Commit log
- prolink: clamp PWV4 band bytes to 7 bits so the XDJ-AZ survives loading by @vynulldev in #38
- overlay: beat-accurate playhead so the scrolling waveform stops jumping by @vynulldev in #39
- pdb: serve a rekordbox USB properly and fix web UI diag log filters by @vynulldev in #42
- web: toolbar USB export sends a string source again by @vynulldev in #45
- analysis: re-trim tempogram latency to center the grid-phase peak by @vynulldev in #43
- memory cues: create from the web UI, survive the wire by @vynulldev in #48
- pre-release audit: test hygiene and README accuracy by @vynulldev in #47
- fix: various export bug fixes by @vynulldev in #49
- pdb: read the artist/album name offset from the row, not a hardcode by @vynulldev in #50
Full Changelog: v0.4.0...v0.5.0
v0.4.0
Vynull v0.4.0
The theme: more ways to reach your library. The binary is now also a shell client for a running server, the web UI installs as an app on phones and desktops, and the playing deck shows up in your desktop's media controls.
Shell subcommands
With a server running, the same binary works as a client — no curl required:
vynull search caribou # list matching tracks (ID, BPM, key, ...)
vynull search --json | jq ... # machine-readable, for pipelines
vynull add ~/Music/new-crate # add files or folders
vynull load 42 2 # load track 42 on deck 2
vynull load "encounter" 2 # or by search — must match exactly one track
vynull players # who's on the link and what they're playing
vynull status # server, analysis, and link state--json on the listing commands is the building block for your own tooling: pipe search --json through jq and fzf and you have a track picker; poll players --json from a status bar. Loading by query refuses ambiguity — if more than one track matches, it lists the candidates and stops, because loading the wrong track on a live deck is not a failure mode worth having. --addr or VYNULL_ADDR point the commands at a non-default server, and --help lists everything.
Install the web UI as an app
The web UI now ships a PWA manifest: browsers can install it as a standalone app that launches fullscreen from a home-screen icon — no address bar, no tabs, dark from the first frame. The practical case is a phone or tablet at the booth. On desktop, Chromium-family browsers install it as its own window with a dock icon.
Notes: install requires a secure context, so it works from localhost (desktop, or adb reverse for Android) and via iOS Safari's Add to Home Screen; Android over plain LAN HTTP creates a working shortcut rather than a full standalone install. There is deliberately no offline mode — the UI is meaningless without the live server.
Now-playing on your desktop (MPRIS)
Vynull publishes the audible deck over MPRIS on the D-Bus session bus. Desktop media applets (XFCE's PulseAudio plugin, GNOME/KDE controls), lock screens, playerctl, status-bar widgets, and KDE Connect's phone mirroring all show the current track — title, artist, artwork, length, and position — updating within a second of the deck changing.
It is read-only by design: decks cannot be paused or skipped over the link, so the player advertises no controls (some simpler applets may render inert buttons). On by default; --mpris=false opts out, and headless machines without a session bus skip it silently.
Internals
The e2e suite grew scenarios for the CLI (driving the built binary's subcommands against a real server) and MPRIS gained integration tests that spin a private D-Bus daemon per run — two publisher bugs were caught by those tests before release. make check now needs dbus-daemon available alongside ffmpeg.
Upgrade notes
- No re-analysis pass this time — nothing in the analysis pipeline changed
- The release binary grows by roughly 2.4MB from the D-Bus dependency
- Nothing deck-facing changed; hardware-verified on a CDJ-2000NXS2 as a regression smoke
Full changelog: git log --merges v0.3.0..v0.4.0
v0.3.0
Vynull v0.3.0
The headline features: BPM detection now lands exactly on integer tempos and beat grids stop drifting; album art appears in the web UI without needing a deck; tracks can finally be removed from playlists; the TUI gains a live Logs tab; and logs are quiet by default.
Exact BPMs, straighter grids
The tempo detector's peak interpolation could land a fraction off the true tempo (120.85 for a track that is really 121), which also poisoned the beat grid: a grid fit at the wrong period drifts a full beat over a typical track. Detection now verifies candidate tempos by tempogram coherence before any grid work:
- Tracks at integer tempos detect exactly; the roughly one-in-three that used to come out fractional snap to the right whole number
- Genuinely fractional tempos are kept when the audio supports them decisively, and half-integer tempos (a true 127.5) are recognized
- The beat grid is fit at the corrected period, so beat indicators stay locked across the whole track
- Library rows now follow re-analysis, so the displayed BPM always matches the grid that actually plays; manual BPM overrides survive untouched
Existing libraries upgrade themselves: the analysis cache version was bumped, so tracks re-analyze once in the background as they are viewed or loaded and pick up the corrected values.
Web UI
- Album art now appears the first time a track is viewed. Previously the artwork extraction was only ever triggered by a CDJ loading the track, so newly added tracks sat artless until they hit a deck
- Tracks can be removed from a playlist: a per-row button, plus a bulk action for removing a whole selection at once. Both are scoped to regular playlists, remove only the membership (the track, its tags, and its cues stay in the library), and pick the right track even with an active search or sort
- Waveform thumbnails for newly added tracks appear the moment analysis completes. Previously they could flash black on view switches, lag the analysis by half a minute, or (with analysis behind a long queue) never appear until a page refresh; a browser image-caching subtlety kept resurrecting the pre-analysis placeholder, and the thumbnail URL now changes when analysis lands so it cannot
TUI
- A new Logs tab shows the live log stream in-place: it follows the tail by default, scrolling up pauses it, and single keys jump to the oldest line or back to following. The log file remains the complete record
- The Settings tab scrolls properly instead of pushing the whole screen off on short terminals
- A DJM mixer now shows reliably in the Players view. A startup race could hide it for an entire session, and newer mixers' stripped status packets were wiping the channel state learned from their on-air broadcasts, making the mixer line flicker between states
Quiet logs
--log-level is now honoured everywhere. The default level no longer produces a line-per-packet spam stream with hex dumps while a deck browses and plays; it keeps the operationally useful record (sessions, loads, errors, deck writes). debug adds per-request browse and mount detail, trace adds wire-level hex dumps, and load-path log lines now show track titles alongside IDs.
Docs
- Run commands in the README, Makefile, and website no longer say
sudofor the default rekordbox mode, which needs no privileged ports; only--mode cdjneeds UDP 111, and the sudo-free options for that are documented - The README now leads with what the app does for hardware DJs, and a new Troubleshooting section covers the problems people actually hit (the waveform-color quirk, the post-upgrade re-analysis pass, the rekordbox slot collision) plus how to collect useful logs
Internals
A new end-to-end suite (make e2e) drives the real binary over its HTTP API against synthesized ground-truth media, covering the analysis pipeline, artwork, playlists, the cache upgrade path, and bulk-add responsiveness in about fifteen seconds. The newer-DJM status handling is additionally pinned by deterministic packet-level tests, since an idle mixer never exercises that path live. make check runs the whole pre-release gate (build, vet, formatting, unit tests, e2e) in one command.
Upgrade notes
- The one-time re-analysis pass after updating is CPU-heavy but bounded; the library stays usable while it runs
- Expect BPM values to visibly change on tracks the old detector had a fraction off; that is the fix working, and the grids move with them
- Hardware-verified on a CDJ-2000NXS2
Full changelog: git log --merges v0.2.0..v0.3.0
v0.2.0
What's Changed
- core: brand-neutral domain model + adapter interfaces by @vynulldev in #1
- analysis: produce neutral core.Analysis + lock the waveform encoders (modular-backends step 2) by @vynulldev in #2
- dsp + golden net: prep for the encoder relocation (modular-backends part 3a/3b) by @vynulldev in #3
- link/prolink: relocate the Pioneer wire encoders out of analysis (modular-backends part 3c) by @vynulldev in #4
- library: import Traktor collection.nml (tracks, playlists, cues) by @vynulldev in #5
- library: generalize the import layer behind an Importer registry by @vynulldev in #6
- web: drop the POLLING 1HZ and API-URL status-bar items by @vynulldev in #8
- web: declutter the import dialog and make progress prominent by @vynulldev in #7
- dbserver: fix CDJ-saved cue colour showing orange instead of green by @vynulldev in #11
- docs/design: import-layer plan + modular-backends reconciliation by @vynulldev in #9
- docs: document Traktor NML import in the README by @vynulldev in #10
- nfs + device + api: metadata and cover art for tracks played from USB by @vynulldev in #14
- analysis + mediadb + api: waveform and cues for external tracks by @vynulldev in #15
- api + web: configurable stream overlay (now-playing, decks, waveforms, history) by @vynulldev in #13
- mediadb: resolve external metadata per media slot (USB / SD, skip CD) by @vynulldev in #16
- api: write analysis back to the library row on every result path by @vynulldev in #18
- analysis: sharper beat-grid phase (windowed phase, gated half-beat flip, codec-aware latency) by @vynulldev in #17
- analysis: bump cacheVersion for the beat-grid phase improvements by @vynulldev in #19
New Contributors
- @vynulldev made their first contribution in #1
Full Changelog: v0.1.0-pre...v0.2.0
v0.1.0-pre
Vynull v0.1.0-pre — first public prerelease
A virtual CDJ / rekordbox source for Linux. Point Vynull at your music
collection and CDJs see it as a connected library over Pro DJ Link — with color
waveforms, beat grids, cues, and a browser-based library manager.
⚠️ First public prerelease. This is a hobby project that speaks a protocol
Pioneer never documented, worked out from other people's reverse-engineering.
Expect bugs and the occasional strange deck behaviour. Not affiliated with
Pioneer DJ / AlphaTheta. Try it before you trust it in a set.
Highlights
- Virtual CDJ / rekordbox on the Pro DJ Link network — CDJs browse (by
artist, album, genre, BPM, key, label, year, remixer, folder) and load your tracks. - Browser library manager (
--web) — browse/search, edit metadata, manage
cues/tags/(smart) playlists, view live players, zoom waveform + beat grid with
beat-jump, three UI themes, and configure CDJ settings. - Import from rekordbox —
rekordbox.xml, an encryptedmaster.db, or a
library-backup.zip: tracks, MyTags (+ categories), colors, (smart)
playlists, hot + memory cues (colors + loops), ANLZ waveforms/beat
grids/phrases, and artwork. - Color waveforms on the CDJ (PWV4 overview + PWV5 scrolling; blue / RGB /
3-band, honoring the deck's waveform-color setting). CDJ-3000 3-band
(PWV6/PWV7) supported. - Native FLAC / WAV / AIFF playback streamed over NFS (optional transcode to MP3).
- BPM detection + beat grid (dynamic-programming beat tracker), cue
management, key detection. - DJM mixer awareness — surfaces channel / master state on the link.
- Live terminal monitor (TUI), lazy analysis for instant startup, and
USB export to a rekordbox-compatible structure.
Full feature list and HTTP API in the README.
Platforms
- Linux — x86-64 & ARM64 (runs on a Raspberry Pi).
- A network interface on the same subnet as your CDJs (typically link-local
169.254.x.x). --mode rekordbox(the default) needs no privileged ports;--mode cdj
(appear as a CDJ-USB source) needs UDP port 111 — see the README.
Tested with
- CDJ-2000NXS2
- DJM-A9
Known limitations
- Beat-grid phase matches rekordbox's on only a fraction of tracks. BPM is
usually right, but the detected downbeat/phase can be off. Adjustable per
track from the web UI / API. - DJM mixers presence + master/channel state are surfaced from
broadcasts; deeper mixer control isn't implemented. - More broadly: some features are half-finished or only work in certain setups.
Treat it as a work in progress. Bug reports and PRs welcome.
Getting started
Grab the build for your platform from the Assets below, or build from source:
git clone https://github.com/vynulldev/vynull && cd vynull
make build
./vynull --web # library mode + web UI, no music dir required
# add music via the web UI or the HTTP API, then LINKSee the Quick Start for import-from-rekordbox, directory mode, and CDJ mode.
Thanks
Built on the reverse-engineering published by Deep Symmetry (dysentery / beat-link / crate-digger), rekordcrate, python-prodj-link, and pyrekordbox.
Full credits in the README.
License
GPL-3.0-or-later. Independent and unofficial — not affiliated with or endorsed by Pioneer DJ / AlphaTheta, Deep Symmetry, or any project listed above.