Abstract
Персоны
Две персоны с разным характером:
| Персона | Стиль | Частота | Длина скрипта | Голос |
|---|---|---|---|---|
| ИИбан | Размеренный эфир, советский диктор | moderate | storyteller | ru_RU-ruslan-medium |
| TOVARISH | Глубокий голос, лаконично и веско | aggressive | extended | ru_RU-ruslan-medium |
Активная персона — ИИбан (p_default0). DJ-режим включён — ИИбан сам выбирает треки и комментирует.
Промпты на английском
Кириллица в промптах — 2–5x больше токенов на слово. Поэтому
soul(характер персоны) на английском с инструкциейWRITE SCRIPTS IN RUSSIANдля выхода.
Навыки (skills)
7 навыков — ИИбан не просто объявляет треки, а ведёт эфир:
| Навык | Что делает |
|---|---|
album-anniversary | Годовщины альбомов — «Ровно 10 лет назад вышел этот альбом…» |
curiosity | Интересные факты о треке/артисте — контекст, истории |
library-deep-cut | Редкие треки из библиотеки — «А вот вам глубокий крой…» |
news | Краткие новости — ИИбан как диктор новостей |
now-playing-dig | Разбор текущего трека — артист, альбом, контекст |
weather | Погода в Перми — советская метеосводка |
web-search | Веб-поиск через DuckDuckGo — актуальный контекст |
Архитектура
Navidrome (671 трек, 241 артист)
↓
Маргинал Controller (DJ agent — 7 skills, tool calling)
↓
vLLM (Gemma 4 12B abliterated, 16K context, numCtx 8128)
↓
Piper TTS (ru_RU-ruslan-medium, 0.2s синтез)
↓
Liquidsoap (crossfade 10s, loudness -14 LUFS)
↓
Icecast → эфир (mp3 320kbps + flac + aac)
vLLM
vLLM — локальная LLM на GPU. OpenAI-совместимый API. Модель Gemma 4 12B (abliterated, FP8).
Ключевые настройки:
reasoning: true— модель думает перед ответом, более развёрнутые скриптыmaxOutputTokens: 1500— баланс между длинными скриптами и чистым JSONtoolChoice: required— DJ agent использует tool calling для навыковpickerAgent: true— LLM сама выбирает треки (не случайный pool)agentTimeoutMs: 300000— 5 минут на pick, потом fallback на poolnoRepeatWindow: 100— не повторяет треки в течение 100 трековpauseWhenEmpty: true— DJ засыпает когда нет слушателей, играет fallback playlist
Abliterated модель и JSON
Модель с убранной safety-tuning иногда выдаёт битый JSON. 5-15% fallback rate — норма для abliterated Gemma 4. Маргинал падает на pool picker, эфир не прерывается. Health report показывает 2-5 schema-validation failures из 20 вызовов.
Piper TTS
Голос ИИбана — Piper (built-in, Russian voices). Перешли с XTTS v2 на Piper — освободили 3.2GB RAM + 820MB swap. Синтез ~0.2s вместо 3-15s на CPU.
4 русских голоса: dmitri (medium), ruslan (medium, deeper), denis (medium), irina (female). ИИбан использует ruslan — глубокий мужской голос.
Эксперимент с Silero TTS
15 июля тестировали Silero TTS как замену Piper — 6 русских голосов, Docker sidecar, CPU. Синтез 0.4-0.9s, RTF 0.15x. Работало, но разница в качестве минимальна, а +530MB RAM и 3.2GB образ не оправданы. Вернулись на Piper.
Web Search
ИИбан ищет в вебе через DuckDuckGo (без VPN, без токена). Навык web-search — актуальные новости, факты об артистах, контекст треков.
Эфир
4 кодировщика: MP3 (320kbps, основной), FLAC, AAC, hourly archive. Load avg 0.5-0.8 на 12 потоков — кодировщики не напрягают.
Скробблинг
Эфир скробблится в ListenBrainz — нативная интеграция Маргинал:
playing_now— когда трек начинаетсяsinglelisten — когда трек доиграл (минимум 30 секунд)
История эфира, статистика, рекомендации — всё на listenbrainz.org/user/mrgnl044.
Библиотека
671 трек, 241 артист. Mood-тегами покрыто 100% библиотеки — ИИбан использует теги для подбора по настроению (calm, energetic, reflective…).
Авто-тегирование
Библиотека тегируется через Beets + кастомные скрипты:
- Обложки — iTunes Search API, 600x600, встраиваются в MP3
- Жанры — iTunes
primaryGenreName(Hip-Hop, Alternative, Rock) - Тексты — lrclib (synced) → Genius (scraping) — встраиваются в MP3
- Очистка тегов —
clean-and-refetch.py(347 строк): чистит title от “Prod. by”, “Remix”, “feat.”, извлекает artist/title из имени файла для нетегированных треков
Cron
| Время | Задача |
|---|---|
| 03:00 | Spotify sync + Beets (метаданные, обложки, тексты) |
| 04:00 | Navidrome scan (переиндексация библиотеки) |
Spotify API 429
Spotify API иногда блокирует приложение на 24 часа (HTTP 429, retry-after 86400). В это время метаданные из Spotify недоступны. spotdl берёт аудио с YouTube Music, метаданные из Spotify API — если API заблокирован, теги не обновляются.
ИИбан использует теги для навыков: now-playing-dig (разбор трека), album-anniversary (годовщины), library-deep-cut (редкие треки). Чем богаче теги — тем содержательнее комментарии.
Сеть
vLLM и Маргинал в разных Docker сетях. Решение — подключить vLLM к сети Маргинал:
docker network connect app_default vllm-serverПосле этого Controller стучится на http://vllm-server:8000/v1.
Команду надо повторять после пересоздания контейнера
Docker не сохраняет ad-hoc подключения к сетям.
Связанные статьи
- ИИбан — продуктовое описание ИИбана (без технических деталей)
- Маргинал — радио, которое ведёт ИИбан
- ListenBrainz — скробблинг эфира
- Beets — авто-тегирование треков
- vLLM — LLM бэкенд
- Silero-TTS — эксперимент с заменой Piper
- ИИбан-бот — мультиагентный бот (Telegram + Matrix)
- Docker — контейнеры и сети