Go to file
ComputerTech cddce99b29 Fix: isolate DJ audio from system audio in streaming/recording
The Qt app was using PulseAudio's 'default.monitor' which captures ALL
system audio (YouTube Music, Spotify, browser, etc.). This caused listeners
to hear whatever was playing on the DJ's system, not just the DJ mix.

Added PulseAudioIsolator class that:
- Creates a virtual PulseAudio null sink ('techdj_stream')
- Routes only this app's audio to the virtual sink
- Creates a loopback so the DJ still hears their mix through speakers
- Captures from the virtual sink's monitor (only DJ audio)
- Reference-counted: shared between streaming and recording workers
- Automatically cleans up stale sinks from previous crashes
- Periodically re-routes audio to catch new tracks/streams
- Falls back to default.monitor if pactl is unavailable

Both StreamingWorker and RecordingWorker now use the isolator.
2026-03-09 19:45:43 +00:00
.gitignore Final bug sweep: fix event param, remove dead code, dedupe CSS; add .gitignore recordings/ 2026-03-05 14:28:17 +00:00
MOBILE_IMPROVEMENTS.md feat: add integrated deck queues and track loop functionality 2026-02-07 20:14:04 +00:00
README.md Mobile UX improvements: Remove emojis, convert to British English, fix queue navigation and floating buttons 2026-02-02 02:37:56 +00:00
compare_memory.py Final bug sweep: fix event param, remove dead code, dedupe CSS; add .gitignore recordings/ 2026-03-05 14:28:17 +00:00
config.example.json Add config.json system; fix bugs across server.py, script.js, techdj_qt.py 2026-03-09 18:02:47 +00:00
dj_icon.png Final bug sweep: fix event param, remove dead code, dedupe CSS; add .gitignore recordings/ 2026-03-05 14:28:17 +00:00
edge_glow_test.html Upload files to "/" 2026-01-02 19:37:56 +00:00
icon.png Fix desktop launcher hanging by skipping dependency install in non-interactive mode 2026-01-20 17:20:33 +00:00
index.html Fix 6 bugs: remove dead listener code from DJ panel, fix StreamingWorker socket reuse, fix GUI-blocking time.sleep, fix abort import 2026-03-09 19:16:42 +00:00
launch_qt.sh Final bug sweep: fix event param, remove dead code, dedupe CSS; add .gitignore recordings/ 2026-03-05 14:28:17 +00:00
listener.css Separate listener page from DJ panel 2026-03-09 18:50:04 +00:00
listener.html Separate listener page from DJ panel 2026-03-09 18:50:04 +00:00
listener.js Separate listener page from DJ panel 2026-03-09 18:50:04 +00:00
requirements.txt Final bug sweep: fix event param, remove dead code, dedupe CSS; add .gitignore recordings/ 2026-03-05 14:28:17 +00:00
script.js Fix 6 bugs: remove dead listener code from DJ panel, fix StreamingWorker socket reuse, fix GUI-blocking time.sleep, fix abort import 2026-03-09 19:16:42 +00:00
server.py Fix 6 bugs: remove dead listener code from DJ panel, fix StreamingWorker socket reuse, fix GUI-blocking time.sleep, fix abort import 2026-03-09 19:16:42 +00:00
settings.json Final bug sweep: fix event param, remove dead code, dedupe CSS; add .gitignore recordings/ 2026-03-05 14:28:17 +00:00
style.css Fix actual root causes: waveform black block, body gradient bleed, JS glow override 2026-03-05 18:02:08 +00:00
techdj_qt.py Fix: isolate DJ audio from system audio in streaming/recording 2026-03-09 19:45:43 +00:00
techdj_qt_v1.py.bak Final bug sweep: fix event param, remove dead code, dedupe CSS; add .gitignore recordings/ 2026-03-05 14:28:17 +00:00

README.md

TechDJ Pro

TechDJ Pro is a local DJ web app with a dual-port architecture:

  • DJ Panel (mix/load tracks + start broadcast): http://localhost:5000
  • Listener Page (receive the live stream): http://localhost:5001

It supports:

  • Local library playback (files in music/)
  • Downloading audio from URLs (via yt-dlp when available, with fallback)
  • Live streaming from the DJ browser to listeners using Socket.IO
  • Live listening via an MP3 stream (/stream.mp3) generated server-side with ffmpeg.
  • Real-time visual spectrum analyzer for listeners
  • Optional password protection for the DJ panel
  • Compatibility with reverse proxies like Cloudflare
  • Remote stream relay: Relay live streams from other DJ servers to your listeners

Requirements

System packages

  • Python: 3.10+ recommended
  • ffmpeg: strongly recommended (required for reliable downloads/transcoding and MP3 fallback)

Linux (Debian/Ubuntu):

sudo apt update
sudo apt install -y ffmpeg

macOS (Homebrew):

brew install ffmpeg

Windows:

Python dependencies

All Python dependencies are listed in requirements.txt:

  • flask
  • flask-socketio
  • eventlet
  • yt-dlp
  • python-dotenv
  • requests

Install (from scratch)

git clone https://git.computertech.dev/computertech/techdj.git
cd techdj

# Create venv
python3 -m venv .venv

# Activate venv
source .venv/bin/activate

# Ensure pip exists (some environments require this)
python -m ensurepip --upgrade || true

# Upgrade tooling (recommended)
python -m pip install --upgrade pip setuptools wheel

# Install deps
pip install -r requirements.txt

Optional configuration (.env)

Create a .env file in the project root if you want YouTube search results to work in the UI:

YOUTUBE_API_KEY=YOUR_KEY_HERE

Notes:

  • If you dont set YOUTUBE_API_KEY, you can still paste a YouTube URL directly into a deck/download box.

Optional DJ panel password (config.json)

By default, anyone who can reach the DJ server (:5000) can open the DJ panel.

If you want to lock it while youre playing live, create a config.json (not committed) in the project root:

{
  "dj_panel_password": "your-strong-password"
}

Behavior:

  • If dj_panel_password is empty/missing, the DJ panel is unlocked (default).
  • If set, visiting http://<DJ_MACHINE_IP>:5000 shows a login prompt.
  • Listener (:5001) is not affected.

Run

Start the server:

source .venv/bin/activate
python server.py

You should see output like:

  • DJ panel: http://localhost:5000
  • Listener page: http://localhost:5001

Using the app

DJ workflow

  1. Open the DJ Panel: http://localhost:5000
  2. Click INITIALISE SYSTEM
  3. Load/play music
    • Upload MP3s (folder/upload button)
    • Or download from URLs (paste into deck input / download controls)
  4. Open the streaming panel and click START BROADCAST

Remote Stream Relay

TechDJ can relay live streams from other DJ servers:

  1. Open the DJ Panel: http://localhost:5000
  2. Click the streaming panel (LIVE STREAM)
  3. In the "Remote Stream Relay" section, paste a remote stream URL (e.g., http://remote.dj/stream.mp3)
  4. Click START RELAY
  5. Your listeners will receive the relayed stream
  6. Click STOP RELAY to end the relay

Listener workflow

  1. Open the Listener Page:

    • Same machine: http://localhost:5001

    • Another device on your LAN/WiFi:

      http://<DJ_MACHINE_IP>:5001

  2. Click ENABLE AUDIO if prompted

    • Browsers block autoplay by default; user interaction is required.3. Enjoy the live stream with real-time spectrum visualization

Multi-device / LAN setup

Find your DJ machine IP

Linux:

ip addr

Windows:

ipconfig

macOS:

ifconfig

Use the LAN IP (commonly 192.168.x.x or 10.x.x.x).

Firewall

Make sure the DJ machine allows inbound connections on:

  • TCP 5000 (DJ Panel)
  • TCP 5001 (Listener)

If listeners cant connect, this is often the cause.


Streaming

TechDJ serves the listener audio as an MP3 HTTP stream:

  • MP3 stream endpoint: http://<DJ_MACHINE_IP>:5001/stream.mp3

This requires ffmpeg installed on the DJ/server machine.

Debug endpoint

  • Stream debug JSON:

    http://<DJ_MACHINE_IP>:5001/stream_debug

This shows whether ffmpeg is running and whether MP3 bytes are being produced.


Deployment behind reverse proxies (e.g., Cloudflare)

TechDJ is compatible with reverse proxies like Cloudflare. To ensure proper functionality:

  • Use same-origin URLs for streaming to avoid port restrictions.
  • Configure your proxy to bypass caching for the /stream.mp3 endpoint, as it's a live audio stream.
  • Set cache control headers to no-cache for /stream.mp3 to prevent buffering issues.
  • Ensure WebSocket connections (used by Socket.IO) are allowed through the proxy.

Example Cloudflare page rule:

  • URL: yourdomain.com/stream.mp3
  • Cache Level: Bypass
  • Edge Cache TTL: 0 seconds

Troubleshooting

Listener says “Browser blocked audio”

  • Click ENABLE AUDIO
  • Try a normal click (not keyboard-only)
  • Disable strict autoplay blocking for the site, if your browser supports it

Listener says “NotSupportedError”

  • Your browser likely doesnt support the default WebM/Opus MediaSource path

  • Ensure ffmpeg is installed on the server

  • Try opening the MP3 fallback directly:

    http://<DJ_MACHINE_IP>:5001/stream.mp3

DJ says broadcast is live but listeners hear nothing

  • Confirm:
    • A deck is actually playing
    • Crossfader isnt fully on the silent side
    • Volumes arent at 0
  • Check http://<DJ_MACHINE_IP>:5001/stream_debug and see if transcoder_bytes_out increases

Spectrum visualiser not showing

  • Ensure the listener page is loaded and audio is enabled.
  • Check browser console for errors related to Web Audio API.

Remote relay not working

  • Ensure the remote stream URL is accessible and returns valid audio
  • Check that ffmpeg is installed and can handle the remote stream format
  • Verify the remote stream is MP3 or a format supported by ffmpeg
  • Check server logs for ffmpeg errors when starting the relay

pip missing inside venv

Some Python installs create venvs without pip. Fix:

python -m ensurepip --upgrade
python -m pip install --upgrade pip

Dev notes

  • Main server: server.py
  • Client UI logic: script.js
  • Downloader: downloader.py
  • Static assets: index.html, style.css

License

No license specified.