STREAMING 24/7

FNDJ

A DJ that never sleeps.

FNDJ beatmatches the entire Jo Luno catalogue into one endless, seamless set — detected, time-stretched, and crossfaded entirely by code, then streamed live around the clock.

The playlist

One giant arc. No cliffs.

Every track's BPM is detected up front, then the whole library is laid out as an arch: start at the median tempo, climb to 200 BPM, dive to 60, and glide back home. Each transition is a neighbour — never more than ~6 BPM apart — and the final track lands 2.5 BPM from the first, so the set loops forever without a seam. This is the real curve, drawn from the live playlist:

200 BPM 150 100 125 · start 200 · peak 60 · floor 122 · loops back ↺
913tracks in the library
1,825entries per cycle — most tracks play twice
~109 hone full cycle, then it loops
6.45largest BPM step anywhere
2.55BPM across the loop seam
On screen

What's playing, always.

A Pillow renderer pulls each track's ID3 tags and embedded album art, wraps long titles, and streams the strip to FFmpeg as raw RGBA frames — the overlay flips to the next track mid-crossfade, right as the new song takes over.

Rendered live by overlay_renderer.py at 2 fps, composited by FFmpeg.

Architecture

Four processes and a named pipe.

No DAW, no DJ software, no browser sources — just Python feeding FFmpeg through a FIFO, with every stage supervised and able to reconnect if its neighbour restarts.

~/Music/Jo Luno
913 MP3s
ID3 tags + album art
playlist_manager.py
detects BPM · time-stretches · equal-power crossfades (16 beats)
audio FIFO
raw PCM
44.1 kHz stereo
ffmpeg
x264 1080p30 + AAC
tee muxer, auto-reconnect
YouTube + Twitch
simulcast RTMP
either can drop, the other stays live
overlay_renderer.py → RGBA frames @ 2 fps, composited into the video by ffmpeg
Under the hood

Built to run unattended.

Beatmatched crossfades

BPM is detected via onset autocorrelation, the incoming track is time-stretched with scipy, and the two are blended with an equal-power curve — 4 bars, like a real DJ.

Arch-shaped playlist

The library is pre-analysed once, then ordered as a rise-and-fall arch so tempo drifts, never jumps — including where the cycle wraps around.

A living overlay

Album art, wrapped titles and the Jo Luno crescent, re-rendered the instant the track flips. Falls back to plain drawtext, then to no overlay, if anything's missing.

Self-healing pipeline

If the network drops, FFmpeg restarts and the playlist blocks on the pipe until it's back. If the playlist dies, the pipe disappears and the stream stops cleanly instead of hanging.

One encode, two platforms

A single x264 encode is tee'd to YouTube and Twitch with onfail=ignore — one destination failing never takes down the other.

Zero-touch operations

A macOS LaunchAgent starts the stream at login and revives it after crashes. Every component logs to its own timestamped file.