Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
cd177b7
Refactor volume mapping
drolex2 Aug 29, 2025
3099c76
Refactor volume mapping
drolex2 Aug 29, 2025
90791f5
update for refactored mounts and variables
drolex2 Aug 30, 2025
71ab0c4
updated project structure and docker-compose
drolex2 Aug 30, 2025
17941de
switched appdata from named volume to bind
drolex2 Aug 30, 2025
9b21c86
Delete LICENSE from app dir
drolex2 Aug 30, 2025
cea2550
improve artist cover search
drolex2 Sep 1, 2025
eba0e06
update image extensions in _find_cover_in_directory
drolex2 Sep 1, 2025
54537bd
add method to get artist image from Jellyfin API
drolex2 Sep 2, 2025
0b8fdfa
debug previous commit
drolex2 Sep 2, 2025
b582456
update _try_artist_folder_fallback for modified _find_artist_cover_im…
drolex2 Sep 2, 2025
0d1f56e
use as internal and external port
drolex2 Sep 7, 2025
e2aaa99
remove export of forced LOG_LEVEL to respect user setting
drolex2 Sep 7, 2025
1c1afbc
Use WEB_PORT internally, respect user set LOG_LEVEL, correct path of …
drolex2 Sep 7, 2025
2795f54
change log_level var to log_level_num for consistency
drolex2 Sep 7, 2025
1aa5dd7
update: use WEB_PORT internally
drolex2 Sep 7, 2025
d3cf15c
add default values for essential vars
drolex2 Sep 7, 2025
74621e7
correct default port settings
drolex2 Sep 7, 2025
c0fadde
fix playlist directory mismatch when artist name has special characters
drolex2 Sep 7, 2025
0f26cd5
correct default LOG_LEVEL
drolex2 Sep 7, 2025
98eb9ee
add comment about default values
drolex2 Sep 8, 2025
47434f2
increase timeout for gunicorn
drolex2 Sep 8, 2025
591ca4d
correct default LOG_LEVEL again
drolex2 Sep 8, 2025
cc7257f
support additional image extentions for remaining playlist types
drolex2 Sep 8, 2025
af8952b
reflect code updates
drolex2 Sep 8, 2025
119fe6c
Merge branch 'refactor-mounts' of github.com:drolex2/JellyJams into r…
drolex2 Sep 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@

# Jellyfin Server Configuration
JELLYFIN_URL=http://jellyfin:8096
JELLYFIN_API_KEY=your_jellyfin_api_key_here
JELLYFIN_API_KEY=
PLAYLIST_DIR_HOST=/host/path/to/jellyfin/config/data/playlists
MUSIC_DIR_HOST=/host/path/to/music
MUSIC_DIR_CONTAINER=/jellyfin/container/path/to/music

# Playlist Configuration
PLAYLIST_FOLDER=/app/playlists
GENERATION_INTERVAL=24
MAX_TRACKS_PER_PLAYLIST=100
MIN_TRACKS_PER_PLAYLIST=5
Expand Down
11 changes: 2 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,16 @@ FROM python:3.11-alpine

# Set working directory and copy app files
WORKDIR /app
COPY . /app
COPY app /app
RUN chmod +x /app/start.sh

# Install required packages
RUN pip install --no-cache-dir -r requirements.txt

# Create directories for playlists, logs, config, and cover
RUN mkdir -p playlists logs config cover

# Copy default cover files to a temporary location
COPY data/cover default_cover
RUN pip install --no-cache-dir -r /app/requirements.txt

# Set environment variables
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
ENV JELLYFIN_URL=http://jellyfin:8096
ENV PLAYLIST_FOLDER=/app/playlists
ENV LOG_LEVEL=INFO
ENV GENERATION_INTERVAL=24
ENV ENABLE_WEB_UI=true
Expand Down
140 changes: 86 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,12 @@ docker run -p 5000:5000 jonasmore/jellyjams
- **Custom Generated Covers** - "This is [Artist]" text overlays on artist folder images
- **Spotify Integration** - Automatic artist playlist cover downloads from Spotify
- **Predefined Custom Covers** - Manual cover art for specific playlists
- **Smart Fallbacks** - Generic covers per playlist type ("Top Tracks - all.jpg")
- **Artist Folder Integration** - Uses existing folder.jpg from music directories
- **Smart Fallbacks** - Generic covers per playlist type ("Top Tracks - all.ext")
- **Multi-format Support** - Searches for images in multiple formats (JPG, JPEG, PNG, WebP, AVIF, BMP)
- **Artist Folder Integration** - Uses existing folder.ext from music directories
- **Unicode Support** - Handles special characters in artist names (alt‐J, Sigur Rós, etc.)
- **Extension Preservation** - Maintains original image formats (PNG, JPG)
- **Extension Preservation** - Maintains original image format when copying.
- **Generated Image Format** - Saves generated images as WebP for high quality and compression.

### 🌐 Modern Web Interface
- **Beautiful Dark Theme** - Modern, responsive design
Expand Down Expand Up @@ -108,39 +110,41 @@ WEBUI_BASIC_AUTH_PASSWORD=your_password
- **Custom Generated Covers** - "This is [Artist]" text overlays on artist folder images
- **Spotify Integration** - Automatic artist playlist cover downloads from Spotify
- **Predefined Custom Covers** - Manual cover art for specific playlists
- **Smart Fallbacks** - Generic covers per playlist type ("Top Tracks - all.jpg")
- **Artist Folder Integration** - Uses existing folder.jpg from music directories
- **Smart Fallbacks** - Generic covers per playlist type ("Top Tracks - all.ext")
- **Multi-format Support** - Searches for images in multiple formats (JPG, JPEG, PNG, WebP, AVIF, BMP)
- **Artist Folder Integration** - Uses existing folder.ext from music directories
- **Unicode Support** - Handles special characters in artist names (alt‐J, Sigur Rós, etc.)
- **Extension Preservation** - Maintains original image formats (PNG, JPG)
- **Extension Preservation** - Maintains original image format when copying.
- **Generated Image Format** - Saves generated images as WebP for high quality and compression.

### 🎯 Cover Art Priority System
1. **Custom Generated Covers** (Artist playlists)
2. **Spotify Cover Art** (Artist playlists, if enabled)
3. **Predefined Custom Covers** (Manual covers)
4. **Artist Folder Fallback** (Uses existing folder.jpg)
4. **Artist Folder Fallback** (Uses existing folder.ext)
5. **Generic Fallbacks** (Type-specific defaults)

#### 🖼️ Custom Generated Covers
For artist playlists, JellyJams automatically generates professional "This is [Artist]" covers:
- Uses artist's existing folder.jpg as background
- Uses artist's existing folder.ext as background
- Adds stylized text overlay with adaptive colors
- Handles Unicode characters (alt‐J, Sigur Rós, Mötley Crüe)
- High-quality PNG output with text shadows
- Automatic brightness analysis for optimal text contrast

#### 📁 Predefined Custom Covers
Place custom images in your cover directory (mapped to `/app/cover`):
- Exact playlist name matching: `"Top Tracks - Jonas.jpg"`
- Generic fallbacks: `"Top Tracks - all.png"`
- Decade-specific covers: `"Back to the 1990s.jpg"`
- Genre-specific covers: `"Jazz Radio.jpg"`
- Exact playlist name matching: `"Top Tracks - Jonas.ext"`
- Generic fallbacks: `"Top Tracks - all.ext"`
- Decade-specific covers: `"Back to the 1990s.ext"`
- Genre-specific covers: `"Jazz Radio.ext"`

#### 🎵 Artist Folder Integration
JellyJams can use existing cover art from your music library:
- Searches for `folder.jpg`, `cover.jpg`, `artist.jpg` in artist directories
- Supports multiple music directory paths (`/app/music`, `/music`, `/media`, etc.)
- Searches for `folder.ext`, `cover.ext`, `artist.ext` in artist directories
- You set the music directory path (in .env) to the same path you set in Jellyfin
- Case-insensitive artist folder matching
- Multiple image format support (JPG, PNG, WebP)
- Multiple image format support (JPG, PNG, WebP, AVIF, BMP)

#### 🔄 Update Covers Feature
Refresh cover art for existing playlists without regenerating:
Expand All @@ -164,14 +168,14 @@ JellyJams automatically triggers a Jellyfin media library scan after playlist cr
JellyJams creates playlists in the following format:

```
📁 Playlists/
├── Rock Radio/
📁/playlists/
├── 📁Rock Radio/
│ └── playlist.xml
├── Jazz Radio/
├── 📁Jazz Radio/
│ └── playlist.xml
├── Back to the 1970s/
├── 📁Back to the 1970s/
│ └── playlist.xml
└── This is The Beatles!/
└── 📁This is The Beatles!/
└── playlist.xml
```

Expand Down Expand Up @@ -203,41 +207,62 @@ version: '3.8'

services:
jellyjams:
build: .
image: jonasmore/jellyjams:latest
container_name: jellyjams
environment:
- JELLYFIN_URL=${JELLYFIN_URL}
# Default values are set here like ${VAR_NAME:-DEFAULT_VALUE}
# in case they aren't provided in the .env file. If you use the
# .env file, there is no need to change the default values.

# Essential container settings (not configurable via web UI)
- JELLYFIN_URL=${JELLYFIN_URL:-http://jellyfin:8096}
- JELLYFIN_API_KEY=${JELLYFIN_API_KEY}
- ENABLE_WEB_UI=true
- ENABLE_WEB_UI=${ENABLE_WEB_UI:-true}
- WEB_PORT=${WEB_PORT:-5000}
# Default fallback values (web UI settings will override these)
- LOG_LEVEL=${LOG_LEVEL:-DEBUG}
- GENERATION_INTERVAL=${GENERATION_INTERVAL}
- MAX_TRACKS_PER_PLAYLIST=${MAX_TRACKS_PER_PLAYLIST}
- MIN_TRACKS_PER_PLAYLIST=${MIN_TRACKS_PER_PLAYLIST}
- EXCLUDED_GENRES=${EXCLUDED_GENRES}
- SHUFFLE_TRACKS=${SHUFFLE_TRACKS}
- PLAYLIST_TYPES=${PLAYLIST_TYPES}
# Web UI Security (environment variables override web UI settings)
- WEBUI_BASIC_AUTH_ENABLED=${WEBUI_BASIC_AUTH_ENABLED}
- WEBUI_BASIC_AUTH_USERNAME=${WEBUI_BASIC_AUTH_USERNAME}
- WEBUI_BASIC_AUTH_PASSWORD=${WEBUI_BASIC_AUTH_PASSWORD}
# Discord Notifications
- DISCORD_WEBHOOK_ENABLED=${DISCORD_WEBHOOK_ENABLED}
- DISCORD_WEBHOOK_URL=${DISCORD_WEBHOOK_URL}
volumes:
- jellyjams_playlists:/app/playlists
- jellyjams_logs:/app/logs
- jellyjams_config:/app/config
# Music directory for cover art generation (adjust path for your system)
- /mnt/user/media/data/music:/mnt/user/media/data/music:ro
# JellyJames app data - bind to existing host directory
- ./jellyjams:/data
# Ready-only access to music directory for cover art generation
- ${MUSIC_DIR_HOST}:${MUSIC_DIR_CONTAINER}:ro
# Jellyfin playlists directory for playlist and art management
- ${PLAYLIST_DIR_HOST}:/playlists
ports:
- "5000:5000"
- "${WEB_PORT:-5000}:${WEB_PORT:-5000}"
restart: unless-stopped

volumes:
jellyjams_playlists:
jellyjams_logs:
jellyjams_config:
```

### Unraid Deployment

For Unraid users, use bind mounts to `/mnt/user/appdata/jellyjams/`:
For Unraid users, use bind app data to `/mnt/user/appdata/jallyjams/` for persistent storage:

```yaml
volumes:
# Playlist folder location of Jellyfin
- /mnt/user/appdata/Jellyfin/data/playlists:/app/playlists
# JellyJams settings and logs
- /mnt/user/appdata/jellyjams/logs:/app/logs
- /mnt/user/appdata/jellyjams/config:/app/config
# Music directory for cover art generation (adjust path for your system)
- /mnt/user/media/data/music:/mnt/user/media/data/music:ro
volumes:
# JellyJames app data
- /mnt/user/appdata/jellyjams:/data
# Ready-only access to music directory for cover art generation
- ${MUSIC_DIR_HOST}:${MUSIC_DIR_CONTAINER}:ro
# Jellyfin playlists directory for playlist and art management
- ${PLAYLIST_DIR_HOST}:/playlists

# Set these vars in your .env
PLAYLIST_DIR_HOST=/mnt/user/appdata/jellyfin/data/playlists
MUSIC_DIR_HOST=/mnt/user/media/data/music
MUSIC_DIR_CONTAINER=/mnt/user/media/data/music
```

## 🔧 API Integration
Expand All @@ -249,6 +274,7 @@ JellyJams uses the Jellyfin REST API to:
- Handle semicolon-separated genre strings
- Test connection status
- Retrieve audio item details
- Retrieve the primary image of artists

## 🎨 Web UI Features

Expand Down Expand Up @@ -282,19 +308,25 @@ JellyJams uses the Jellyfin REST API to:

```
jellyjams/
├── vibecodeplugin.py # Main playlist generator
├── webapp.py # Flask web UI
├── start.sh # Container startup script
├── .env.example # Environment template
├── Dockerfile # Container definition
├── docker-compose.yml # Docker Compose config
├── requirements.txt # Python dependencies
├── .env.example # Environment template
└── templates/ # HTML templates
├── base.html
├── index.html
├── settings.html
├── playlists.html
└── logs.html
└── app/ # Container app files
├── vibecodeplugin.py # Main playlist generator
├── webapp.py # Flask web UI
├── start.sh # Container startup script
├── requirements.txt # Python dependencies
└── cover # Default playlist images
├── Playlist Name.jpg
└── static/ # WebUI assets
└── css/
├── app.css
└── templates/ # HTML templates
├── base.html
├── index.html
├── settings.html
├── playlists.html
└── logs.html
```

## 🤝 Contributing
Expand Down
Loading
Loading