Inspiration
Shuffle and auto-crossfade treat songs like interchangeable blocks: the last few seconds of one track get faded into the first few seconds of the next, wherever those happen to land. With dance remixes that sometimes works. With pop, Bollywood or rap it usually doesn't: a vocal gets cut off mid-line and crashes straight into the next singer. A real DJ does three things automatic crossfades don't: picks an order that flows, chooses where to leave one song and enter the next, and makes the blend sound intentional. We wanted to build that for anyone's playlist, keeping every song intact instead of skipping to the drops.
## What it does Upload 2–5 MP3 or WAV files and Mixr:
- Listens to each song: tempo and beat grid, musical key (in Camelot notation), loudness over time, how much lead melody or vocal is present, 8-bar phrase boundaries, and song sections (intro, break, chorus/drop, outro where the shape is clear).
- Scores every possible transition between every pair of songs, and finds the running order with the smoothest overall flow.
- Explains its choices: a "Why this order" card says why songs were reordered and what makes each transition work ("neighboring keys (8A → 9A); matching tempo (128 vs 126 BPM)").
- Lets you tune the blends with quick A/B listening tests: the same transition with a short and a long overlap. Your picks set how long the blends are.
- Picks cue points: where each song is left and where the next one comes in, so the melody hands over cleanly instead of two vocals overlapping.
- Renders the mix: long phrase-length blends that land on the downbeat, tempo glides between songs at different speeds, loudness matching, drop transitions (a filter sweep and beat roll into the next song's drop) when the next song has a real drop, and an echo-out when two melodies would otherwise clash.
There are two modes: Full songs (every song plays nearly in full) and DJ set (each song's best part, sized to a target length like a 5-minute set).
## How we built it Stack: Python + FastAPI backend, Next.js + Tailwind frontend, librosa and NumPy for analysis, the Rubber Band library for time-stretching, and pytest for testing (230+ tests on Python 3.11 and 3.12).
We split the work into three modules with a written integration contract between them, so all three of us could build in parallel:
- Audio analysis and rendering: beat tracking with a refined BPM (averaging the regular beat gaps beats librosa's frame-quantized tempo) and half/double-time folding; key detection by matching chroma against Krumhansl–Schmuckler key profiles; melody activity from the harmonic part of a harmonic/percussive split in the 300–3400 Hz band. A single transition renderer powers both the A/B previews and the final mix, so a preview is exactly what you'll hear.
Scoring, ordering, calibration and explanations: each directed pair A → B gets a weighted score from four sub-scores between 0 and 1: harmonic compatibility H, tempo match T, energy match E, and mood M.
Score(A → B) = 0.40·H + 0.35·T + 0.15·E + 0.10·M
Any sub-score that can't be measured (e.g. an unreliable key) counts as a neutral 0.5, so missing data is never a bonus or a penalty. Harmonic compatibility uses distance on the Camelot wheel; tempo compares BPMs, treating half/double time (64 ↔ 128 BPM) as a match. With at most 5 songs there are only 5! = 120 possible orders, so we search them all and keep the best, falling back to a greedy search for longer playlists. Calibration maps your A/B votes to a preference p between −1 and 1, and an overlap of 16 + 8p seconds.
Cue points: every candidate (A exit, B entry) pair on phrase boundaries is scored on melody handoff (55%), energy match (25%) and song structure (20%), and a dynamic program picks all the windows across the running order at once.
API and UI: upload, analyze, order, tune and mix steps, a timeline with each song's waveform, and a tracklist showing which part of each song played and why.
## Challenges we ran into
- Two melodies at once. Our test pair, "Sheila Ki Jawani" → "Tell Her You Know", has vocals right up to the last 2 seconds of one song and from the first second of the next. A crossfade there sounds like a crash. We attacked it from two sides: cue points that leave a song as a vocal line ends and enter the next where it's instrumental, and an echo-out fallback (the outgoing song's last beat echoes out while the next drops in on the bar line) when no clean handoff exists.
- Imprecise tempo detection. librosa reported 129.2 and 123.0 BPM for tracks that were really 128 and 126, which would have wrecked tempo matching. Averaging regular beat gaps fixed the precision.
- Getting two systems to agree. The cue picker and the renderer each had their own idea of where a fade-out starts and when a seam would echo out, and their fade estimates differed by 35–40%. We traced it down and made the cue picker ask the renderer's own functions instead of re-deriving the answer.
- Three people, one codebase, 24 hours. Parallel work on shared files led to merge conflicts and at one point two versions of the same feature. The integration contract, small PRs, and running the full test suite before every merge kept it from falling apart.
## Accomplishments that we're proud of
- On real songs, the Sheila → Tell Her transition now hands the melody over cleanly in full mode, and DJ set mode hits 5-minute targets close to the target length
- Every number Mixr shows is something it actually measured. Explanations never claim a key match or a Claude rating that didn't happen.
- A single renderer for previews and the final mix, so what you approve in the A/B test is what ends up in the mix.
## What we learned Music theory (the Camelot wheel, phrasing in 8-bar blocks), practical audio signal processing (beat tracking, chroma, harmonic/percussive separation, time-stretching), and how much a written interface contract matters when three people build the same pipeline at once. We also learned to design for missing data from the start: real audio doesn't always give you a confident key or a clean beat.
## What's next for Mixr
- Claude-powered mood scoring: the scoring already accepts a mood score per transition; next is a single batched Claude call per upload that rates how well songs fit together by vibe.
- A before/after comparison so you can hear a plain crossfade next to Mixr's transition.
- Tuning by ear on a larger set of real songs, and finer chorus/drop detection for DJ set mode.
- Longer-term: offering Mixr as an API that music apps and streaming services can use for DJ-style transitions.
Log in or sign up for Devpost to join the conversation.