Professional DJ app for macOS. Pioneer DDJ-200 controller. AI stem separation. Rekordbox-style beat sync.
- Connect DDJ-200 via USB before launching
- Open
U-DJ.appfrom your Desktop - Click + Add Folder → select your music folder
- Tracks analyse automatically in the background (BPM, key, beat grid, cues)
- Drag a track onto each deck or double-click a track to load it
- Press PLAY
| Control | Action |
|---|---|
| PLAY/PAUSE | Play / pause |
| CUE | Set cue / return to cue / stutter play |
| Shift + CUE | Jump to cue and stop |
| SYNC | Sync this deck to the other (see Sync section) |
| Shift + SYNC | Set loop IN point |
| SYNC (2nd press) | Set loop OUT point and activate |
| Control | Action |
|---|---|
| Touch surface (playing) | Scratch — suspends sync momentarily |
| Rim only | Pitch bend |
| Shift + Rim | Key shift ±1 semitone per 5 ticks |
Adjusts playback rate ±16%. Moving the slider while sync is active breaks sync for that deck.
This is the core of U-DJ. The HI / MID / LOW knobs on the DDJ-200 do double duty:
| Mode | How to activate | What the knobs do |
|---|---|---|
| Stem blend | Normal (no Shift) | Crossfade between two stem groups |
| EQ | Hold Shift | 3-band EQ (kill to +10 dB) |
Each knob is a crossfader between two stems. Center = both stems full.
| Knob | Turn LEFT | Center | Turn RIGHT |
|---|---|---|---|
| HI | Kill vocals → only drums | Both full | Kill drums → only vocals |
| MID | Kill bass → only other/synths | Both full | Kill other → only bass |
| LOW | Kill lead synth → only pads | Both full | Kill pads → only lead |
Hard left and hard right are hard cuts — complete silence on that stem.
Stems take ~90 seconds to separate the first time (demucs ML). Check the ● STEMS READY indicator in the mixer panel. Knobs have no effect on audio until stems are ready — the full track plays until then.
Hold Shift then turn HI / MID / LOW for 3-band EQ. Uses soft-pickup — EQ only engages once the knob crosses the current EQ value, preventing jumps.
| Knob | Band | Range |
|---|---|---|
| Shift + HI | High (3.5 kHz+) | Kill to +10 dB |
| Shift + MID | Mid (200 Hz – 3.5 kHz) | Kill to +10 dB |
| Shift + LOW | Low (0 – 200 Hz) | Kill to +10 dB |
Controls Color FX depth directly. Select FX type from the mixer panel dropdown (FILTER, DELAY, REVERB, FLANGER, PHASER, DRIVE).
Press SYNC on the deck you want as master. The other deck locks to its tempo and bar phase.
| Action | Result |
|---|---|
| SYNC on a deck | That deck becomes master, other snaps to bar |
| SYNC on master again | Re-snaps the follower |
| SYNC on follower (both playing) | Follower promotes to master |
| PLAY while sync armed | Snaps to master bar phase on play-start |
Sync is continuous — phase nudge corrects drift automatically. The beat grid strip at the top shows both decks: when bar markers align, you're locked.
Switch pad mode with Shift + first BEAT LOOP pad:
HOT CUE → BEAT LOOP → STEMS → BEAT JUMP → PAD FX → (loop)
Default on startup: BEAT LOOP
| Action | Result |
|---|---|
| Pad (empty) | Set cue at current position (beat-snapped) |
| Pad (set, lit) | Jump to cue and play |
| Shift + pad | Delete cue |
Up to 8 auto cue points (INTRO / DROP / BUILD / BREAK / OUTRO) load automatically from energy analysis.
Pads left→right: ¼ ½ 1 2 4 8 16 32 bars
| Action | Result |
|---|---|
| Pad | Activate loop at that size |
| Same pad | Exit loop |
| Shift + pads 1–4 (loop active) | Halve loop |
| Shift + pads 5–8 (loop active) | Double loop |
Loop start snaps to nearest phrase → bar → beat.
| Action | Result |
|---|---|
| Pads 1–4 | Toggle stem on/off (drums / bass / other / vocals) |
| Pads 5–8 | Hold to solo a stem (all others mute while held) |
| Pads 1–4 | Pads 5–8 |
|---|---|
| −1 bar | +1 bar |
| −2 bars | +2 bars |
| −4 bars | +4 bars |
| −8 bars | +8 bars |
Hold to apply, release to bypass:
| Pad | Effect |
|---|---|
| 1 | Filter HPF |
| 2 | Filter LPF |
| 3 | Echo (BPM-synced) |
| 4 | Roll (BPM-synced) |
| 5 | Reverb |
| 6 | Flanger |
| 7 | Phaser |
| 8 | Echo Out |
| Control | Function |
|---|---|
| Channel fader | Per-deck volume |
| Crossfader | Constant-power A→B blend |
| PFL button | Headphone cue for that deck |
| Shift + PFL | Key Sync — auto-match key to master using Camelot wheel (≤6 semitones) |
- UI ▲/▼ buttons or Shift + jog rim → ±1 semitone per press/5 ticks
- UI 0 button → reset to original key
- Key display turns amber when shifted
Press NORM on either deck panel to apply EBU R128 gain normalisation. Tracks hit a consistent level. Toggle per deck independently.
| Dot | Colour | Meaning |
|---|---|---|
| ● | Green | Fully analysed — BPM, key, beat grid, cues, stems cached |
| ● | Blue | BPM/key done, stems not yet cached |
| ● | Amber | Beat grid done, some metadata missing |
| ● | Orange | BPM only |
| ○ | Grey | Not yet analysed |
+ Add Folder — replaces the library with a new folder scan.
⟳ Analyse All — queues all tracks for full analysis and stem pre-computation.
python3 stem_example.py /path/to/your/musicStems cached to ~/udj_cache/ as WAV files. Next load is instant.
U-DJ uses htdemucs_6s (6-stem ML model) to separate:
| Stem | Content |
|---|---|
| Vocals | Voice, spoken word |
| Drums | Kick, snare, hats, cymbals |
| Bass | Sub-bass, bass line |
| Other | Remaining elements |
| Guitar / Lead | Lead synths, melodic lines |
| Piano / Pad | Chords, pads, sustained textures |
Falls back to htdemucs_ft (4-stem) if 6s is unavailable, with DSP split of "other" into lead/pad at 1500 Hz.
Post-processing tuned for Detroit techno / electronic music:
- Kick: sub-body preserved to 30 Hz, transient punch enhanced
- Bass: high-cut at 1200 Hz so 303 acid resonance passes through
- Drums: +2 dB hat air above 10 kHz, −3 dB de-mud at 300 Hz
Per-channel status in the mixer panel:
| Badge | Meaning |
|---|---|
○ NO TRACK |
Nothing loaded on this deck |
◌ STEMS LOADING… |
Separating (~90s first time, instant from cache) |
● STEMS READY |
Stem blend knobs are live |
| Path | Contents |
|---|---|
~/.udj/library.db |
Track database |
~/.udj/events.db |
Sync/quantise event log |
~/udj_cache/<hash>/ |
Stem WAV cache |
These instructions cover everything from a clean macOS machine to a running .app bundle.
| Minimum | Recommended | |
|---|---|---|
| OS | macOS 12 Monterey | macOS 13+ |
| Chip | Intel x86_64 | Apple Silicon (M1/M2/M3) — MPS makes stem separation 5–10× faster |
| Python | 3.9 | 3.9 (tested — 3.10+ untested) |
| Disk | 2 GB free | 5 GB (models + stem cache) |
| RAM | 8 GB | 16 GB |
| Controller | — | Pioneer DDJ-200 (USB) |
Check if you already have it:
python3 --versionIf not, install via python.org or Homebrew:
brew install python@3.9Make sure python3 resolves to 3.9:
python3.9 --version # should print Python 3.9.xgit clone https://github.com/PahtrikProper/U-DJ.git
cd U-DJInstall the core requirements first:
pip3 install -r requirements.txtThen install the ML stack. Apple Silicon (M1/M2/M3):
pip3 install torch==2.8.0 torchaudio==2.8.0
pip3 install demucs==4.0.1
pip3 install pyloudnormIntel Mac:
pip3 install torch torchaudio --index-url https://download.pytorch.org/whl/cpu
pip3 install demucs pyloudnormInstall PyInstaller for building the .app:
pip3 install pyinstaller==6.20.0Verify everything loaded:
python3 -c "import torch, torchaudio, demucs, sounddevice, PyQt6; print('All good')"python3 main.pyThis is the fastest way to test changes. The app runs identically to the built .app.
python3 -m PyInstaller udj.spec --clean -y
rm -rf ~/Desktop/U-DJ.app
cp -R dist/U-DJ.app ~/Desktop/U-DJ.app
open ~/Desktop/U-DJ.appThe build takes 60–90 seconds. The resulting .app is fully self-contained — no Python install needed to run it on another Mac of the same architecture.
Note: The
.appbuilt on Apple Silicon will not run on Intel Macs and vice versa. Build on the target architecture.
- macOS will ask for Microphone access (required for audio output — approve it)
- If a DDJ-200 is connected, it will be detected automatically — no driver install needed
- Click + Add Folder and point it at your music directory
- Tracks start analysing immediately in the background
- Load a track onto a deck — the first stem separation triggers a one-time ~50 MB model download (demucs htdemucs_ft). Subsequent loads are instant from cache
Always do a full clean build — incremental builds can silently include stale files:
python3 -m PyInstaller udj.spec --clean -y
rm -rf ~/Desktop/U-DJ.app
cp -R dist/U-DJ.app ~/Desktop/U-DJ.app| Path | Contents |
|---|---|
~/.udj/library.db |
Track database (BPM, key, beat grid, cues) |
~/.udj/events.db |
Sync/quantise event log |
~/udj_cache/<hash>/ |
Stem WAV cache — delete to force re-separation |
~/.cache/torch/hub/checkpoints/ |
Demucs model weights |