{"id":48915294,"url":"https://github.com/interfluve-wav/dj-metadata","last_synced_at":"2026-04-17T02:00:41.391Z","repository":{"id":351898998,"uuid":"1212981611","full_name":"interfluve-wav/dj-metadata","owner":"interfluve-wav","description":"Cross-platform DJ library metadata quality: UDMS schema, Python adapters (Rekordbox, Serato, Engine DJ, VirtualDJ), replication data \u0026 LaTeX. Zenodo DOI 10.5281/zenodo.19618271.","archived":false,"fork":false,"pushed_at":"2026-04-17T00:49:24.000Z","size":456,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-17T01:31:55.659Z","etag":null,"topics":["bpm-detection","camelot-wheel","dj-software","engine-dj","latex","metadata-quality","music-information-retrieval","python","rekordbox","replication-package","serato","udms","virtualdj"],"latest_commit_sha":null,"homepage":"https://doi.org/10.5281/zenodo.19618271","language":"TeX","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/interfluve-wav.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":".zenodo.json","notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-16T23:38:42.000Z","updated_at":"2026-04-17T00:49:28.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/interfluve-wav/dj-metadata","commit_stats":null,"previous_names":["interfluve-wav/dj-metadata"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/interfluve-wav/dj-metadata","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interfluve-wav%2Fdj-metadata","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interfluve-wav%2Fdj-metadata/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interfluve-wav%2Fdj-metadata/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interfluve-wav%2Fdj-metadata/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/interfluve-wav","download_url":"https://codeload.github.com/interfluve-wav/dj-metadata/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interfluve-wav%2Fdj-metadata/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31911846,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-16T18:22:33.417Z","status":"online","status_checked_at":"2026-04-17T02:00:06.879Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bpm-detection","camelot-wheel","dj-software","engine-dj","latex","metadata-quality","music-information-retrieval","python","rekordbox","replication-package","serato","udms","virtualdj"],"created_at":"2026-04-17T02:00:36.775Z","updated_at":"2026-04-17T02:00:41.382Z","avatar_url":"https://github.com/interfluve-wav.png","language":"TeX","funding_links":[],"categories":[],"sub_categories":[],"readme":"# UDMS: A canonical schema and assessment framework for DJ metadata quality\n\n[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.19618271.svg)](https://doi.org/10.5281/zenodo.19618271)\n[![Zenodo record](https://img.shields.io/badge/Zenodo-record-blue)](https://zenodo.org/records/19618271)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)\n[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)\n\n**Python (schema + analysis)** · **LaTeX paper** · **Four DJ platforms (Rekordbox, Serato, Engine DJ, VirtualDJ)**\n\n**Preprint (archived PDF):** [Zenodo record 19618271](https://zenodo.org/records/19618271) · [https://doi.org/10.5281/zenodo.19618271](https://doi.org/10.5281/zenodo.19618271)\n\n*Replication bundle: UDMS (eleven canonical fields) plus adapters for Rekordbox, Serato, Engine DJ, and VirtualDJ, cross-platform comparison code, anonymized parsed exports, JSON Schema, and the LaTeX paper in `paper/`.*\n\nWe present the first cross-platform metadata quality analysis of real-world DJ libraries. Using UDMS (Unified DJ Metadata Schema), we analyze 636 Rekordbox tracks, 382 Serato tracks, 112 Engine DJ tracks, and 190 VirtualDJ tracks — matching 143 tracks across Rekordbox and Serato, and 22 tracks across Rekordbox and VirtualDJ — quantifying how reliably metadata is preserved across ecosystem boundaries.\n\n## Key Findings\n\n| Finding | Value |\n|---------|-------|\n| Genre annotation coverage | 31–69% (varies by platform) |\n| Editorial metadata (ratings, labels) | 0–53% (sparse) |\n| Musical key coverage | 93–98% (best across platforms) |\n| BPM coverage | 100% (Rekordbox) |\n| Cross-platform key agreement (exact / effective) | 71.3% / 100% |\n| BPM disagreement | Explained by systematic 2× half-tempo interpretation difference in Rekordbox for half-tempo genres |\n| Key finding | Title, artist, album are perfectly preserved across platforms (100%) |\n\nRekordbox applies a 95 BPM threshold heuristic when analyzing half-tempo genres (UK dubstep, drum-and-bass, footwork, Jersey Club), causing it to store BPM at exactly 2× the actual tempo. Engine DJ and Serato store the correct value. This is a systematic interpretation difference, not a cross-platform transfer issue.\n\n## UDMS — Unified DJ Metadata Schema\n\nUDMS normalizes 11 canonical fields across Rekordbox, Serato, Engine DJ, VirtualDJ, and Traktor. The Python implementation is in `code/schema/udms_schema.py`.\n\n**UDMS fields:** title, artist, album, genre, BPM, key (Camelot), rating (0–5), label, duration_sec, bitrate, sample_rate\n\n**Key normalization:** OpenKey and Traditional notations are normalized to Camelot (e.g., \"Fm\" → \"4A\"). Rating is normalized from platform-specific scales to 0–5 stars.\n\n**BPM 2× detection:** UDMS flags potential 2× errors by checking if `1.95 \u003c platform_bpm / reference_bpm \u003c 2.05`.\n\n## Repository Structure\n\n```\ndj-metadata-study/\n├── paper/\n│   ├── main.tex              — LaTeX paper (27 pages)\n│   ├── preamble.tex          — LaTeX preamble (packages, macros)\n│   ├── references.bib        — 35 citations (all cited)\n│   ├── cite.sty\n│   └── fig_*.pdf             — All figures\n├── code/\n│   ├── schema/\n│   │   └── udms_schema.py    — UDMS schema + 5 platform adapters\n│   ├── compare_platforms.py  — Cross-platform comparison engine\n│   └── parse_serato.py        — Parse Serato database V2 binary\n├── data/\n│   ├── rekordbox_tracks_parsed.json    — 636 Rekordbox tracks (UDMS format)\n│   ├── serato_tracks.json / .csv       — 382 Serato tracks (UDMS format)\n│   ├── engine_dj_tracks.csv            — 112 Engine DJ tracks (UDMS format)\n│   ├── virtual_dj_tracks.csv           — 190 VirtualDJ tracks (UDMS format)\n│   ├── cross_platform_comparison.json  — 143 matched Rekordbox/Serato tracks\n│   ├── engine_dj_comparison.json / .csv — Engine DJ cross-platform results\n│   ├── virtual_dj_comparison.json / .csv — VirtualDJ cross-platform results\n│   ├── bpm_validation_table.json       — Audio BPM validation subset\n│   └── serato_database_v2             — Raw Serato binary DB (input)\n├── schema/\n│   └── udms_schema.json      — Standalone JSON schema definition\n├── ARCHITECTURE.md\n├── CONTRIBUTING.md\n└── .gitignore\n```\n\n## Compiling the Paper\n\n```bash\ncd paper\nrm -f aux bbl blg\npdflatex main.tex\nbibtex main.aux\npdflatex main.tex\npdflatex main.tex\n```\n\nThe paper compiles to 27 pages with no errors.\n\n\n## Running the Analysis\n\n```bash\n# Cross-platform comparison (requires rekordbox XML + serato JSON)\npython code/compare_platforms.py \\\n  --rekordbox path/to/library.xml \\\n  --serato data/serato_tracks.json \\\n  --output data/cross_platform_comparison.json\n```\n\nRequirements: Python 3.10+.\n\n## Companion Tools\n\n**[rekordbox-smart-mcp](https://github.com/interfluve-wav/rekordbox-smart-mcp)** — MCP server for Rekordbox library management. 33 tools covering library queries, smart playlists, BPM cache with multi-algorithm voting, Camelot key normalization, and safe mutations with full audit logging. 20/20 tests passing.\n\n**[Bonk!](https://github.com/interfluve-wav/bonk-app)** — Electron+React desktop DJ metadata editor. Reads Rekordbox XML and master.db directly, normalizes BPM/key via aubio and keyfinder-cli, writes back to Rekordbox.\n\n## Citation\n\n```bibtex\n@misc{chitturi2026djmetadata,\n  author  = {Suhaas Chitturi},\n  title   = {UDMS: A canonical schema and assessment framework for {DJ}\n             metadata quality},\n  year    = {2026},\n  publisher = {Zenodo},\n  doi     = {10.5281/zenodo.19618271},\n  url     = {https://doi.org/10.5281/zenodo.19618271},\n}\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finterfluve-wav%2Fdj-metadata","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finterfluve-wav%2Fdj-metadata","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finterfluve-wav%2Fdj-metadata/lists"}