Skip to content

Repository files navigation

AI Radio for Music Assistant

AI Radio

AI Radio is a tool that uses AI to convert your Music Assistant playlists to a radio station.

This project takes a source playlist, injects AI-generated moderator sections (intros, transitions, weather, news, fun bits), converts them to speech, and publishes a fresh target playlist in Music Assistant. Alternatively, it can run in dynamic generation mode, where sections are generated on the fly and queued for immediate playback without creating a target playlist.

Features

  • 5-step pipeline with clear boundaries and debug output
  • Music Assistant integration via music-assistant-client SDK
  • Rule-based section scheduling (MUST, ALTERNATIVE, OPTIONAL + guards)
  • Dynamic generation mode with live queue updates (--dynamic-generation)
  • Optional weather context (Open-Meteo)
  • Optional news context with OpenAI web search
  • OpenAI or ElevenLabs TTS generation for all sections
  • Optional cover image generation per section (OpenAI Images)
  • Optional HTTP daemon to trigger runs via API (dynamic_daemon.py)

How It Works

  1. step1_connect.py Connect to Music Assistant and verify access.

  2. step2_gather_playlist.py Load source playlist + tracks (optional random subset by max_duration).

  3. step3_generate_sections.py Evaluate section_order, resolve placeholders, fetch optional context, generate section text.

  4. step4_tts_sections.py Convert text to MP3, set metadata, embed covers.

  5. step5_update_playlist.py Sync section provider, create target playlist, add tracks + generated sections.

main.py orchestrates all steps.

Architecture

flowchart LR
  A[Config YAML + .env] --> B[Step 1 Connect]
  B --> C[Step 2 Gather Playlist]
  C --> D[Step 3 Plan and Generate Sections]
  D --> E[Step 4 TTS + ID3 + Covers]
  E --> F[Step 5 Sync + Publish Playlist]
Loading

Project Structure

  • main.py: pipeline orchestrator
  • step1_connect.py ... step5_update_playlist.py: pipeline steps
  • step_generate_covers.py: one-shot section cover generation
  • dynamic_daemon.py: HTTP daemon to start/stop dynamic generation runs
  • lib/: shared modules (ma_client, providers, helpers)
  • config/sample_config.yaml: fully documented reference config
  • .tmp/: runtime artifacts (ignored by git)

Requirements

  • Python 3.12+
  • A Music Assistant instance with API access
  • OpenAI API key for LLM (and optional images/news search)
  • TTS API key for selected provider (OPENAI_API_KEY or ELEVENLABS_API_KEY)
  • A way to share generated MP3 files with Music Assistant (e.g. local filesystem, SMB/NFS share, etc.)

Setup

  1. Create and activate virtual environment
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
  1. Create .env in repository root
OPENAI_API_KEY=...
OPENAI_ADMIN_KEY=...            # optional (cost endpoint)
ELEVENLABS_API_KEY=...          # optional (only if TTS provider is ElevenLabs)
MUSIC_ASSISTANT_API_KEY=...
  1. Create local config
cp config/sample_config.yaml config/local_config.yaml
  1. Edit config/local_config.yaml
  • set Music Assistant base_url
  • set source playlist_id
  • set local section_store_path
  • set provider ids/domains for your MA setup
  1. Ensure Music Assistant can read generated section files
  • MA must have filesystem access to general.section_store_path (or the same share/path exposed by your MA filesystem provider).
  • Recommended: run this pipeline on the same host as MA, or use a shared SMB/NFS path mounted on both systems.
  • Why: step 5 triggers MA sync, then searches MA library for indexed section tracks and adds them by URI (not by your local host file path).

Usage

Run full pipeline:

python3 main.py -c config/local_config.yaml

Run from a specific step:

python3 main.py -c config/local_config.yaml --from-step 3

Generate covers only:

python3 main.py -c config/local_config.yaml --generate-covers-only

Step 5 billing check only:

python3 step5_update_playlist.py -c config/local_config.yaml --only-oai-check

Dynamic generation mode (no target playlist creation, queue playback directly):

python3 main.py -c config/non_techno_playlist.yml --dynamic-generation 1 --playback-device ap8aedae8231f2

Dynamic daemon (HTTP start/stop for dynamic mode):

python3 dynamic_daemon.py --port 8787 --auth-token YOUR_TOKEN

Start dynamic generation:

curl -H "Authorization: Bearer YOUR_TOKEN" \
  "http://127.0.0.1:8787/start-dynamic?playback-id=ap8aedae8231f2&generate_count=1&config=config/non_techno_playlist.yml"

Stop current dynamic run:

curl -H "Authorization: Bearer YOUR_TOKEN" \
  "http://127.0.0.1:8787/stop-dynamic"

Configuration Guide

All options are documented in config/sample_config.yaml.

Important groups:

  • general: naming, timezone, host style prompt, output paths
  • providers: credentials + provider-specific behavior
  • sections: generated content blocks (ai_text) and optional merger (ai_meta)
  • section_order: placement rules and guard constraints

Covers and Metadata

Per section, you can define:

  • name: human-readable metadata title base
  • cover_image: image filename located in general.covers_path

For the target playlist, you can define:

  • general.playlist_cover_image: playlist cover image (filename, absolute path, or URL)

For merged multi-section outputs (multi_*), the system falls back to the ai_meta section cover/name when available.

Output Naming

Target playlist:

  • AI Radio: <general.name> (<weekday>. <dd.mm.>) [<run_id>]

Generated section track metadata:

  • title: <sections[*].name> [<run_id>]
  • artist: AI Radio

Notes

  • .env is loaded automatically from repository root.
  • Runtime artifacts are written to .tmp/.
  • If a section cover is missing, MP3 generation still succeeds.

Disclaimer

  • This project is an independent community project and is not affiliated with, endorsed by, or officially connected to the Music Assistant project or the Open Home Foundation.
  • "Music Assistant", "Open Home Foundation", and related names, logos, and marks are the property of their respective owners.
  • Any reference to third-party names/logos in documentation or examples is for identification, compatibility, or commentary purposes only (nominative fair use/fair usage context).

About

AI Radio is a tool that uses AI to convert your Music Assistant playlists to a radio station.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages