Slopify

https://slopify-app.vercel.app/ (Live demo on website!)

Every other music app recommends from what you've already played. Slopify recommends your actual surroundings, and gives the WORST soundtrack for your situation.

Inspiration

Recommendation engines have one input: your history. The longer you use them, the tighter the loop gets, until every playlist is a slightly worse version of the last one (Spotify DJ is notoriously bad at giving songs).

But history isn't what makes a song right. Music complements life and can elevate a scene drastically. The same track could be perfect in a car at midnight, but terrible for your 9-5.

What it does

Slopify looks at whatever you are looking at, understands the moment, and queues the "most wrong" song for it.

Examples: A funeral service gets Yakety Sax. A dentist waiting room gets Slayer. A silent library during exam week gets Sandstorm. A dance gets "50 Ways to Leave Your Lover", which is a song about leaving,

Those are real outputs the app generated!

The part we care about most is that it picks how to be wrong, because loud where it should be quiet is the boring version and it is all a mood vector can give you. So the model chooses an axis first:

  • counter_register: a solemn place gets a song with no dignity at all. This is the one that fires most.
  • counter_lyrics: the sound can even fit. The words must not. Break-up songs at weddings live here.
  • counter_genre: a string quartet in a candlelit chamber gets Cannibal Corpse.
  • counter_era: a torchlit medieval hall gets 100 gecs.
  • counter_energy: the blunt one, used when nothing sharper fits.
  • counter_rivalry: and occasionally it gets specific. Point it at a Lakers game and it queues Boston anthems, because it knows what a Lakers game is.

It runs on your phone, uses the glasses as eyes and ears, and plays through Spotify. It also runs on a laptop with a webcam, a shared screen, or a video file, because we wanted to be able to test it without wearing anything.

Two rules it will not break. It never goes silent: every model, player and voice degrades to a stand-in, and under all of them sits a hand-picked fallback deck. And it says nothing about anyone's race, religion, sex or politics. It reads places, occasions and institutions.

How we built it

Video and audio go in. A song comes out. In between:

  1. Notice. A cheap local check asks whether anything has actually changed. Most frames haven't, and those never reach a model (video processing is expensive!)
  2. Read. One Gemini call turns the frame into a description: where you are, what's happening, what kind of occasion it is, how it feels and how sure it is about all of that.
  3. Invert. The mood is five numbers. The opposite is those five numbers, mirrored. No model, no waiting.
  4. Argue. Six strategies go hunting at once, each with its own theory of what "wrong" means. Five search our hand-picked list; the sixth ignores the list and asks the model for famous songs that miss in whichever way hurts most.
  5. Judge. A second model call picks the winner and writes the one line explaining it.
  6. Decide. Then it decides whether to act at all — slip the song in behind what's playing, or cut the music off. Interrupting has to be earned.
  7. Play. Spotify finds the actual recording and plays it.

The stack. Python, LangGraph, FastAPI, Gemini, Spotify Web API. Next.js

Challenges we ran into

Every Gemini call was silently failing. The timeout was 4 seconds, the model took 5 to 8, so every call fell back to a canned response that looked perfectly plausible — benchmarking four models got us to 1.17s median.

One Christmas song won the monastery, the dentist and the football stadium. Any scene matching none of the nine rules fell through to a single fallback tag that exactly two tracks carry

Spotify locked us out for 23 hours. We were resolving all eight candidates before the judge picked one; resolving only the winner took it from fourteen searches per moment to one.

Spotify has closed most of its music API to new apps. Recommendations 404, audio features and related artists 403, popularity gone — which forced the architecture we now prefer: the model thinks, Spotify resolves and plays.

Accomplishments that we're proud of

It knows when it doesn't know. Pointed at a covered lens it reported "obstructed or blocked camera view" at 0.10 confidence and did nothing.

The timing is measured, not felt. The model disagrees with itself by at most 0.173 on an unchanged frame and the smallest real scene change moves the target 0.563, so every threshold sits in the gap between those two numbers.

Six strategies that genuinely disagree. A test fails if a new strategy keeps proposing what an existing one already found, and the losing candidates stay on screen with their scores, because the argument is more interesting than the verdict.

What we learned

Ship it into a terminal before you believe any of it. The timeout, the Premium check, the Christmas song and the rate limit were all sitting in a repo that passed its tests.

A field you never requested reads exactly like a field that says no. If you gate on something an API returns, check you asked for the scope that fills it — and treat missing as unknown, not as no.

Fame beats accuracy, and we couldn't measure fame. Spotify stopped exposing popularity, so we ask the model for famous songs instead; asking turned out to work better than measuring would have.

What's next for Slopify

Memory across sessions, so it stops reaching for the same joke twice in one evening.

Track duration, so it knows when a song ends instead of inferring it.

A real corpus. The hand-picked 47 are the safety net; the live catalogue is where the good jokes are.

None of us have Ray Bans so maybe you guys can give us the #1 prize??? <3

Built With

Share this project:

Updates