OctoGen automatically generates personalized music playlists for your Navidrome server using an LLM, LastFM, ListenBrainz and/or AudioMuse-AI seamlessly integrating with Octo-Fiesta to download missing tracks.
Built with AI assistance. Contributions and pull requests welcome!
- Multiple LLM providers: Gemini and OpenAI-compatible API-supported providers
- Smart context caching: Efficient, low-cost API usage
- Variety seed: Different recommendations every day
- Discovery (50 songs) - New music discoveries
- Daily Mix 1-6 (30 songs each) - Genre-based mixes
- Chill Vibes (30 songs) - Relaxing tracks
- Workout Energy (30 songs) - High-energy music
- Focus Flow (30 songs) - Ambient/instrumental
- Drive Time (30 songs) - Upbeat driving music
- Time-of-Day Playlist (30 songs) - Mood-matched to current time period
Total: 12 playlists, 380+ songs automatically curated!
Automatic mood-appropriate playlists that rotate based on time of day:
- Morning Mix (4 AM - 10 AM): Upbeat, energetic, positive vibes
- Afternoon Flow (10 AM - 4 PM): Balanced, productive, moderate energy
- Evening Chill (4 PM - 10 PM): Relaxing, wind-down music
- Night Vibes (10 PM - 4 AM): Ambient, calm, sleep-friendly
Features:
- β Hybrid generation: 25 songs from AudioMuse-AI + 5 from LLM
- β Auto-rotates when time period changes
- β Auto-deletes previous period's playlist
- β Configurable time boundaries
- β LLM prompts enhanced with time-of-day context
Enable with:
TIMEOFDAY_ENABLED=trueOctoGen can optionally integrate with AudioMuse-AI for enhanced sonic analysis:
- Default Mode: All playlists use LLM (current behavior)
- Hybrid Mode: Most playlists use 25 AudioMuse-AI + 5 LLM songs
Enable hybrid mode by setting:
AUDIOMUSE_ENABLED=true
AUDIOMUSE_URL=http://localhost:8000Hybrid playlists (when AudioMuse enabled):
- Daily Mix 1-6: Genre-based mixes (25 AudioMuse + 5 LLM)
- Chill Vibes: Relaxing tracks (25 AudioMuse + 5 LLM)
- Workout Energy: High-energy music (25 AudioMuse + 5 LLM)
- Focus Flow: Ambient/instrumental (25 AudioMuse + 5 LLM)
- Drive Time: Upbeat driving music (25 AudioMuse + 5 LLM)
- Time-of-Day Playlist: Depends on time of day (25 AudioMuse + 5 LLM)
LLM-only playlists (always):
- Discovery: New discoveries (50 LLM songs)
This combines:
- AudioMuse-AI: Sonic similarity, mood analysis, audio feature matching
- LLM: Creative variety, metadata-based recommendations
See AudioMuse-AI Setup below.
- Star rating filtering: Excludes 1-2 star rated songs
- Duplicate detection: No repeated tracks across playlists
- Automatic downloads: Missing songs fetched via Octo-Fiesta
- Daily cache: Efficient library scanning
- Async operations: Fast, parallel processing
- LastFM, ListenBrainz & AudioMuse-AI: Optional integrations
- Built-in scheduling: No external cron needed π
- Web UI dashboard: Real-time service health monitoring with auto-refresh
- Prometheus metrics: Track playlists, downloads, API calls, latency
- Circuit breaker: Prevents cascading failures to external APIs
- Structured logging: JSON format support for log aggregation
- Health checks: Monitor Navidrome, Octo-Fiesta, LLM, AudioMuse, LastFM, ListenBrainz
- Modular architecture: Clean, maintainable codebase
- Batch processing: Configurable concurrency for downloads
- Docker secrets: Secure credential management
- Playlist templates: Customizable via YAML configuration
- Configuration validation: Pydantic-based validation with helpful errors
- Progress indicators: Visual feedback for long operations
- Navidrome server running
- Octo-Fiesta configured for downloads
- At least one music source:
- LLM API key (Gemini recommended - free tier available), OR
- AudioMuse-AI configured, OR
- LastFM enabled, OR
- ListenBrainz enabled
Visit: https://aistudio.google.com/apikey
# Create .env file
cat > .env << 'EOF'
# Required
NAVIDROME_URL=http://192.168.1.100:4533
NAVIDROME_USER=admin
NAVIDROME_PASSWORD=your_password
OCTOFIESTA_URL=http://192.168.1.100:5274
AI_API_KEY=your_llm_api_key
# Optional
AI_MODEL=gemini-2.5-flash
AI_BACKEND=gemini
LOG_LEVEL=INFO
# Scheduling
SCHEDULE_CRON=0 2 * * *
TZ=America/Chicago
EOF# Pull the image
docker pull blueion76/octogen:latest
# Run OctoGen with automatic scheduling
docker run -d \
--name octogen \
-v octogen-data:/data \
--env-file .env \
--restart unless-stopped \
blueion76/octogen:latest
# Check logs (see countdown to next run!)
docker logs -f octogenOpen Navidrome and find your new playlists! π
Playlists update automatically at the time(s) you set your cronjob
To test the latest development version:
docker pull blueion76/octogen:devFor production use (recommended):
docker pull blueion76/octogen:latestversion: '3.8'
services:
octogen:
image: blueion76/octogen:latest
container_name: octogen
restart: unless-stopped
volumes:
- octogen-data:/data
environment:
# Required
NAVIDROME_URL: http://navidrome:4533
NAVIDROME_USER: admin
NAVIDROME_PASSWORD: ${NAVIDROME_PASSWORD}
OCTOFIESTA_URL: http://octofiesta:5274
AI_API_KEY: ${GEMINI_API_KEY}
# Scheduling
SCHEDULE_CRON: "0 2,4,10,16,22 * * *" # Daily at 2 AM, 4 AM, 10 AM, 4 PM and 10 PM
TZ: America/Chicago
# Optional
AI_MODEL: gemini-2.5-flash
AI_BACKEND: gemini
LOG_LEVEL: INFO
volumes:
octogen-data:Run:
docker-compose up -d
docker-compose logs -f octogenOctoGen includes a real-time monitoring dashboard accessible at http://localhost:5000.
-
Service Health Monitoring: Real-time status for all connected services
- Navidrome (connection, library stats)
- Octo-Fiesta (connection status)
- LLM Engine (backend, model, status)
- AudioMuse-AI (enabled/disabled, health)
- LastFM (enabled/disabled, connection)
- ListenBrainz (enabled/disabled, connection)
-
System Statistics:
- Playlists created
- Songs rated
- Low-rated song count
- Cache size
- Last run timestamp
- Next scheduled run
-
REST API:
GET /api/health- Overall health statusGET /api/services- Detailed service informationGET /api/stats- System statisticsGET /api/status- Current run status
-
Auto-refresh: Dashboard updates every 30 seconds
# Enable web UI (enabled by default)
WEB_ENABLED=true
# Configure port
WEB_PORT=5000Expose port 5000 in your docker-compose.yml:
services:
octogen:
image: blueion76/octogen:latest
ports:
- "5000:5000" # Web UI dashboard
environment:
WEB_ENABLED: "true"
WEB_PORT: "5000"Access the dashboard at http://localhost:5000 after starting the container.
To enable hybrid playlist generation with sonic analysis:
Follow the AudioMuse-AI documentation to deploy:
- Open AudioMuse-AI at
http://localhost:8000 - Navigate to "Analysis and Clustering"
- Click "Start Analysis" (one-time, analyzes your library)
- Wait for completion
Add to your .env:
AUDIOMUSE_ENABLED=true
AUDIOMUSE_URL=http://localhost:8000
AUDIOMUSE_AI_PROVIDER=gemini
AUDIOMUSE_AI_MODEL=gemini-2.5-flash
AUDIOMUSE_AI_API_KEY=your_api_key_hereAUDIOMUSE_SONGS_PER_MIX=25 # Songs from AudioMuse (default: 25)
LLM_SONGS_PER_MIX=5 # Songs from LLM (default: 5)| Variable | Description | Example |
|---|---|---|
NAVIDROME_URL |
Navidrome server URL | http://192.168.1.100:4533 |
NAVIDROME_USER |
Navidrome username | admin |
NAVIDROME_PASSWORD |
Navidrome password | your_password |
OCTOFIESTA_URL |
Octo-Fiesta server URL | http://192.168.1.100:5274 |
Note: At least one music source must also be configured:
AI_API_KEY(for LLM-based playlists), ORAUDIOMUSE_ENABLED=true(for AudioMuse-AI sonic analysis), ORLASTFM_ENABLED=true(for LastFM recommendations), ORLISTENBRAINZ_ENABLED=true(for ListenBrainz recommendations)
| Variable | Default | Description |
|---|---|---|
AI_MODEL |
gemini-2.5-flash |
AI model to use |
AI_BACKEND |
gemini |
Backend: gemini or openai |
AI_BASE_URL |
(none) | Custom API endpoint |
SCHEDULE_CRON |
(none) | Cron schedule (e.g., 0 2 * * *) |
TZ |
UTC |
Timezone (e.g., America/Chicago) |
LOG_LEVEL |
INFO |
DEBUG, INFO, WARNING, ERROR |
See ENV_VARS.md for complete reference.
AI_BACKEND=gemini
AI_MODEL=gemini-2.5-flash
AI_API_KEY=your_llm_api_keyGet key: https://aistudio.google.com/apikey
AI_BACKEND=openai
AI_BASE_URL=https://api.groq.com/openai/v1
AI_MODEL=llama-3.3-70b-versatile
AI_API_KEY=your_groq_api_keyGet key: https://console.groq.com
AI_BACKEND=openai
AI_MODEL=gpt-4o
AI_API_KEY=your_openai_api_keyAI_BACKEND=openai
AI_BASE_URL=http://host.docker.internal:11434/v1
AI_MODEL=llama3.2
AI_API_KEY=ollamaAI_BACKEND=openai
AI_BASE_URL=https://openrouter.ai/api/v1
AI_MODEL=anthropic/claude-3.5-sonnet
AI_API_KEY=your_openrouter_api_keyOctoGen includes built-in cron scheduling
Just add these two environment variables:
SCHEDULE_CRON=0 2 * * * # Daily at 2 AM
TZ=America/Chicago # Your timezoneThe container stays running and automatically executes on schedule. You'll see countdown logs:
π OCTOGEN SCHEDULER
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Schedule: 0 2 * * *
Timezone: America/Chicago
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π
Next scheduled run: 2026-02-11 06:00:00
β° Next run in 3.5 hours (2026-02-11 06:00:00)
Music| Schedule | Cron Expression | Description |
|----------|----------------|-------------|
| Daily at 2 AM | 0 2 * * * | Once per day |
| Twice daily | 0 */12 * * * | Every 12 hours |
| Every 6 hours | 0 */6 * * * | 4 times per day |
| Weekly (Sunday 3 AM) | 0 3 * * 0 | Once per week |
| Every Monday 9 AM | 0 9 * * 1 | Weekly on Monday |
Cron Format:
* * * * *
β β β β β
β β β β ββββ Day of week (0-7)
β β β ββββββ Month (1-12)
β β ββββββββ Day of month (1-31)
β ββββββββββ Hour (0-23)
ββββββββββββ Minute (0-59)
Test your expressions: crontab.guru
Important: Set TZ to get correct local times! Without it, times are in UTC.
# United States
TZ=America/New_York # Eastern
TZ=America/Chicago # Central
TZ=America/Denver # Mountain
TZ=America/Los_Angeles # Pacific
# Europe
TZ=Europe/London # UK
TZ=Europe/Paris # France
TZ=Europe/Berlin # Germany
# Other
TZ=Asia/Tokyo # Japan
TZ=Australia/Sydney # AustraliaLeave SCHEDULE_CRON unset or set to manual:
OctoGen uses a modular architecture with clean separation of concerns:
octogen/
βββ api/ # External API clients (Navidrome, LastFM, ListenBrainz, AudioMuse)
βββ ai/ # Multi-backend LLM recommendation engine
βββ monitoring/ # Prometheus metrics + circuit breaker
βββ web/ # Flask dashboard
βββ storage/ # SQLite ratings cache
βββ models/ # Pydantic configuration validation
βββ playlist/ # Template system
βββ scheduler/ # Cron support
βββ utils/ # Auth, secrets, retry, batch processing, logging
-
Analyzes your Navidrome library
- Reads starred/favorited songs
- Identifies top artists and genres
- Caches ratings (daily refresh for performance)
-
Generates LLM recommendations
- Sends music profile to LLM (or uses AudioMuse/LastFM/ListenBrainz)
- Excludes low-rated songs (1-2 stars)
- Requests 11 themed playlists with variety
-
Smart processing
- Checks which songs exist in library (fuzzy matching)
- Detects and prevents duplicates
- Triggers downloads for missing tracks via Octo-Fiesta
- Processes in batches with configurable concurrency
-
Creates playlists in Navidrome
- Builds 11 themed playlists
- Mixes library favorites with discoveries
- Applies star rating filters
-
Monitoring & scheduling
- Records metrics (if enabled)
- Updates web dashboard (if enabled)
- Waits for next scheduled run (if configured)
- Automatically retries on errors with circuit breaker
- Navidrome API: Library reading, playlist creation, rating management
- LLM Provider: Personalized recommendations (Gemini, OpenAI, Groq, Ollama, etc.)
- Octo-Fiesta: Automatic download of missing tracks
- SQLite Cache: Rating storage with daily refresh
- Circuit Breaker: Prevents cascading failures to external APIs
- Prometheus: Metrics collection for monitoring (optional)
- Web Dashboard: Real-time monitoring interface (optional)
- Scheduler: Built-in cron for automatic execution
Test without making changes:
docker run --rm \
-v octogen-data:/data \
--env-file .env \
blueion76/octogen:latest \
python octogen.py --dry-runShows what would happen without:
- Downloading songs
- Creating playlists
- Making any changes
OctoGen stores data in /data:
/data/
βββ octogen.log # Application logs
βββ octogen_cache.db # Star ratings cache
βββ gemini_cache.json # LLM context cache
βββ octogen.lock # Prevents duplicate runs
Mount a volume to persist data:
-v octogen-data:/dataView container logs:
# Real-time logs
docker logs -f octogen
# Last 100 lines
docker logs --tail 100 octogen
# Save to file
docker logs octogen > octogen.logLogs show:
- β Successful operations (green checkmarks)
β οΈ Warnings (yellow)- β Errors (red)
- π Scheduled run countdown
- π Statistics (playlists created, songs downloaded)
Enable metrics collection:
# In .env or docker-compose.yml
METRICS_ENABLED=true
METRICS_PORT=9090
# Expose port
docker run -p 9090:9090 ...Access metrics:
# Metrics endpoint
curl http://localhost:9090/metricsAvailable metrics:
octogen_playlists_created_total{source}- Playlists createdoctogen_songs_downloaded_total- Songs downloadedoctogen_api_calls_total{service,status}- API callsoctogen_api_latency_seconds{service}- API latencyoctogen_ai_tokens_used- LLM tokens consumedoctogen_last_run_timestamp- Last successful runoctogen_last_run_duration_seconds- Run duration
Integrate with Prometheus:
# prometheus.yml
scrape_configs:
- job_name: 'octogen'
static_configs:
- targets: ['octogen:9090']Enable web dashboard for real-time monitoring:
# In .env or docker-compose.yml
WEB_UI_ENABLED=true
WEB_UI_PORT=5000
# Expose port
docker run -p 5000:5000 ...Access dashboard at: http://localhost:5000
Dashboard shows:
- Real-time status and health
- Statistics (playlists, downloads, failures)
- Service health checks (Navidrome, Octo-Fiesta)
- Auto-refreshes every 30 seconds
# Container status
docker ps -a | grep octogen
# Resource usage
docker stats octogen
# Health check file
docker exec octogen cat /data/health.json
# Verify scheduler
docker logs octogen | grep "SCHEDULER"
# See next run time
docker logs octogen | grep "Next scheduled run"
# Verify timezone
docker logs octogen | grep "Timezone:"# Check data directory
docker exec octogen ls -lh /data
# View log file
docker exec octogen tail -n 50 /data/octogen.log
# Check cache
docker exec octogen sqlite3 /data/octogen_cache.db "SELECT COUNT(*) FROM ratings;"Solution:
- Check
NAVIDROME_URLis correct - Use Docker network name if both containers on same network
- Try:
http://navidrome:4533instead ofhttp://localhost:4533
Solution:
- Verify API key is correct
- Check API provider status
- Ensure you have API credits/quota
- Try different model if rate limited
Solution:
- Check logs:
docker logs octogen - Ensure you have starred songs in Navidrome
- Verify Octo-Fiesta is running
- Try dry-run mode to see what would happen
Solution:
- Verify
OCTOFIESTA_URLis correct - Check Octo-Fiesta is configured properly
- Ensure Navidrome credentials are correct
- Check network connectivity between containers
Solution:
- Verify
SCHEDULE_CRONis set:docker inspect octogen | grep SCHEDULE_CRON - Check logs for "OCTOGEN SCHEDULER" message
- Ensure container has restart policy:
--restart unless-stopped - Verify timezone:
docker logs octogen | grep "Timezone:"
Solution:
- Set
TZenvironment variable to your timezone - Without
TZ, times are in UTC - Check current timezone in logs
- Test cron expression at crontab.guru
Components:
- Navidrome API: Reads library, creates playlists
- LLM Provider: Generates recommendations
- Octo-Fiesta: Downloads missing tracks
- SQLite Cache: Stores ratings (daily refresh)
- Logs: Application activity
- Built-in Scheduler: Automatic execution
- ENV_VARS.md - Complete environment variables reference
Contributions welcome! Just create a pull request.
- Navidrome - Open-source music server
- Octo-Fiesta - Automated music downloader
- LastFM - Music discovery API
- ListenBrainz - Open music metadata
- AudioMuse-AI - In-depth analysis of your music library
- Docker Hub: hub.docker.com/r/blueion76/octogen
- GitHub: github.com/Blueion76/Octogen
- Issues: github.com/Blueion76/Octogen/issues
If you find this project useful, please consider giving it a star! β
Made with β€οΈ for the self-hosted music community