# apj72/dj-meta-manager architecture

> Architecture diagram of the GitHub repository apj72/dj-meta-manager, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-29). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/apj72/dj-meta-manager
- Repository: https://github.com/apj72/dj-meta-manager

## Overview

DJ MetaManager is a local web application for turning recordings and existing audio files into a tagged DJ library. Its main workflow extracts audio from recordings, optionally analyses and normalises it, fetches metadata and artwork, then tags and exports the result. Other branches cover editing and inspecting files, batch conversion and fixing, loudness normalisation, lossless analysis, and Music.app playlist capture. The graph reflects documented workflows and indexed module references; some UI-to-route wiring and unsampled implementations are represented only at the subsystem level.

Main entry points: [`static/app.js`](https://github.com/apj72/dj-meta-manager/blob/master/static/app.js) (Local Web UI), [`app.py`](https://github.com/apj72/dj-meta-manager/blob/master/app.py) (Extract recordings), [`capture/manager.py`](https://github.com/apj72/dj-meta-manager/blob/master/capture/manager.py) (Capture coordinator), [`capture/routes.py`](https://github.com/apj72/dj-meta-manager/blob/master/capture/routes.py) (Capture API)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_library["Extract and Library"]
  node_extract["Extract recordings<br/>[app.py]"]
  node_audio["Audio processing<br/>[audio.py]"]
end

subgraph group_metadata["Metadata and Analysis"]
  node_metadata["Tag and artwork<br/>[metadata.py]"]
  node_scrapers["Metadata sources<br/>[scrapers.py]"]
  node_spectral["Lossless analysis<br/>[spectral.py]"]
  node_cue["Mix Tags<br/>[cue.py]"]
end

subgraph group_capture["Playlist Capture"]
  node_routes["Capture API<br/>[routes.py]"]
  node_manager["Capture coordinator<br/>[manager.py]"]
  node_models["Session state<br/>[models.py]"]
  node_store[("Session manifests<br/>[storage.py]")]
  node_music["Music.app control<br/>[music.py]"]
  node_backend["Recorder interface<br/>[base.py]"]
  node_obs["OBS recorder<br/>[obs.py]"]
  node_blackhole["BlackHole recorder<br/>[blackhole.py]"]
  node_captureprocess["Track processing<br/>[processing.py]"]
end

subgraph group_interface["Browser Interface"]
  node_webui["Local Web UI<br/>[app.js]"]
  node_fixinspect["Fix and Inspect<br/>[fix.js]"]
  node_bulkfix["Bulk Fix<br/>[bulk-fix.js]"]
  node_fixlist["Fix List<br/>[fix-list.js]"]
  node_convert["WAV/AIFF conversion<br/>[convert.js]"]
  node_normalise["Normalise<br/>[normalise.js]"]
  node_losslessui["Lossless Check UI<br/>[lossless-check.js]"]
  node_player["Audio preview<br/>[player.js]"]
  node_captureui["Capture Playlist UI<br/>[capture.js]"]
end

subgraph group_configuration["Settings"]
  node_settings["Settings<br/>[config.py]"]
end

node_dj(("DJ or Librarian"))

node_dj -->|"uses"| node_webui
node_webui -->|"requests extraction"| node_extract
node_extract -->|"processes audio"| node_audio
node_extract -->|"fetches metadata"| node_scrapers
node_extract -->|"writes tags"| node_metadata
node_extract -->|"analyses audio"| node_spectral
node_extract -->|"reads options"| node_settings
node_fixinspect -->|"edits tags"| node_metadata
node_bulkfix -->|"batch fixes"| node_metadata
node_fixlist -->|"searches metadata"| node_scrapers
node_convert -->|"converts files"| node_audio
node_normalise -->|"normalises files"| node_audio
node_losslessui -->|"checks spectra"| node_spectral
node_player -->|"streams audio"| node_extract
node_settings -->|"configures output"| node_extract
node_dj -->|"starts capture"| node_captureui
node_captureui -->|"calls capture API"| node_routes
node_routes -->|"dispatches commands"| node_manager
node_manager -->|"updates session"| node_models
node_manager -->|"persists session"| node_store
node_manager -->|"controls playback"| node_music
node_manager -->|"records audio"| node_backend
node_manager -->|"processes tracks"| node_captureprocess
node_obs -->|"implements interface"| node_backend
node_blackhole -->|"implements interface"| node_backend
node_routes -->|"selects backend"| node_obs
node_routes -->|"selects backend"| node_blackhole
node_captureprocess -->|"applies tags"| node_metadata
node_webui -->|"opens tools"| node_fixinspect
node_webui -->|"opens tools"| node_bulkfix
node_webui -->|"opens tools"| node_fixlist
node_webui -->|"opens tools"| node_convert
node_webui -->|"opens tools"| node_normalise
node_webui -->|"opens tools"| node_losslessui
node_webui -->|"provides preview"| node_player

click node_webui "https://github.com/apj72/dj-meta-manager/blob/master/static/app.js"
click node_extract "https://github.com/apj72/dj-meta-manager/blob/master/app.py"
click node_audio "https://github.com/apj72/dj-meta-manager/blob/master/audio.py"
click node_metadata "https://github.com/apj72/dj-meta-manager/blob/master/metadata.py"
click node_scrapers "https://github.com/apj72/dj-meta-manager/blob/master/scrapers.py"
click node_spectral "https://github.com/apj72/dj-meta-manager/blob/master/spectral.py"
click node_fixinspect "https://github.com/apj72/dj-meta-manager/blob/master/static/fix.js"
click node_bulkfix "https://github.com/apj72/dj-meta-manager/blob/master/static/bulk-fix.js"
click node_fixlist "https://github.com/apj72/dj-meta-manager/blob/master/static/fix-list.js"
click node_convert "https://github.com/apj72/dj-meta-manager/blob/master/static/convert.js"
click node_normalise "https://github.com/apj72/dj-meta-manager/blob/master/static/normalise.js"
click node_losslessui "https://github.com/apj72/dj-meta-manager/blob/master/static/lossless-check.js"
click node_player "https://github.com/apj72/dj-meta-manager/blob/master/static/player.js"
click node_settings "https://github.com/apj72/dj-meta-manager/blob/master/config.py"
click node_captureui "https://github.com/apj72/dj-meta-manager/blob/master/static/capture.js"
click node_routes "https://github.com/apj72/dj-meta-manager/blob/master/capture/routes.py"
click node_manager "https://github.com/apj72/dj-meta-manager/blob/master/capture/manager.py"
click node_models "https://github.com/apj72/dj-meta-manager/blob/master/capture/models.py"
click node_store "https://github.com/apj72/dj-meta-manager/blob/master/capture/storage.py"
click node_music "https://github.com/apj72/dj-meta-manager/blob/master/capture/music.py"
click node_backend "https://github.com/apj72/dj-meta-manager/blob/master/capture/backends/base.py"
click node_obs "https://github.com/apj72/dj-meta-manager/blob/master/capture/backends/obs.py"
click node_blackhole "https://github.com/apj72/dj-meta-manager/blob/master/capture/backends/blackhole.py"
click node_captureprocess "https://github.com/apj72/dj-meta-manager/blob/master/capture/processing.py"
click node_cue "https://github.com/apj72/dj-meta-manager/blob/master/cue.py"

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_extract,node_audio toneBlue
class node_metadata,node_scrapers,node_spectral,node_cue toneAmber
class node_routes,node_manager,node_models,node_store,node_music,node_backend,node_obs,node_blackhole,node_captureprocess toneMint
class node_webui,node_fixinspect,node_bulkfix,node_fixlist,node_convert,node_normalise,node_losslessui,node_player,node_captureui toneRose
class node_settings,node_dj toneIndigo
```

## Components

### Extract and Library

- [Extract recordings](https://github.com/apj72/dj-meta-manager/blob/master/app.py): `app.py`
- [Audio processing](https://github.com/apj72/dj-meta-manager/blob/master/audio.py): `audio.py`

### Metadata and Analysis

- [Tag and artwork](https://github.com/apj72/dj-meta-manager/blob/master/metadata.py): `metadata.py`
- [Metadata sources](https://github.com/apj72/dj-meta-manager/blob/master/scrapers.py): `scrapers.py`
- [Lossless analysis](https://github.com/apj72/dj-meta-manager/blob/master/spectral.py): `spectral.py`
- [Mix Tags](https://github.com/apj72/dj-meta-manager/blob/master/cue.py): `cue.py`

### Playlist Capture

- [Capture API](https://github.com/apj72/dj-meta-manager/blob/master/capture/routes.py): `capture/routes.py`
- [Capture coordinator](https://github.com/apj72/dj-meta-manager/blob/master/capture/manager.py): `capture/manager.py`
- [Session state](https://github.com/apj72/dj-meta-manager/blob/master/capture/models.py): `capture/models.py`
- [Session manifests](https://github.com/apj72/dj-meta-manager/blob/master/capture/storage.py): `capture/storage.py`
- [Music.app control](https://github.com/apj72/dj-meta-manager/blob/master/capture/music.py): `capture/music.py`
- [Recorder interface](https://github.com/apj72/dj-meta-manager/blob/master/capture/backends/base.py): `capture/backends/base.py`
- [OBS recorder](https://github.com/apj72/dj-meta-manager/blob/master/capture/backends/obs.py): `capture/backends/obs.py`
- [BlackHole recorder](https://github.com/apj72/dj-meta-manager/blob/master/capture/backends/blackhole.py): `capture/backends/blackhole.py`
- [Track processing](https://github.com/apj72/dj-meta-manager/blob/master/capture/processing.py): `capture/processing.py`

### Browser Interface

- [Local Web UI](https://github.com/apj72/dj-meta-manager/blob/master/static/app.js): `static/app.js`
- [Fix and Inspect](https://github.com/apj72/dj-meta-manager/blob/master/static/fix.js): `static/fix.js`
- [Bulk Fix](https://github.com/apj72/dj-meta-manager/blob/master/static/bulk-fix.js): `static/bulk-fix.js`
- [Fix List](https://github.com/apj72/dj-meta-manager/blob/master/static/fix-list.js): `static/fix-list.js`
- [WAV/AIFF conversion](https://github.com/apj72/dj-meta-manager/blob/master/static/convert.js): `static/convert.js`
- [Normalise](https://github.com/apj72/dj-meta-manager/blob/master/static/normalise.js): `static/normalise.js`
- [Lossless Check UI](https://github.com/apj72/dj-meta-manager/blob/master/static/lossless-check.js): `static/lossless-check.js`
- [Audio preview](https://github.com/apj72/dj-meta-manager/blob/master/static/player.js): `static/player.js`
- [Capture Playlist UI](https://github.com/apj72/dj-meta-manager/blob/master/static/capture.js): `static/capture.js`

### Settings

- [Settings](https://github.com/apj72/dj-meta-manager/blob/master/config.py): `config.py`

### Other components

- **DJ or Librarian**

## Connections

- DJ or Librarian → Local Web UI: uses (evidence: `README.md`)
- Local Web UI → Extract recordings: requests extraction (evidence: `README.md`)
- Extract recordings → Audio processing: processes audio (evidence: `app.py`)
- Extract recordings → Metadata sources: fetches metadata (evidence: `app.py`)
- Extract recordings → Tag and artwork: writes tags (evidence: `app.py`)
- Extract recordings → Lossless analysis: analyses audio (evidence: `app.py`)
- Extract recordings → Settings: reads options (evidence: `README.md`)
- Fix and Inspect → Tag and artwork: edits tags (evidence: `README.md`)
- Bulk Fix → Tag and artwork: batch fixes (evidence: `README.md`)
- Fix List → Metadata sources: searches metadata (evidence: `README.md`)
- WAV/AIFF conversion → Audio processing: converts files (evidence: `README.md`)
- Normalise → Audio processing: normalises files (evidence: `README.md`)
- Lossless Check UI → Lossless analysis: checks spectra (evidence: `README.md`)
- Audio preview → Extract recordings: streams audio (evidence: `README.md`)
- Settings → Extract recordings: configures output (evidence: `README.md`)
- DJ or Librarian → Capture Playlist UI: starts capture (evidence: `README.md`)
- Capture Playlist UI → Capture API: calls capture API (evidence: `capture/routes.py`)
- Capture API → Capture coordinator: dispatches commands (evidence: `capture/routes.py`)
- Capture coordinator → Session state: updates session (evidence: `capture/manager.py`)
- Capture coordinator → Session manifests: persists session (evidence: `capture/manager.py`)
- Capture coordinator → Music.app control: controls playback (evidence: `capture/manager.py`)
- Capture coordinator → Recorder interface: records audio (evidence: `capture/manager.py`)
- Capture coordinator → Track processing: processes tracks (evidence: `capture/manager.py`)
- OBS recorder → Recorder interface: implements interface (evidence: `capture/backends/obs.py`)
- BlackHole recorder → Recorder interface: implements interface (evidence: `capture/backends/blackhole.py`)
- Capture API → OBS recorder: selects backend (evidence: `capture/routes.py`)
- Capture API → BlackHole recorder: selects backend (evidence: `capture/routes.py`)
- Track processing → Tag and artwork: applies tags (evidence: `capture/processing.py`)
- Local Web UI → Fix and Inspect: opens tools (evidence: `README.md`)
- Local Web UI → Bulk Fix: opens tools (evidence: `README.md`)
- Local Web UI → Fix List: opens tools (evidence: `README.md`)
- Local Web UI → WAV/AIFF conversion: opens tools (evidence: `README.md`)
- Local Web UI → Normalise: opens tools (evidence: `README.md`)
- Local Web UI → Lossless Check UI: opens tools (evidence: `README.md`)
- Local Web UI → Audio preview: provides preview (evidence: `README.md`)
