Skip to content

Conversation

@rendyhd
Copy link
Contributor

@rendyhd rendyhd commented Nov 29, 2025

This is a draft to share the playlist builder I made. I marked it as experimental because I've changed a lot to get it to work the way I wanted it, which is not necessarily in line with the core purpose of this project.

NOTE: If you want to test this, I'd recommend you make sure it runs on a new postgres volume, it is not compatible the production one
It's built on top of #195

Summary

New Playlist Builder page that combines song discovery via Smart Filters with playlist extension capabilities, plus an integrated web player for previewing songs and dark mode support.

New Features

Playlist Builder Page

A new unified interface at /playlist_builder with two tabs:

Smart Filters Tab

  • Search and filter songs by multiple criteria: mood, energy, BPM, key, scale, artist, album, title
  • Supports operators: contains, does not contain, is, is not, greater than, less than
  • "Match All" vs "Match Any" filter logic
  • Exclude button to remove unwanted songs from results
  • "Send to Extend Playlist" to use filtered results as seeds for similarity search

Existing Playlist Tab

  • Load playlists from your media server
  • Extend with similar songs based on the playlist's audio centroid
  • Include/Exclude buttons to curate recommendations
  • Adjustable result count and max songs per artist
  • Track Weights, to fine-tune playlist preferences

Web Player

  • Sticky audio player at bottom of page
  • Play/pause, seek forward/back, stop controls
  • Displays current track title and artist
  • Streams directly from Jellyfin, Emby, or Navidrome (in theory, only tested on Jellyfin)

Dark Mode

  • Toggle via menu button
  • Persists preference to localStorage
  • Respects system preference on first visit

Playlist Saving

  • Save curated playlists directly to media server
  • Option to save without _instant suffix (for Playlist Builder saves)

Next step: I'm looking to add star ratings, but unfortunately Jellyfin doesn't support this. Might have to experiment with Navidrome

Other Improvements

  • Jellyfin/Emby: Added stream_url and song_artist to API responses
  • Analysis UI: Fixed progress tracking bug
  • API: Similarity results now include title and author fields

Screenshots

image image

claude and others added 30 commits November 18, 2025 21:44
Implements a new service and page for extending playlists with similar songs.

Key features:
- Fetch and display existing playlists from the database
- Find similar songs based on the entire playlist's centroid vector
- Adjustable similarity threshold slider (0.0-1.0)
- Configurable max songs limit
- Accept/Decline buttons for each suggested song
- Dynamic re-search when songs are accepted (included in centroid) or declined (excluded from results)
- Save extended playlist with original + accepted songs to media server
- Real-time statistics display showing original, accepted, declined, and suggested song counts

Files added:
- app_extend_playlist.py: Backend blueprint with API endpoints
- templates/extend_playlist.html: Frontend UI with interactive controls

Files modified:
- app.py: Registered extend_playlist_bp blueprint
- templates/sidebar_navi.html: Added navigation link
…s8mGAn5UghuFemm5ydF3

Claude/add openrouter support 01 c fs8m g an5 ughu femm5yd f3
CONFIRMED: GPU (CUDA) is currently only used for Analysis, not Clustering

RESEARCH FINDINGS:
- GPU acceleration can provide 10-30x speedup for clustering tasks
- KMeans: 10-50x faster, DBSCAN: 5-100x faster, PCA: 10-40x faster
- Example: 5000 clustering runs that take 2-4 hours on CPU can complete in 5-15 minutes on GPU

IMPLEMENTATION:
Implemented GPU-accelerated clustering using RAPIDS cuML as an optional feature:

New Features:
- GPU-accelerated KMeans, DBSCAN, and PCA using RAPIDS cuML
- Automatic fallback to CPU if GPU unavailable or encounters errors
- New environment variable USE_GPU_CLUSTERING (default: false)
- Maintains all existing clustering options and settings
- Compatible with CUDA 12.2+ and NVIDIA GPUs

Files Modified:
1. config.py:
   - Added USE_GPU_CLUSTERING configuration flag

2. tasks/clustering_gpu.py (NEW):
   - Created GPU clustering module with RAPIDS cuML implementations
   - GPU-accelerated classes: GPUKMeans, GPUDBSCAN, GPUPCA
   - CPU-only wrappers: GPUGaussianMixture, GPUSpectralClustering
   - Factory functions for model creation with GPU/CPU selection
   - Automatic GPU availability detection and graceful fallback

3. tasks/clustering_helper.py:
   - Imported GPU clustering module with fallback handling
   - Updated _perform_single_clustering_iteration to use GPU PCA when enabled
   - Modified _apply_clustering_model to support GPU clustering
   - Maintains full backward compatibility with CPU-only mode

4. Dockerfile:
   - Added cupy-cuda12x and cuml-cu12 installation for NVIDIA builds
   - Only installs GPU packages when BASE_IMAGE is nvidia/cuda
   - CPU builds remain unchanged and lightweight

5. deployment/.env.example:
   - Added USE_GPU_CLUSTERING configuration with documentation
   - Default: false (CPU only, backward compatible)

6. README.md:
   - Added "GPU Acceleration for Clustering" section
   - Documented performance improvements and usage instructions
   - Listed supported algorithms and compatibility requirements
   - Noted that GaussianMixture and SpectralClustering use CPU (no GPU version)

Notes:
- GPU clustering is OPTIONAL and disabled by default
- CPU clustering remains the default for backward compatibility
- All existing clustering parameters and settings are preserved
- GaussianMixture and SpectralClustering always use CPU (no cuML implementation)
- GPU usage: Analysis (ONNX inference) + Clustering (RAPIDS cuML, optional)
The bash -lc subshell prevented access to the BASE_IMAGE ARG,
causing GPU packages (cupy, cuml) to never be installed.

Changed to use 'set -ux;' pattern (matching base stage) which
properly accesses Docker ARG variables in the current shell.

This ensures cuML and cupy are installed when building with
nvidia/cuda base images, enabling GPU-accelerated clustering.
The new docker image needed packages that where quite large, resulting in a very slow docker build
Dealing with empty responses, sql handling, and how it retires.
The pre-requirements also would fail silently, now that's explicit and it asks for a retry
…ct play URL for Jellyfin

- Added `album`, `song_artist`, and `album_artist` columns to the `score` table in PostgreSQL.
- Updated `tasks/mediaserver_jellyfin.py` to extract `SongArtist` and preserve `OriginalAlbumArtist` from Jellyfin items.
- Updated `tasks/analysis.py` and `app_helper.py` to persist the new metadata fields during track analysis.
- Updated `app_sonic_fingerprint.py` to include the new metadata fields and construct a direct stream URL in the API response.
- Dockerfile: Conditionally install `voyager` only in CUDA/GPU images. `voyager` requires AVX instructions which may crash on old CPUs. The non-CUDA image will now skip `voyager` to ensure compatibility with older hardware (Celeron/ARM).
- tasks/artist_gmm_manager.py:
    - Wrap `import voyager` in try-except block to handle missing library gracefully on old CPUs.
    - Add `VOYAGER_AVAILABLE` checks to disable artist similarity features if the library is missing, preventing crashes.
    - Add support for GPU-accelerated GMM using `cuml.mixture.GaussianMixture` if available, falling back to `sklearn` otherwise.
- tasks/voyager_manager.py:
    - Wrap `import voyager` in try-except block.
    - Add `VOYAGER_AVAILABLE` checks to `build_and_store_voyager_index` and `load_voyager_index_for_querying` to prevent crashes on non-AVX systems.
- Added Smart Filters UI to Extend Playlist page, allowing users to select seed tracks based on metadata rules (Album, Artist, BPM, etc.).
- Integrated a sticky Web Player to play songs directly from search results.
- Updated results to display "Song Artist" instead of "Album Artist".
- Backend updates to `app_extend_playlist.py`:
    - Added `_build_filter_query` to construct SQL from filters.
    - Added `_get_stream_url` to generate playback URLs for Jellyfin/Emby/Navidrome.
    - Updated `extend_playlist_api` to accept filters and return enriched metadata (song_artist, stream_url).
    - Updated `save_extended_playlist` to handle filter-based sources.
- Frontend updates to `templates/extend_playlist.html`:
    - Implemented Filter Builder UI.
    - Implemented Sticky Audio Player.
    - Added Play buttons to result rows.
New feature that lets you weight tracks from x1 to x1024 to control
how much they influence similar song recommendations.

Features:
- Weight buttons cycle: x1→x2→x4→...→x512→x1024→x1
- Source Playlist Drawer shows your tracks with weight controls
- Works for both Smart Filter→Extend AND Existing Playlist flows
- Remove button drops tracks; Exclude button pushes away similar songs
- Auto-recalculates recommendations 500ms after weight changes

Backend:
- Weighted centroid: sum(w_i * v_i) / sum(w_i)
- At x1024, one track = 99.1% of the centroid influence
- Server-side weight validation

Also fixed: weights and include/exclude state now survive recalculations

TL;DR: That one perfect track can now bully the algorithm into submission 💪
@rendyhd
Copy link
Contributor Author

rendyhd commented Dec 8, 2025

Hi @NeptuneHub ,
I've been further experimenting, here is a list of things I've looked at:

  • The Playlist curator shared above, this includes
    • Smart Filter (to implement this I included track artist besides album artist and Track rating (currently only tested with Plex, as Jellyfin doesn't support))
    • Expand Playlist (including track preview via web player, so I had to include stream_url - this isn't available for all services though). For this I also added a Track Weight feature, for longer playlists
    • Because I wanted the playlist on both Plex and Jellyfin, I've been looking at a primary/secondary provider possibility
  • Plex integration for track ratings - don't know if this was the best choice regarding overhead, but I already had a script that synced track ratings between plex and mp3 tags.
    • To get the flacs via plex API was quite unreliable with closed connections, so I looked at adding Direct File Access (it gets the path and meta data from plex, and then directly grabs the file over cifs)
  • Dark mode
  • Ways to speed up the analysis, this has been very tricky to balance though.

Would there be things you're interested in for the main project?

@NeptuneHub
Copy link
Owner

NeptuneHub commented Dec 8, 2025

Hi @rendyhd, thanks again for your great work!

It would be very interesting if you want integrate these features into the main project:

  • Expand Playlist: Great idea. If you add streaming API support (in mediaserver.py and its specializations), please make sure to check each supported server (Jellyfin, Navidrome, Emby, Lyrion). Implement it where supported, and simply disable the streaming feature where it isn’t. The deployment config (deployment/config.py) already exposes the current music server via env vars.
  • Smart filter: Same logic as above, support the feature for all servers that can handle it, and disable it where they cannot to avoid errors.
  • Dark mode: this is also very appreciated if you can implement it in the entire front-end, like a button to switch between light and dark mode.
  • Analysis: here I just suggest to share your idea but not merge it because in :devel I added a new model in the analysis step that enable the search in free text form. I want to avoid that we change in 2 the same file for now.

Regarding Plex, full support would be ideal (playlists, analysis, etc.). From what I’ve seen, Plex doesn't allow downloading tracks for analysis, but if you’ve found a workaround, that would be excellent.

Before we move forward from moving the PR from draft to an actual one, I just ask that:

  • All new features either support every music server or are cleanly disabled where not supported.
  • If additional data needs to be stored, please create new tables rather than modifying existing ones. (Also, [FEEDBACK] Show more song tags in a dropdown list. #162 has ongoing work by @tysoncung on album information, so coordination would help.)
  • Test, test everything to avoid regression :)

Thanks again for your contribution, really appreciated!

@rendyhd
Copy link
Contributor Author

rendyhd commented Dec 8, 2025

Thanks for your commetns @NeptuneHub. How do you currently test? Do you have all media servers running? Currently I only have experience with Plex and Jellyfin (and Music Assistant running via Jellyfin)

btw, did you have a dev discord, or prefer everything via github. Really love this project

@NeptuneHub
Copy link
Owner

I’m kindly hosted in the Discord Server of the Jellify app (an amazing iOS/android client for jellyfin) where I have my AudioMuse-AI channel:
https://discord.gg/jellify

You can definitely find me there!

About test:

  • emby: I don’t had, was from a contributor;
  • Jellyfin / Navidrome like: I have;
  • Lyrion : I had on my old homelab, I need to reinstall.

So basically yes, you add to install all and test. Especially when you change the media server API you need to retest all.

I’m trying to implement more test, but are mainly unit test and don’t has big chance to find if you call the media server bad. So here the secret is:

  • change less possible;
  • do a good error handling in the code;
  • if you change an API call to the media server you had to retest ALL the functionality of AudioMuse-AI.

I would like to get a VM in cloud strong enough, also to do some integration test on ALL the music server. But we need one big enough and start to have a cost. Being an opensource project without funds I preferred to avoid.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants