Back to projects

KuraiMusik

An internet radio that never switches off. AI generates the music, and the system mixes and streams it on its own, around the clock, across several stations with nobody in the booth.

  • 2026
  • Next.js
  • FastAPI
  • Celery
  • Redis
  • Liquidsoap
  • Icecast
  • ACE-Step
  • Docker
  • Prometheus

Try it live

What you see

Step in, pick a station from Dubstep, Hacker Music and Jazz, and listen to a continuous stream, just like a real radio. There's no playlist to build: tracks are generated with AI, blend into each other with a crossfade, and the player shows you what's on.

The KuraiMusik landing page, with the Enter Experience button on a dark background.
1. Step in
The KuraiMusik mood selector, with Dubstep, Hacker Music and Jazz, above the playback and volume controls.
2. Pick a mood and press play
The KuraiMusik player streaming an AI-generated jazz track.
3. Listen

Architecture

A radio can't pause while a model finishes generating. So I separated what takes time from what always has to be playing: music is generated in the background, and the broadcast only picks up what's already ready.

  1. Web clientNext.js

    Lives in its own repository. It picks the station, plays the stream and gets the current track and system status in real time.

  2. OrchestratorFastAPI

    Exposes the stations, the current track and system health, and announces changes over WebSocket and Socket.IO.

  3. Background generationCelery and Redis

    Watches each station's buffer and queues new tracks when they're needed, without touching the broadcast.

  4. Mixing and broadcastLiquidsoap and Icecast

    Liquidsoap blends tracks with a crossfade and normalizes the volume, and Icecast delivers the audio to whoever is listening.

  • ACE-StepGenerates the music, as a separate microservice
  • RedisWork queues
  • LiquidsoapMixing and gain control
  • IcecastStreaming to listeners
  • PrometheusMetrics and system health
  • A playlist that evolves

    Each station keeps a dynamic buffer. New tracks are generated continuously and the oldest ones leave to make room, so over time the programming changes completely instead of looping the same songs.

  • Failures never reach your ears

    A circuit breaker protects the system when the generation API fails, and the radio keeps playing what's already in the buffer. Its state also reaches the client, which can say so with a friendly "we're tuning the signal".

  • Making it sound like a radio

    Crossfades and automatic gain control prevent cuts and volume jumps between tracks that were generated separately. Each MP3 also carries its ID3 metadata.

  • Stations as configuration

    Each station is declared in a YAML file, with its mount point, its name and its prompts. Adding one doesn't require touching the orchestrator's code.

  • A client that knows right away

    Track changes, buffer updates and the circuit breaker's state are sent as events, so the interface doesn't have to keep asking.

The challenge

Keeping a radio station of AI-generated music going all day with no operator, so that a single failure never reaches the ears of whoever is listening. Generating a track takes time, and a live stream can't wait.

What's behind it

  • The backend and streaming engine live in one repository, the Next.js client in another, and ACE-Step runs as an independent service.
  • The whole backend starts with Docker Compose, including Icecast and Liquidsoap.
  • The system exposes health probes, Prometheus metrics and structured logs.
  • Rate limiting protects the API from abuse.
  • Tests cover unit, integration, smoke, API contracts, resilience and load with Locust.

Decisions and trade-offs

  • Generate before streaming. Generating ahead uses more resources, but listeners never depend on the model's inference time.
  • Degrade instead of going down. If one piece fails, the system isolates it and the radio keeps playing.
  • Keep the generator apart from the radio. There are more services to coordinate, but the model can fail, restart or change without stopping the broadcast.
  • Use Icecast and Liquidsoap instead of custom streaming. I depend on how they're configured, and in return I lean on radio tools that are already proven.