Guide & Support
AI DJ Pro — Complete Technical Guide
Combined reference for architecture, sessions, library, mixing, session alignment, waveform fades, Set Cue, stems, deck effects, loops, sound FX, sampler, backup, crowd requests, MC, AI tools, configuration, and troubleshooting.
New to AI DJ Pro?
Prefer plain language? The user guide covers the same workflows without technical jargon — perfect for first-time DJs and party hosts.
1. Big picture
AI DJ is a local-first DJ application: your music stays on your machine, playback and mixing run in the desktop app, and a Python DJ brain on your PC chooses tracks, drives auto-mix timing, and generates host (MC) announcements. Optional cloud APIs (OpenAI, ElevenLabs) power AI search, set planning, and voice — but core playback does not require them.
Plain-language guide for first-time DJs and party hosts — no technical jargon required.
Simple User GuideDivision of labour
| Layer | Responsibility |
|---|---|
| Electron client | Dual decks (A/B), crossfader, waveforms, transport, library UI, MC audio playback, volume ducking during MC |
| WebSocket server | Session state, track queue, smart next-track picks, MC text generation, TTS orchestration, crowd queue, license checks |
| HTTP file server | Serves local files from your music folder; proxies YouTube streams for in-browser playback |
| Crowd HTTP server | Simple web form on your LAN so guests can request songs from their phones |
The client and server talk over ws://127.0.0.1:8765. The UI must stay connected for crowd requests and server-driven auto mix to work.
2. Components and ports
| Port | Service | Purpose |
|---|---|---|
| 8765 | WebSocket (AIDJ_WS_PORT) | All DJ commands and real-time updates |
| 8766 | HTTP (AIDJ_HTTP_PORT) | Local audio files, /health, YouTube stream proxy |
| 8767 | Crowd HTTP (AIDJ_CROWD_HTTP_PORT) | Guest song-request form (LAN) |
Key source files
| Area | File |
|---|---|
| Backend hub | aidj_server.py |
| Feature helpers | aidj_features.py |
| Waveform / mix cues | waveform_analysis.py |
| Library AI search | library_ai_search.py |
| AI set builder | ai_set_builder.py |
| MC templates / AI lines | mc_brain.py |
| Desktop UI logic | electron_mock/renderer.js |
| Electron shell | electron_mock/main.js |
| Waveform rendering | electron_mock/ProfessionalWaveform.js |
| Backup / Restore UI | electron_mock/BackupRestore.js |
| User quick start | README.md |
Production vs development
- Installed app: Electron spawns bundled aidj-server.exe, waits for http://127.0.0.1:8766/health, then opens the UI.
- Development: Run python aidj_server.py and npm start in electron_mock/ separately.
Default music folder on first install: Documents\AI DJ\Music (Windows) or ~/Documents/AI DJ/Music (macOS).
3. First run and data storage
Setup wizard
On first successful library load, a 4-step setup wizard may appear (unless you already completed it):
- Music folder — point at your MP3/M4A/FLAC library
- API keys — optional OpenAI / ElevenLabs for AI and MC voice
- Crowd requests — LAN URL and QR code for guests
- Analyze a track — BPM/key for beat grid and auto cues
Completion is stored in browser localStorage as AIDJ_SETUP_COMPLETE.
Where data lives (Windows example)
%APPDATA%\AI_DJ_Demo_Pro\
| Data | Location |
|---|---|
| App config | aidj_config.json |
| Track genres / metadata | track_metadata.json |
| Waveform cache | waveform_cache/ |
| Crowd blocklist | crowd/blocklist.json |
| License blob | Encrypted, via license_storage.py |
| Server log | aidj-server.log (packaged) |
| Sampler banks + settings | Electron userData\sampler\ (banks.json, settings.json) |
| Sampler audio files | userData\sampler\files\ or user-chosen folder (settings.json → filesDir) |
On Windows packaged builds, Electron userData is typically %APPDATA%\AI DJ\.
The client also mirrors the library in IndexedDB (AIDJLibrary) so reopening the library panel can show tracks immediately while refreshing from the server in the background.
4. The music library
Scanning local files
On startup (and when you change the music folder), the server scans AIDJ_MUSIC_DIR for: .mp3, .m4a, .flac, .wav, .ogg, .aac
For each file it builds a library item with title, artist, duration, BPM and musical key (Camelot), genre, album art, beat grid origin, and mix cue.
Library panel (client)
- Search, filter by genre / BPM / Camelot / date added
- Sort and drag-to-reorder (playlist order)
- Half / Full layout — half docks the sheet so decks stay usable; drag tracks onto Deck A/B
- Wave column — spectral waveform thumbs (fetched via get_library_waveforms; YouTube ids / filenames matched for streams)
- Album art when available; compact rows for 1080p
- Double-click — set as starting track or play (mode-dependent)
- Right-click — queue next (auto mode)
- Genre editing, AI genre detect, dedications, remove from playlist, add to saved playlist
- Stems button — local files only; YouTube streams show N/A
- In manual mode: Load Deck A / B buttons per row (requires Start Session first — in-app reminder if you load early; DJ Phone Start syncs desktop started)
- In auto mode (session active): live/next deck indicators on rows
Request full library sync: client sends get_library → server responds with { type: "library", tracks: [...] }.
Saved playlists & analysis tools
Save the current library view to IndexedDB (named playlists) and reload later, including save filtered by genre. Add to playlist appends a single track into a named list. Wire-format playlists from YouTube preserve order; sequential queue mode plays them in list order instead of smart reordering.
| Action | What it does |
|---|---|
| Analyze missing BPM | Batch BPM, beat grid, Camelot for tracks that lack them |
| Detect genre (AI) | OpenAI one-word genre for a single track |
| Analysis queue | Full waveform + cue analysis for all tracks missing data |
5. YouTube and streaming
Single track import
Paste a URL → Load YouTube (Add) or Replace. Server uses yt-dlp + FFmpeg to download (or stream), analyzes BPM/key, adds to state.lib, and pushes library_update to the client. Duplicate detection can warn before adding a second copy of the same song.
Playlist import (stream mode)
- Resolve — yt_playlist_resolve returns track list without downloading everything
- Load — yt_playlist_load adds entries as stream URLs: http://127.0.0.1:8766/stream/youtube?id=VIDEO_ID
- Background preload — parallel BPM/key/genre for tracks that need metadata (configurable concurrency)
- Download — ai_set_download with source: "yt_playlist" writes audio into a user-chosen folder (same download pipeline as AI Set Builder)
- Cancel on new load — client bumps playlist_load_generation / beginPlaylistLoad so stale preload/analysis cannot clear busy state for a newer list
Replace during a live session: the library swaps, but the currently playing track keeps going until it ends or you skip — the new list does not hijack the mix mid-song. Stems: streamed YouTube paths are not Demucs-eligible; library UI shows N/A.
Playback URLs
- Local files → file:// or http://127.0.0.1:8766/... (served from music dir only — path traversal blocked)
- YouTube → stream proxy on 8766
First play of a YouTube stream may take 15–30 seconds while the pipeline starts. Duplicate detection can warn before adding a second copy of the same song.
6. Running a session
Start
- Load a library (local folder and/or YouTube playlist).
- Optionally double-click a starting track in the library.
- Press Start on the desktop or Start from DJ Phone (/dj/mc) → client sends { type: "start" } (phone path uses remote_control → proxy_ws). Optional welcome MC if MC is enabled.
- Desktop sets local started = true (phone Start also calls applyLocalSessionStarted so Library load/queue works without a second Start on the PC).
- Server sets started = true and the player loop picks the first track (crowd queue, DJ-selected starting track, or first in queue).
- Server sends incoming (with optional next_track) → client loads the live deck and soft-preloads the next track on the idle deck in parallel.
During the session
- Pause — freezes client audio and server track clock; resume continues the same song.
- Next Track (auto only) — skip to next pick with an immediate linear crossfade (quickFade: skips beat-phrase wait). Soft-reuse plays the idle deck if already buffered; otherwise takes over the in-progress soft-preload without restarting the download. Gain nodes call cancelScheduledValues before setValueAtTime so a leftover fade curve cannot throw and abort the load.
- Energy slider — crowd energy 0–100; biases BPM targets for smart selection.
- End — goodbye MC (optional) → music fade out → session reset.
Stop
- Client: { type: "stop" }
- Optional goodbye MC → client plays TTS wav
- Server: fade_out (default ~8s) → client fades gains → fade_complete
- Server: stop_ack — library queue reset, stats finalized
Decks A and B
Two logical decks alternate in auto mode. Server toggles state.deck between A and B each transition. Live deck = on air; idle deck = soft-preloaded with the next track as soon as session start / post-mix (maybePreloadNextTrackOnIdleDeck, preloadOnly: true) so Next can take over immediately.
7. Auto mix vs manual mix
Toggle via mix control mode (stored in localStorage, synced to server as mix_control_mode). In manual mode the horizontal crossfader uses a center dead zone (snaps near 50%): at center, both decks stay at full volume — fading only begins when you move past center toward Deck A or Deck B.
| Auto mix | Manual mix | |
|---|---|---|
| Track advance | Server timer + skip; sends incoming | You load decks from library; server holds queue |
| incoming messages | Loaded and crossfaded | Ignored |
| Next Track button | Active | Disabled |
| Crossfader | Automated (gains follow live deck) | You blend Deck A ↔ B (center = both full) |
| Phrase / Bar / Phase lock / Set Cue | Active | Auto-only — not used for manual blends |
| Library | Browse, queue, indicators | Load Deck A / B per row (after Start Session) |
| MC | Server premix/postmix/interval | Intro when you press play on a deck |
| Deck effects / hot cues / loops | Available on both decks | Same — primary tool for live performance |
Use auto for hands-off hosting; manual when you want full DJ control with the crossfader. In manual mode, Load Deck A / B does nothing until Start Session — the app shows a reminder if you try early. DJ Phone Start syncs desktop started so Library load/queue works after a remote start.
Manual crossfader curve
- Center — both gainA and gainB at full level (~80% peak headroom).
- Left of center — Deck A stays full; Deck B fades out toward the left extreme.
- Right of center — Deck B stays full; Deck A fades out toward the right extreme.
This matches hardware DJ mixers with a wide overlap at center. Saved position is in client memory; switching back to auto resets the fader to the live deck.
8. How a transition works
Auto mix is a cooperation between server timing and client audio engineering.
Server side
After sending incoming, the server waits roughly track duration minus overlap. While paused, that clock does not advance. On timeout or skip, it calls pick_next_track(), flips deck, sends the next incoming.
Client side (playOnDeck)
- Resolve crossfade length — always from outgoing waveform analysis (Manual Xfade faders removed; isXfadeAutoMode() is always true).
- Resolve mix-in point (Set Cue: Auto / Drop / Chorus / Beginning from waveform — Manual Set Cue removed from UI). Beginning always starts at 0:00.
- Snap cue to Phrase or Bar grid (see Session alignment controls, section 11).
- Beat-align incoming to outgoing (tempo + phase) at mix start.
- Schedule crossfade; run phase lock during overlap. Non-shock mixes may use slow overlap hold (crossfadeToOverlapHold).
- Update UI: waveforms, deck titles, library deck indicators.
Shock mix (hard transitions)
When Shock mix is enabled (checkbox next to Align on mix), the client may replace a normal crossfade with a shock transition:
- Spinback — outgoing playback rate ramps down + spinback SFX, then hard drop; or
- Echo out — deck Echo wet/feedback automation trails while the next track drops (crossfadeToShockTransition flavor echo).
| Mode | Condition |
|---|---|
| BPM | Incoming vs outgoing BPM differs by more than ~8% |
| Genre | Genres are incompatible for a smooth blend (genresCompatibleForMix) |
| Both | Either condition qualifies (default) |
Style (Auto / Spinback / Echo out): Auto biases spinback on BPM jumps and echo on genre-only jumps.
Runs on natural track end and when you press Next Track. Requires genre metadata for genre-based detection. When Shock is off, or the pair does not qualify for shock, auto mixes use a slow center-hold overlap so both tracks stay audible longer. Fade begin also prefers mixing before beat collapse (vocals-only / soft outro).
Client: evaluateShockTransition() / crossfadeToShockTransition() / crossfadeToOverlapHold() in renderer.js. Persisted: localStorage keys aidj_auto_shock_transition, aidj_shock_mix_trigger, aidj_shock_mix_style. Shock mix is auto mode only — disabled in manual mix, and also disabled while Mashup is Creative (UI greyed out; resolveShockTransitionForMix returns no shock).
Creative Mashup (stem choreography)
When Mashup → Creative is on (session bar, next to Set arc), auto crossfades may choreograph Demucs stem gains on both decks:
- prepareCreativeStemMashup checks both decks for local files + stem cache ready + stem audio loaded.
- Enables stem playback; arms a rotating recipe (vocal_ride, beat_bed, bass_swap).
- After crossfadeToken increments, armPendingStemMashup schedules V/D/B/O gain ramps for the fade duration.
- Shock transitions clear any pending mashup and skip stem choreography.
Persisted: localStorage key aidj_creative_mashup. See Session alignment controls (section 11) — Mashup.
Crossfade audio graph
audioA ──► gainFullMixA ──┐
stem A (V/D/B/O) ─────────┼──► stemBusA ──► … ──► gainA ──┐
│ ├──► gainMusicDuck ──► speakers
audioB ──► gainFullMixB ──┤ │
stem B (V/D/B/O) ─────────┘──► stemBusB ──► … ──► gainB ──┘
audioMC ──► gainMC ──► (parallel, for host voice)MC ducking lowers gainMusicDuck during announcements so the crossfader gains on A/B are untouched. In Stems mode, ducking targets vocals on the active stem deck instead.
9. Smart track selection and set arc
When AIDJ_SMART_SELECTION=1 (default), the server does not pick tracks randomly. find_best_next_track() scores candidates.
Pick priority
- Manually queued track (queue_next / right-click in library)
- Crowd queue (FIFO, approved requests)
- Sequential playlist — if enabled, next in wire order
- Smart selection — scored best match
- Fallback — first available track ≠ current
| Factor | Typical weight | Notes |
|---|---|---|
| Genre | primary | Genre-first ranking in auto mix (camelot_first path); after AIDJ_GENRE_STREAK (default 4) same-genre plays, prefer_genre_variety flips ranking to switch genres |
| BPM closeness | high | Tolerance AIDJ_BPM_TOL (default 6) |
| Camelot key | medium | Harmonic mixing; optional hard filter |
| Energy curve | medium | Set arc phase + crowd energy slider |
| Diversity | lower | Prefer different artists |
| Recent history | — | Avoid last N tracks (AIDJ_AVOID_RECENT) |
Set arc (energy curve)
Set arc dropdown → server energy_arc_mode. See Session alignment controls (section 11) for how Set arc differs from Phrase, Bar, and Phase lock.
| Mode | Behaviour |
|---|---|
| Auto | Phases by tracks played: build → peak → cooldown (defaults: 3 + 5 tracks). Sequential playlists keep order. |
| Warm up | Force build phase — gentler, rising BPM; overrides sequential playlist order |
| Peak | Force peak — high energy maintenance; overrides playlist order |
| Cool down | Force wind-down — lower BPM bias; overrides playlist order |
Crowd energy slider (0–100) further nudges target BPM within each phase. Harmonic filter in the library (Δ column vs live deck key) is a UI filter for browsing; smart selection uses its own key logic server-side.
10. Waveforms, cues, and beat alignment
Server analyzes audio (librosa + FFmpeg) to produce peak waveform segments (multi-band colours on deck display), beat grid (BPM + beat_grid_origin), and mix cue (structural mix-in point). Results cached under waveform_cache/ by file hash.
Set Cue modes (client)
| Mode | Mix-in point |
|---|---|
| Auto Cue | Waveform structural cue + grid snap (default) |
| Drop | Emphasis on drop detection |
| Chorus | Emphasis on chorus / lift |
| Beginning | Always mix in from 0:00 with a slower beat-matched fade |
Removed: Manual Set Cue (fixed seconds fader) and the Xfade / Next vertical faders. Fade timing is always waveform Auto Xfade. Full detail: section 18 — Waveform fades and Set Cue.
Fade timing
Always Auto Xfade: fade starts where outgoing waveform energy drops (including before beatless outros). Non-shock transitions may lengthen into a slow overlap hold.
Session alignment toolbar
Phrase, Bar, Phase lock, Set arc, Mashup, Set Cue, Align on mix, and Shock mix — documented in Session alignment controls (section 11) and section 18. Deck waveforms use a centered playhead; near track end the playhead walks right again when the viewport pins. The beat bar dots (1–2–3–4) show live beat position on the playing deck.
11. Session alignment controls
These settings sit in the top control bar (next to Start, Pause, and Next Track). They apply in auto mix mode only — not when you are blending decks manually with the crossfader.
Phrase
Options: 16, 24, 32, 48, 64 beats (default: 32). Align mixes to longer musical phrases on the outgoing track's analyzed beat grid.
Phrase controls when the next crossfade is allowed to start (the app waits for the next phrase boundary when possible) and where the incoming track's mix cue snaps (aligned to the same phrase length on the incoming grid). At 128 BPM, 32 beats is roughly 15 seconds (about 8 bars in 4/4) — a common DJ phrase length.
| Setting | Effect |
|---|---|
| Shorter (16–24) | Tighter, more frequent transitions |
| 32 | Balanced default — musical without feeling rushed |
| Longer (48–64) | Mixes land on bigger section changes |
If waiting for a full phrase would run past the waveform fade window, the app falls back to Bar, then to a single beat, so the mix still happens in time. Saved in browser localStorage (persists across sessions on this machine).
Bar
Options: 4 or 8 beats (default: 4). Finer beat-grid alignment when a full phrase is not used or as a fallback.
- 4 = one bar (four beats in 4/4)
- 8 = two bars
Bar affects the same two things as Phrase — crossfade timing and cue snap — but on a shorter grid. Use 8 for slightly looser bar-line mixes; 4 for tighter alignment to every bar. Saved in browser localStorage.
Phase lock
Options: Off, Low, Medium, High (default: Medium in code; UI may show High if you changed it). Keep beats locked during the crossfade overlap.
While both decks are audible, the app briefly nudges the incoming deck's tempo so its beat phase matches the outgoing deck. When the fade finishes, tempo returns to normal.
| Setting | Effect |
|---|---|
| Off | No beat pulling during the blend |
| Low | Gentle correction |
| Medium | Balanced |
| High | Strongest lock — beats line up fastest; more noticeable tempo micro-adjustments |
Phase lock does not change which song plays next or when the fade is scheduled — only how tightly the beats align while the two tracks overlap. Saved in browser localStorage.
Set arc
Options: Auto, Warm up, Peak, Cool down (default: Auto). Tell the server which energy curve to use when choosing the next track in smart / auto playback.
This does not control crossfade length, cue points, or beat alignment. It influences BPM and energy of upcoming picks (and related smart-selection logic). Saved on the server for the active session (sent over WebSocket when you change the dropdown).
| Mode | Behavior |
|---|---|
| Auto | Natural set flow over time: build energy early, maintain a peak, then cool down. With a fixed playlist / sequential queue, order is preserved. |
| Warm up | Prefer lower-BPM build zone picks — overrides strict playlist order |
| Peak | Prefer higher-BPM peak picks — overrides playlist order |
| Cool down | Prefer easing / lower-energy picks — overrides playlist order |
Mashup
Options: Off, Creative (default: Off). Optional Creative stem choreography during auto crossfades.
When Creative is on and both decks have Demucs stems cached and loaded:
- The client enables stem playback on outgoing + incoming decks.
- During the crossfade, V/D/B/O gains follow a rotating recipe (e.g. vocal ride over incoming beat, beat bed → vocal handoff, bass swap).
- After the fade, stem mutes restore to full stems (or you can switch back to Full mix manually).
| Requirement | Notes |
|---|---|
| Local files | YouTube / stream decks are skipped |
| Stems ready | Separate stems on both tracks first |
| Auto mix | Ignored in manual mix mode |
Mutual exclusion with Shock mix: While Mashup is Creative, the Shock mix checkbox and trigger dropdown are disabled, and shock transitions will not run. Turning Mashup Off restores Shock mix to your saved preference.
Client: prepareCreativeStemMashup / scheduleStemMashupMacro in renderer.js. Saved in browser localStorage key aidj_creative_mashup.
How they work together
Outgoing track playing
│
▼
Phrase / Bar ──► wait for grid boundary (when possible)
│
▼
Incoming track cue snapped to same grid idea
│
▼
Mashup (if Creative + stems ready) ──► stem recipe armed
│
▼
Crossfade starts (timing follows waveform Auto Xfade)
│ (Shock mix skipped when Mashup is Creative)
▼
Phase lock ──► micro-tempo on incoming deck during overlap
│
▼
Set arc ──► (parallel) server picks next track for following transition| Control | Affects | Scope |
|---|---|---|
| Phrase | Long-grid mix start + cue snap | Client (auto mix) |
| Bar | Short-grid mix start + cue snap / fallback | Client (auto mix) |
| Phase lock | Beat alignment during overlap | Client (auto mix) |
| Set arc | Next-track energy / BPM bias (locked modes override playlist order) | Server |
| Mashup | Stem V/D/B/O choreography during auto fades | Client (auto mix) |
Related settings (not in this toolbar)
- Fade timing — always waveform Auto Xfade (Manual Xfade / Next faders removed). See section 18.
- Set Cue — Auto Cue / Drop / Chorus / Beginning mix-in (session toolbar; Manual Set Cue removed). See section 18.
- Shock mix — spinback or echo-out on big BPM/genre jumps; otherwise slow overlap hold (auto mode only; disabled while Mashup is Creative). See section 8 and /guide/user#shock-mix.
- Deck effects / hot cues / auto loops — per-deck knobs, C1–C8 cues, and 4/8 beat loops. See section 20.
- Sound FX / Sampler / Backup — one-shots, custom pads, and disaster-recovery export. See section 21 and /guide/user#sound-fx-sampler.
- Manual mix mode — Phrase, Bar, Phase lock, and Mashup are for auto mix; in manual mode press Start Session, then load decks and blend yourself. DJ Phone Start syncs desktop started so Library load/queue works after a remote start.
Tips
- Start with Phrase 32, Bar 4, Phase lock Medium or High, Set arc Auto, Mashup Off for typical club/party sets.
- Raise Phrase if mixes feel too busy; lower it if you want quicker turnover.
- Use Set arc → Warm up at the start of an event or Cool down for last hour — without touching mix timing controls.
- Use Mashup → Creative only when both decks show Stems ready; otherwise the log will say the mashup was skipped.
12. The MC (host) system
The MC is an optional AI/host voice that speaks between or over tracks.
Generation pipeline
- Prompt — event context, venue, track title, energy, dedication, Mem0 memories (optional).
- Line source — OpenAI (AIDJ_LIVE_AI_MC) and/or script templates (default, hype, smooth, wedding, etc.).
- TTS — ElevenLabs if API key configured; else local pyttsx3.
- Delivery — server sends { type: "mc", text, wav_path, duck_enabled, duck_level } → client plays audioMC.
| Trigger | When |
|---|---|
| intro | Session welcome |
| premix | Before track (if enabled + seconds configured) |
| postmix | Shortly after track starts |
| interval | Every N minutes (mc_interval_min) |
| goodbye | Session end |
| manual | Test button or manual deck intro (manual mix) |
Ducking & settings
While MC speaks, music volume ramps down via gainMusicDuck (default ~30%). On end, music restores and client sends mc_done so the server can continue timing.
- Event prompt, venue name, DJ name
- Enable/disable MC, interval minutes, premix/postmix delay seconds
- Template set vs live AI lines; language, tone, voice
- Dedicate — one-shot shout-out tied to a specific library track
Rapid Next Track presses temporarily disable skip to prevent chaos. MC announcements can delay skip processing so crossfade timing stays musical.
Deep dive into OpenAI prompting, Mem0, ElevenLabs, Event Prompt customization, banned phrases, and troubleshooting.
Read the full MC System guide13. Crowd song requests
Guests on the same Wi‑Fi open the crowd page (default http://<your-LAN-IP>:8767/).
Guest flow
- Enter song search (artist + title) and optional dedication/name.
- Optional PIN (AIDJ_CROWD_REQUEST_PIN).
- Content filters block explicit, commercial, and movie-trailer style queries.
Server processing
- Fuzzy match local library (AIDJ_CROWD_MIN_MATCH_SCORE, default 0.52).
- Optional AI verification for borderline queries.
- If no match → YouTube search + download/stream for crowd.
- Queue in crowd_play_queue or pending approval if AIDJ_CROWD_REQUIRE_APPROVAL=1.
DJ tools: Crowd link and QR in the top bar, approve/reject pending requests, blocklist for repeat bad queries. Crowd tracks show REQUEST badge in library; play with priority after manual queue.
DJ Phone (booth remote)
Separate from the guest form: open http://<LAN-IP>:8767/dj/mc, unlock with the DJ Phone PIN from MC Settings.
- Start / Pause / Next, deck loads, MC triggers, mix toggles (energy, mashup, shock, cue, SFX)
- Commands arrive as remote_control → proxy_ws on the desktop WebSocket client
- Start from phone calls applyLocalSessionStarted so desktop started matches — Library load / queue works without pressing Start again on the PC
PIN setup, LAN URL, and what you can control from your phone.
Simple User Guide — DJ Phone14. AI features
All AI features require OPENAI_API_KEY unless noted. Keys are stored via server config (not logged).
Library AI Search
Natural-language search: "1980s wedding opener", lyric queries, theme/era/mood. Returns matches from your library plus YouTube suggestions. Paginated load more results. WebSocket: library_ai_search → library_ai_search_result.
AI Set Builder
Plans a full 6–40 track set from a prompt with energy flow (warmup → build → peak → cooldown), BPM/key smoothing, and marks library vs YouTube import needs. Stream set loads the set as the live queue (library fuzzy match + YouTube stream fallback). Download set writes audio into a user-chosen folder plus an .m3u playlist (ai_set_download). WebSocket: ai_set_builder → ai_set_builder_result; ai_set_download → progress / result.
Genre detection & MC
- Genre: ID3 tags → heuristics → AI detect (OpenAI) → manual override
- MC lines: OpenAI + optional Mem0 for venue-specific memories
- ElevenLabs v3 emotional tags optional for richer TTS
15. Client ↔ server communication
URL: ws://127.0.0.1:8765 (configurable via AIDJ_WS_PORT). On connect: license status, API config, energy arc, mix control mode, MC context. Reconnect with exponential backoff if server restarts.
Important client → server messages
| Message | Purpose |
|---|---|
| start / pause / stop | Session transport |
| cmd + skip | Next track (auto) |
| mix_control_mode | Auto vs manual |
| get_library / set_music_dir | Library sync |
| yt_add / yt_playlist_resolve / yt_playlist_load | YouTube |
| set_starting_track / queue_next | DJ overrides |
| set_energy_arc / energy | Set arc + crowd energy |
| library_ai_search / ai_set_builder / ai_set_download | AI tools |
| analyze_track / analyze_missing_bpm / start_analysis_queue | Analysis |
| mc_context / mc_advanced / mc_dedication_set | MC settings |
| crowd_request_action / crowd_blocklist_add | Crowd moderation |
| manual_live_track | Manual mode: tell server what's live |
| fade_complete / mc_done | Client acknowledgements |
Important server → client messages
| Message | Purpose |
|---|---|
| library / library_update | Full or partial library sync |
| incoming | Load and mix next track (auto) |
| next_track | Preview of upcoming pick |
| mc | Host audio + ducking params |
| pause_ack / stop_ack / fade_out | Session control |
| skip_button_state | Rate-limit UI |
| yt_import_progress / playlist_preload_* | YouTube pipeline status |
| library_ai_search_result / ai_set_builder_result | AI responses |
| crowd_queue / crowd_request_ack | Crowd UI |
| log | Live log ticker |
| license_status / license_required | Licensing |
Many operations are license-gated (start, library load, YouTube, AI search, set builder, etc.). Set LICENSE_DISABLE=1 in dev config to bypass. Max WebSocket frame size: 32 MiB (large libraries with embedded art).
16. Configuration reference
Config merges: environment variables → user aidj_config.json → bundled aidj_config.json.
Core
| Variable | Default | Meaning |
|---|---|---|
| AIDJ_WS_PORT | 8765 | WebSocket |
| AIDJ_HTTP_PORT | 8766 | File/stream HTTP |
| AIDJ_CROWD_HTTP_PORT | 8767 | Crowd form |
| AIDJ_MUSIC_DIR | (see §2) | Library root |
| AIDJ_OVERLAP_SEC | 8 | Overlap hint for track timing |
| AIDJ_STOP_FADE_SEC | 8 | End-of-session fade |
Selection / energy
| Variable | Default | Meaning |
|---|---|---|
| AIDJ_SMART_SELECTION | 1 | Enable smart next-track scoring |
| AIDJ_GENRE_STREAK | 4 | Same-genre plays before variety flip |
| AIDJ_BPM_TOL | 6 | BPM match tolerance |
| AIDJ_REQUIRE_KEY_MATCH | 0 | Hard-filter incompatible keys |
| AIDJ_REQUIRE_GENRE_MATCH | 0 | Hard-filter genre mismatches |
| AIDJ_AVOID_RECENT | 5 | Recent track memory |
| AIDJ_ENERGY_CURVE | 1 | Energy phase BPM biasing |
| AIDJ_ENERGY_BUILD | 3 | Tracks in build phase |
| AIDJ_ENERGY_PEAK | 5 | Tracks in peak phase |
YouTube / preload
| Variable | Default | Meaning |
|---|---|---|
| AIDJ_FFMPEG_DIR | auto | FFmpeg + ffprobe for yt-dlp |
| AIDJ_PRELOAD_CONCURRENCY | 4 | Parallel metadata preload threads |
| AIDJ_PRELOAD_AI_GENRE | (see config) | AI genre during playlist preload |
Crowd
| Variable | Default | Meaning |
|---|---|---|
| AIDJ_CROWD_HTTP | 1 | Enable crowd server |
| AIDJ_CROWD_REQUEST_PIN | — | Optional guest PIN |
| AIDJ_CROWD_REQUIRE_APPROVAL | 0 | Hold requests for DJ approve |
| AIDJ_CROWD_MIN_MATCH_SCORE | 0.52 | Library fuzzy match threshold |
| AIDJ_CROWD_BLOCK_EXPLICIT | 1 | Block explicit YouTube imports |
| AIDJ_CROWD_BLOCK_COMMERCIAL | 1 | Block ad-like content |
| AIDJ_CROWD_BLOCK_MOVIE | 1 | Block film/trailer content |
AI / voice
| Variable | Meaning |
|---|---|
| OPENAI_API_KEY | Library search, set builder, genre, MC |
| ELEVEN_API_KEY / ELEVEN_VOICE_ID | MC TTS voice |
| AIDJ_LIVE_AI_MC | Enable live AI MC lines |
| AIDJ_LLM_MODEL | OpenAI model (e.g. gpt-4o-mini) |
Client-only (localStorage)
| Key | Meaning |
|---|---|
| mixControlMode | auto / manual |
| aidj_mix_phrase_beats | Phrase length (16–64) |
| aidj_mix_bar_beats | Bar length (4 or 8) |
| aidj_phase_lock_strength | Phase lock 0–3 |
| aidj_auto_shock_transition | Shock mix enabled |
| aidj_shock_mix_trigger | Shock mix trigger: both / bpm / genre |
| aidj_shock_mix_style | Shock mix style: auto / spinback / echo |
| aidj_creative_mashup | Creative Mashup on/off |
| cueMode | Set Cue mode: auto / drop / chorus / beginning |
| AIDJ_SETUP_COMPLETE | Setup wizard done |
17. License and troubleshooting
License
Online validation (Gumroad / Paddle / FastSpring / generic REST) + offline crypto + trusted keys. UI modals for activation; periodic re-check (~12h). Dev bypass: LICENSE_DISABLE=1 in config.
Common issues
| Symptom | Check |
|---|---|
| WebSocket error / 1006 | Is aidj_server.py running on 8765? |
| No audio from YouTube | FFmpeg path (AIDJ_FFMPEG_DIR), yt-dlp, server console errors |
| ffprobe Win32 error | Broken ffprobe on PATH; use bundled electron_mock/resources/ffmpeg |
| Crowd page unreachable | Firewall, same Wi‑Fi, correct LAN IP, port 8767 |
| Library always loading | Server connected? IndexedDB cache should show tracks while syncing |
| Resume plays wrong track | Server pause clock fix — restart server after updates |
| MC silent | ElevenLabs quota/key, or pyttsx3 fallback on system |
Logs
- Packaged: %APPDATA%\AI_DJ_Demo_Pro\aidj-server.log
- Dev: terminal running python aidj_server.py
- Client: in-app log panel + browser DevTools console
18. Waveform fades and Set Cue
Auto mix fade timing is always waveform-driven. The old vertical Xfade, Next, and Manual Set Cue faders (and Manual/Auto Xfade dropdown) were removed from the UI. In code, isXfadeAutoMode() is always true and isXfadeManualMode() always false.
Set Cue remains as a session-toolbar dropdown: Auto Cue / Drop / Chorus / Beginning.
In manual mix mode, Phrase/Bar/Set Cue/Shock/Align apply to auto transitions only — you load decks yourself and blend with the horizontal crossfader. Loading a deck before Start Session opens an in-app reminder. DJ Phone Start syncs desktop started so Library load/queue works after a remote start.
Outgoing fade (Auto Xfade)
- Fade start and length come from waveform analysis on the outgoing track (detectFadeBeginOnWaveform; prefers mixing before beat collapse / soft outros).
- Fade duration = content end minus fade start (clamped roughly 2–30s; slow-overlap path may lengthen further).
- On the live deck waveform, an orange Fade marker shows where the blend will begin.
- Deck time may count down to fade.
- Automatic transitions: the client watches the live deck and sends a skip when the fade trigger is reached.
- Next Track: immediate linear blend (quickFade / skipBeatAlignment); soft-reuses the idle deck when ready; cancels leftover gain curves before priming.
Set Cue (mix-in)
UI: session toolbar — Auto Cue / Drop / Chorus / Beginning (no Manual mode, no cue fader).
| Mode | Mix-in detection |
|---|---|
| Auto Cue | General structural mix point from waveform |
| Drop | Emphasis on drop / impact |
| Chorus | Emphasis on chorus / lift |
| Beginning | Always from 0:00; slower beat-matched fade (never uses short Next fade length) |
- Mix-in comes from server waveform analysis (mix_cue_sec, mix_cue_drop_sec, mix_cue_chorus_sec), cached per track (skipped in Beginning mode).
- The app aligns that structural point to the outgoing fade window (getAlignedMixCueSec).
- Result is snapped to the Phrase or Bar grid when beat alignment is on (Next Track itself skips beat wait).
- First track of a session always plays from 0:00.
- Temporary fallback: 1s until analysis completes (SMART_CUE_FALLBACK_SEC).
- Waveform markers: live deck orange Fade; incoming deck green Mix.
- Saved in browser localStorage (cueMode).
Non-shock vs shock crossfades
| Path | Behavior |
|---|---|
| Shock (when enabled + trigger matches) | Spinback or echo-out hard transition |
| Slow overlap (default otherwise) | Longer fade, ease to center, hold both decks, then finish (crossfadeToOverlapHold) |
End-to-end: natural mix vs Next Track
Natural mix: Live deck playing → client hits fade trigger (waveform Auto Xfade) → client sends skip to server → server picks next track, sends incoming → client loads other deck at Set Cue point (soft-preload idle deck) → beat-aligned crossfade (Phrase/Bar wait if needed; shock or slow overlap) → new live deck Next Track: You press Next Track → pendingSkip; server skip → soft-reuse idle deck if buffered (else take over soft-preload) → quickFade=true; cancelScheduledValues on gains → immediate linear blend (no phrase / beat wait)
The server's playback timer (AIDJ_OVERLAP_SEC, default 8s) is a rough overlap hint; the client governs the audible blend.
Quick reference
| Control | UI | Notes |
|---|---|---|
| Fade out | (automatic) | Always waveform Auto Xfade |
| Next Track | Button | Immediate blend; soft-reuse idle deck |
| Set Cue | Auto / Drop / Chorus / Beginning | Session toolbar; no Manual fader |
| Shock mix | Checkbox + trigger + style | Optional hard transition |
| Manual mix | Crossfader | Load Deck A/B after Start Session |
| Mode combo | Typical use |
|---|---|
| Auto Cue + Shock off | Smooth party blends with slow overlap |
| Auto Cue + Shock on (Both / Auto style) | Hard cuts on big BPM/genre jumps |
| Drop / Chorus | Steer mix-in character after analysis |
| Beginning | Always start incoming from 0:00 with a slower fade |
| Manual mix | Full hands-on control with crossfader |
Plain-language walkthrough for waveform fades, Set Cue, and deck playheads.
Simple User Guide — How mixes land19. Stem separation (Demucs)
AI DJ can split local tracks into four stems using Demucs htdemucs (vocals, drums, bass, other).
Architecture
- aidj-stems (Windows: aidj-stems.exe; macOS: aidj-stems binary) — bundled worker (PyTorch + Demucs + NumPy). Runs as a subprocess only; the main server never imports torch.
- Cache — per-user folder with four WAV files + meta.json per track hash: %AppData%\AI_DJ_Demo_Pro\stems\<hash>\ (Windows) or ~/Library/Application Support/AI_DJ_Demo_Pro/stems/<hash>/ (macOS).
- HTTP — stems stream at http://127.0.0.1:8766/stems/<cache_key>/<role>.wav.
- Queue — one separation job at a time (CPU/GPU heavy).
Both Windows and macOS installers bundle the stem worker when the PyInstaller build step succeeds (build-installer.bat / build-installer.sh step [2b/6]).
Using stems on decks
Each deck has V / D / B / O pads, a Full mix / Stems toggle, and a status chip.
- Load a local file (not a YouTube stream).
- Click Separate stems in the library row (status sync via stem_status / stem_cache_sync).
- When status shows Stems ready, click Full mix to switch to Stems (short gain crossfade; stems start muted then fade in).
- Click pads to mute; Alt+click to solo a stem.
Waveform and BPM analysis still use the full mix file.
Playback notes
- Stem role gains use STEM_PLAYBACK_MAKEUP (~+2.6 dB) so recombined stems are closer in level to the original file. Demucs separation still sounds slightly different (artifacts / thinner highs) — that is expected.
- Switching Full mix ↔ Stems uses a short Web Audio ramp (STEM_MODE_XFADE_SEC) to avoid a hard mute gap.
- Do not optimistic-queue Demucs on every deck load; the client prefers stem_status_get / cache sync so a stale queued entry cannot shadow a ready cache.
Creative Mashup (auto)
With Mashup → Creative, auto mixes call prepareCreativeStemMashup before the crossfade and schedule stem macros during the fade. Requires stems ready on both decks. Mutually exclusive with Shock mix. See section 8 — Creative Mashup.
MC ducking with stems
When Stems mode is active on a playing deck, MC volume ducking lowers vocals only on that deck instead of ducking the entire mix.
First run & installer size
- First separation downloads htdemucs weights (~80 MB) into the torch hub cache. CPU works; CUDA or Apple Silicon GPU may be used when available.
- The stem worker adds roughly 1.5–2 GB to the installer (PyTorch + Demucs). Build the worker on the same OS and CPU architecture you ship.
Development (from source)
pip install -r requirements-stems.txt python aidj_server.py
In dev, the server runs stem_worker.py via your Python interpreter instead of the bundled aidj-stems binary.
Building / rebuilding the stem worker
Full installer builds include the worker automatically. To rebuild only the stem worker (e.g. after a fix):
Windows:
pip install -r requirements-stems.txt "pyinstaller>=6.14.1" rmdir /s /q electron_mock\resources\aidj-stems python -m PyInstaller --noconfirm --onedir --console --name aidj-stems --log-level WARN ^ --collect-all demucs --collect-all torch --collect-all torchaudio --collect-all soundfile --collect-all numpy ^ stem_worker.py xcopy /E /I /Y dist\aidj-stems\* electron_mock\resources\aidj-stems\ electron_mock\resources\aidj-stems\aidj-stems.exe check
macOS:
pip3 install -r requirements-stems.txt "pyinstaller>=6.14.1" rm -rf electron_mock/resources/aidj-stems python3 -m PyInstaller --noconfirm --onedir --console --name aidj-stems --log-level WARN \ --collect-all demucs --collect-all torch --collect-all torchaudio --collect-all soundfile --collect-all numpy \ stem_worker.py mkdir -p electron_mock/resources/aidj-stems cp -R dist/aidj-stems/* electron_mock/resources/aidj-stems/ chmod +x electron_mock/resources/aidj-stems/aidj-stems electron_mock/resources/aidj-stems/aidj-stems check
The check command should print JSON with "ok": true. Then rebuild the Electron app (npm run dist / npm run dist:mac) or run the full build-installer.bat / build-installer.sh.
Stem troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Stems unavailable / worker not found | Stem worker not bundled or build step [2b/6] failed | Rebuild installer; confirm electron_mock/resources/aidj-stems/ exists before electron-builder |
| No module named numpy.core.multiarray | Old stem worker missing NumPy binaries | Rebuild with --collect-all numpy and PyInstaller ≥ 6.14.1 |
| Separation stuck / failed | Missing FFmpeg, corrupt file, or out of disk/RAM | Ensure bundled ffmpeg is present; try a local MP3/WAV; check server log |
| YouTube track | Stems require a decoded local file | Download or use a file from your music folder |
| Very slow | Demucs on CPU | Normal for long tracks; only one job runs at a time |
| Creative mashup skipped | Stems not ready / not local on both decks | Separate stems on both tracks; check log for the skip reason |
Plain-language walkthrough for V / D / B / O pads, MC + stems, and common fixes.
Simple User Guide — Stem separation20. Deck effects, hot cues, loops, and manual crossfader
Per-deck performance tools live in the Electron client (renderer.js, EchoEffect.js). They work in auto and manual mix.
Effects signal path
eqMix (post-EQ) ──┬──► dry bus ──► effectsOutput ──► analysers ──► gainMusicDuck
│
└──► parallel wet effects ──► wet mix ──┘Each deck has 12 effect sends in two UI rows plus a separate Filter panel (low/high/band-pass when enabled).
| Knob | Audio behavior |
|---|---|
| Reverb | Convolution reverb (generated impulse) |
| Delay | Feedback delay; D.Time / D.Feedback knobs |
| Flanger | Short modulated delay |
| Phaser | All-pass filter chain |
| Echo | Stereo ping-pong delay (EchoEffect.js) — BPM-synced, damped feedback |
| Spiral | LFO-modulated short delay |
| Slip Roll | Tight looping delay |
| Robot | Ring-mod style timbre |
| Mob Saw | Saw LFO → resonant low-pass |
| Mob Tri | Triangle LFO → band-pass |
Echo (electron_mock/EchoEffect.js): dual delay lines with cross-feedback, high-pass on input, low-pass on feedback and wet path. Delay time maps from dotted-eighth to quarter note using deckABPM / deckBBPM when known.
FX bypass toggle
Round FX buttons (deckFxToggleA / deckFxToggleB) appear under the channel fader when the Effects panel is expanded. They toggle effectsAEnabled / effectsBEnabled — wet gains go to zero while knob values are preserved.
Hot cues
- 8 slots per deck (C1–C8); was 4 in earlier builds.
- Shift+click or Shift+1…8 stores the current playhead.
- Cues persist per track URL in localStorage.
- HOT_CUE_COUNT = 8 in renderer.js.
Auto loops (4 / 8)
- Each deck has 4 and 8 buttons (loopAuto4A/B, loopAuto8A/B) beside Loop In/Out.
- Click arms an N-beat loop from the playhead (requires BPM).
- Click again exits.
- Ctrl+click halves length; Shift+click doubles (max 64 beats).
- Active button label updates to the current beat length.
MIDI
Effect and filter knobs are exposed to the MIDI learn system (same pattern as EQ). Hot cue MIDI actions use deck-specific note/CC mappings.
Sampler: pads 1–8 (note on/off = hold/gate like the UI), bank previous/next, stop all, grab beats / grab loop. Stems: mode buttons still enable all stems; individual stem actions match the UI. Creative mashup has a toggle action. The Extended MIDI preset includes default notes for sampler (ch1 notes 12–24) and creative mashup (ch1 note 25).
Exit confirm
Closing the main window requests an in-app confirm (showAppExitConfirm via IPC app-request-exit-confirm / app-exit-confirm-response) instead of the native OS dialog.
Plain-language walkthrough for effect knobs, FX bypass, filters, and C1–C8 cues.
Simple User Guide — Deck effects & hot cues4/8 beat auto loops, exit, and length modifiers.
Simple User Guide — Loops21. Sound FX, sampler, and backup
Center-column performance tools and disaster-recovery backup. Implemented in electron_mock/renderer.js, main.js / preload.js (sampler IPC), and BackupRestore.js.
- Sound FX (gainSfx) and Sampler (gainSampler) are separate buses into gainMaster — FX volume does not affect pads.
- Sampler: banks of 8 pads, optional custom WAV folder, polyphonic playback, pad editor (trim / BPM / sync / loop).
- Pad gestures: Right-click opens/closes the pad editor; Ctrl+click (Cmd on Mac) clears; Shift+click renames.
- Deck capture grabs beats or loop regions; in stem mode, only audible V/D/B/O stems are mixed into the WAV.
- Backup (BackupRestore.js) can optionally embed sampler banks + audio via sampler-export-bundle / sampler-import-bundle.
- Settings → Shortcuts — editable app keyboard shortcut help (#shortcutsHelp).
Sound FX bus
- Built-in library (SFX_LIBRARY) plays through gainSfx → gainMaster.
- sfxVolumePercent (UI: #volSfx) controls only that bus.
- Triggers create fresh HTMLAudioElements so presses stack/overlap.
Sampler architecture
| Piece | Role |
|---|---|
| Banks | userData/sampler/banks.json — multiple banks × 8 pads |
| Settings | userData/sampler/settings.json — optional custom filesDir |
| Audio files | Hex fileId + extension under files/ or custom folder |
| Playback bus | gainSampler → gainMaster (independent of gainSfx) |
| Voices | samplerVoices Map — polyphonic (one voice per pad) |
Pad model: label, fileId, originalName, shortcut, volume, tempo, bpm, loop, trimStart, trimEnd.
- Play / hold: quick tap latches (single plays through trim; loop until re-tap); longer press gates until release. Keyboard shortcuts mirror hold/tap.
- Live pad volume rides HTMLMediaElement.volume with a square-law curve; GainNode holds fixed SAMPLER_PAD_GAIN_MAX makeup so fast slider drags stay reliable in Chromium.
- Clear pad removes the bank reference and deletes the WAV via sampler-delete-file unless another pad still references the same fileId.
Deck capture → pad
IPC: sampler-save-bytes writes a generated WAV.
| Action | Region |
|---|---|
| Grab beats | Last N beats ending at playhead (needs deck BPM) |
| Grab loop | Normalized Loop In/Out |
Stem-aware capture: if deckStemsReady(side), decode/mix only audible stem roles (solo or unmuted V/D/B/O) via toStemPlaybackURL + decodeAudioData. Otherwise use the full-mix deckAudioBufferCache buffer. Peak-normalize before encode (SAMPLER_CAPTURE_TARGET_PEAK).
Sampler IPC (Electron)
| Channel | Purpose |
|---|---|
| sampler-get-state / sampler-save-state | Banks JSON |
| sampler-get-files-dir / choose / reset / open | Custom storage folder |
| sampler-import-files / sampler-import-paths | Copy audio into store |
| sampler-file-url / sampler-delete-file | Resolve / remove |
| sampler-save-bytes | Capture / generated WAV |
| sampler-export-bundle / sampler-import-bundle | Backup bundle (banks + base64 files) |
Key files
| File | Role |
|---|---|
| electron_mock/renderer.js | Pads, capture, stem-aware chop, polyphony |
| electron_mock/main.js / preload.js | Sampler IPC + custom folder + exit confirm |
| electron_mock/BackupRestore.js | Export/import UI and payload |
Backup & Restore
BackupRestore.js builds aidj-backup JSON: server snapshot, IndexedDB playlists/EQ/tracks, localStorage, optional license.
When Include sampler is checked, sampler-export-bundle embeds banks + audio (hard cap ~200 MB). Restore calls sampler-import-bundle into the current files directory (does not force the old PC's absolute filesDir).
UI: #backupRestoreModal — license + sampler checkboxes on export; same sampler checkbox gates restore.
Pad banks, editor, deck grab (including stems), and Backup walkthrough.
Simple User Guide — Sound FX and SamplerWhat is included in exports and how restore remaps library / sampler folders.
Simple User Guide — Backup & RestoreQuick workflows
Party (auto, hands-off)
- Load YouTube playlist or local folder.
- Run Analyze missing BPM if needed.
- Set Set arc → Auto, MC on with event prompt.
- Enable crowd QR.
- Start — let smart selection and crossfades run.
Club segment (manual)
- Switch to manual mix mode.
- Load tracks on Deck A / B from library.
- Blend with crossfader (center = both decks full); use hot cues and deck effects.
- MC intro fires when you play a deck.
Planned wedding set
- AI Set Builder — "wedding cocktail 2h, 90s–today, no explicit".
- Review results, import missing YouTube tracks.
- Stream set (or Download set) with sequential mode.
- Warm up set arc at start; switch to Peak for dancing.
Still need help?
Contact our support team for licensing, setup, or technical questions.
