Conversation
…time behavior - refactor AI Radio plugin structure and web UI flows (wizard, sections, run controls) - improve config clarity/help text and standalone MA-styled web UI experience - add detailed runtime phases/logging and human-readable session status rendering - improve dynamic batching with earlier prefetch trigger (`dynamic_prefetch_remaining_tracks`) - add advanced plugin setting for UI auto-refresh interval (`ui_auto_refresh_seconds`) - fix typing issues and expand provider tests
Remove AI-Radio subproject
…e prompts, and improve styles; add air.png to mp3 metadata.
…tyling for better layout and usability. Adjust grid alignment, input heights, and import label styles for improved user experience.
…o-generate IDs from names, and enhance UI layout for better usability.
…ndling, session cancellation, and normalization logic
…ove error handling
🔒 Dependency Security Report✅ No dependency changes detected in this PR. |
There was a problem hiding this comment.
Pull request overview
Adds a new AI Radio plugin provider to Music Assistant that can generate radio-style moderator sections (LLM + TTS) and insert them into a playlist (playlist mode) or generate them on-the-fly while queueing (dynamic mode).
Changes:
- Introduces a new
ai_radioplugin provider with storage/normalization and runtime execution logic (LLM generation, TTS synthesis, optional weather enrichment). - Registers new admin-only API commands for station/section CRUD and run control (start/stop/status).
- Adds unit tests for storage normalization, runtime session state handling, and provider validation helpers.
Reviewed changes
Copilot reviewed 15 out of 17 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| music_assistant/providers/ai_radio/provider.py | Plugin provider entrypoint, API route registration, run lifecycle management. |
| music_assistant/providers/ai_radio/runtime.py | Core runtime for playlist/dynamic modes, planning/generation/TTS, weather token prep. |
| music_assistant/providers/ai_radio/storage.py | Persistent storage + normalization for stations/sections and defaults. |
| music_assistant/providers/ai_radio/models.py | Dataclasses/utilities for session state, slot planning, text limiting, etc. |
| music_assistant/providers/ai_radio/constants.py | Plugin constants and defaults. |
| music_assistant/providers/ai_radio/config.py | Provider config entries (API keys, UI refresh interval, UI link label). |
| music_assistant/providers/ai_radio/manifest.json | Declares the plugin manifest. |
| music_assistant/providers/ai_radio/example_station.json | Example station definition for reference/testing. |
| tests/providers/ai_radio/* | Unit tests covering storage/runtime/provider helper behavior. |
| scripts/update_and_redeploy_container.sh | Local dev helper script for building and redeploying a container. |
| DEVELOPMENT.md | Adds instructions for building a local Python artifact for Docker builds. |
| track_entry_local_indices = [ | ||
| index for index, uri in enumerate(entries) if "://track/" in uri |
| parsed = {item["id"]: item for item in defaults} | ||
| await self._write_sections() |
| raw_constraints = section.get("constraints") | ||
| max_chars = 0 | ||
| if isinstance(raw_constraints, dict): | ||
| max_chars = int(raw_constraints.get("max_chars", 0) or 0) |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds a new AI Radio plugin provider that can generate LLM-driven “radio host” sections (with optional weather/news) and synthesize them to TTS MP3s, supporting both prebuilt playlist mode and dynamic queue mode.
Changes:
- Introduces the
ai_radioplugin provider (storage, runtime execution, config entries, manifest, example station). - Adds unit tests covering storage normalization, runtime session state/logging, and provider helper validation.
- Adds a local Docker redeploy helper script and a short DEVELOPMENT.md note about building Python artifacts.
Reviewed changes
Copilot reviewed 15 out of 17 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| music_assistant/providers/ai_radio/provider.py | Plugin provider wiring: API commands, station/section CRUD, session lifecycle. |
| music_assistant/providers/ai_radio/runtime.py | Core runtime: planning sections, LLM calls, weather tokens, TTS synthesis, queue/playlist publishing. |
| music_assistant/providers/ai_radio/storage.py | Disk persistence + normalization/validation for stations/sections/general settings. |
| music_assistant/providers/ai_radio/models.py | Dataclasses/utilities used across runtime/provider (slots, session state, helpers). |
| music_assistant/providers/ai_radio/config.py | Provider config entries (API keys, UI refresh, UI URL label). |
| music_assistant/providers/ai_radio/constants.py | Plugin constants/defaults (models, providers, limits, tokens). |
| music_assistant/providers/ai_radio/manifest.json | Declares the plugin provider and its metadata. |
| music_assistant/providers/ai_radio/example_station.json | Example station payload for reference/testing. |
| music_assistant/providers/ai_radio/init.py | Exposes setup + config entries for provider loading. |
| tests/providers/ai_radio/test_storage.py | Unit tests for storage normalization/materialization behavior. |
| tests/providers/ai_radio/test_runtime.py | Unit tests for session execution state changes and weather-token prep warnings. |
| tests/providers/ai_radio/test_provider.py | Unit tests for provider validation logic (dynamic-mode requirements, UI settings). |
| tests/providers/ai_radio/init.py | Test package marker. |
| scripts/update_and_redeploy_container.sh | Local helper to build artifacts and redeploy a Docker container. |
| DEVELOPMENT.md | Adds short instructions for building dist/ artifacts for Docker builds. |
| parsed = {item["id"]: item for item in defaults} | ||
| await self._write_sections() |
| raw_constraints = section.get("constraints") | ||
| max_chars = 0 | ||
| if isinstance(raw_constraints, dict): | ||
| max_chars = int(raw_constraints.get("max_chars", 0) or 0) |
| "instructions": str(source_general.get("instructions", defaults["instructions"])), | ||
| "openai_base_url": _text("openai_base_url"), | ||
| "section_store_path": _text("section_store_path"), | ||
| "weather_provider": _text("weather_provider"), | ||
| "weather_timeout_seconds": _number("weather_timeout_seconds", int), | ||
| "tts_provider": _text("tts_provider"), | ||
| "openai_tts_model": _text("openai_tts_model"), | ||
| "openai_tts_voice": _text("openai_tts_voice"), | ||
| "openai_tts_instructions": str( | ||
| source_general.get( | ||
| "openai_tts_instructions", | ||
| defaults["openai_tts_instructions"], | ||
| ) | ||
| ), | ||
| "elevenlabs_model": _text("elevenlabs_model"), | ||
| "elevenlabs_voice_id": str( | ||
| source_general.get("elevenlabs_voice_id", defaults["elevenlabs_voice_id"]) | ||
| ).strip(), | ||
| } |
| "authorization": f"Bearer {api_key}", | ||
| "content-type": "application/json", | ||
| "accept": accept, | ||
| }, |
| CONTAINER_NAME="${CONTAINER_NAME:-music-assistant-local}" | ||
| IMAGE_NAME="${IMAGE_NAME:-ma-server-local}" | ||
| MASS_VERSION="${MASS_VERSION:-0.0.0}" | ||
| NETWORK_MODE="${NETWORK_MODE:-host}" | ||
|
|
||
| DATA_DIR="${DATA_DIR:-/path/to/mass_data}" | ||
| MUSIC_DIR="${MUSIC_DIR:-/path/to/music}" | ||
| TIMEZONE_FILE="${TIMEZONE_FILE:-/path/to/timezone/file}" | ||
|
|
||
| TOTAL_STEPS=5 | ||
| if [[ -n "$FRONTEND_PATH_ARG" ]]; then | ||
| TOTAL_STEPS=6 | ||
| fi |
As discussed in Discord here is the pull request for my AI Radio plugin.
The plugin allows a user to define a 'station' and specify a MA playlist and the tool will generate the text and respective TTS mp3 files and insert them into a new playlist (or to a current queue) making it more like a radio like experience with weather reports, song intro and outros, news etc.
Features
Notes
scripts/update_and_redeploy_container.shto help me update my local deployment, but if you want I can remove thatDEVELOPMENT.mdas close as possible. Though this is the first time contributing to this project so there are certainly things I missed so have mercy 😅Screenshots
Backend (API)
Frontend