Releases: kamilkosek/jellyplist
Release v0.1.9
Whats up in Jellyplist v0.1.9?
⚠️ BREAKING CHANGE: docker-compose.yml
Warning
In this release I´ve done some rework so now the setup is a bit easier, because you don´t have to spin up the -worker -beat container, these are now all in the default container and managed via supervisor. This means you have to update your docker-compose.yml
when updating!
So now your compose file should look more or less like this
services:
redis:
image: redis:7-alpine
container_name: redis
volumes:
- redis_data:/data
networks:
- jellyplist-network
postgres:
container_name: postgres-jellyplist
image: postgres:17.2
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
PGDATA: /data/postgres
volumes:
- /jellyplist_pgdata/postgres:/data/postgres
networks:
- jellyplist-network
restart: unless-stopped
jellyplist:
container_name: jellyplist
image: ${IMAGE}
depends_on:
- postgres
- redis
ports:
- "5055:5055"
networks:
- jellyplist-network
volumes:
- /jellyplist/cookies.txt:/jellyplist/cookies.txt
- /jellyplist/open.spotify.com_cookies.txt:/jellyplist/spotify-cookie.txt
- ${MUSIC_STORAGE_BASE_PATH}:${MUSIC_STORAGE_BASE_PATH}
- /my/super/cool/storage/jellyplist/settings.yaml:/jellyplist/settings.yaml
env_file:
- .env
networks:
jellyplist-network:
driver: bridge
volumes:
postgres:
redis_data:
And the .env
File
IMAGE = ghcr.io/kamilkosek/jellyplist:latest
POSTGRES_USER = jellyplist
POSTGRES_PASSWORD = jellyplist
SECRET_KEY = supersecretkey # Secret key for session management
JELLYFIN_SERVER_URL = http://<jellyfin_server>:8096 # Default to local Jellyfin server
JELLYFIN_ACCESS_TOKEN = <jellyfin access token>
JELLYFIN_ADMIN_USER = <jellyfin admin username>
JELLYFIN_ADMIN_PASSWORD = <jellyfin admin password>
SPOTIFY_CLIENT_ID = <spotify client id>
SPOTIFY_CLIENT_SECRET = <spotify client secret>
JELLYPLIST_DB_HOST = postgres-jellyplist
JELLYPLIST_DB_USER = jellyplist
JELLYPLIST_DB_PASSWORD = jellyplist
LOG_LEVEL = INFO
LIDARR_API_KEY = <lidarr api key>
LIDARR_URL = http://<lidarr server>:8686
LIDARR_MONITOR_ARTISTS = false
SPOTIFY_COOKIE_FILE = '/jellyplist/spotify-cookie.txt'
MUSIC_STORAGE_BASE_PATH = '/storage/media/music'
🆕 Log Viewer
Under the Admin
Page there is now a tab called Logs
from where you can view the current logs, change the log-level on demand and copy a prepared markdown snippet ready to be pasted into a GitHub issue.
🆕 New env var´s, a bit more control over spotDL
SPOTDL_PROXY
Set a Proxy for spotDL. See https://spotdl.readthedocs.io/en/latest/usage/#command-line-options
SPOTDL_OUTPUT_FORMAT
Set the output folder and file name format for downloaded tracks via spotDL. Not all variables, which are supported by spotDL are supported by Jellyplist.
{title}
{artist}
{artists}
{album}
This way you will have a bit more controler over how the files are stored.
The complete output path is joined from MUSIC_STORAGE_BASE_PATH
and SPOTDL_OUTPUT_FORMAT
Example:
MUSIC_STORAGE_BASE_PATH = /storage/media/music
and
SPOTDL_OUTPUT_FORMAT = /{artist}/{album}/{title}
The Track is All I Want for Christmas Is You by Mariah Carey this will result in the following folder structure:
/storage/media/music/Mariah Carey/Merry Christmas/All I Want for Christmas Is You.mp3
🆕 Admin Users can now add Playlists to multiple Users
Sometimes I want to add a playlist to several users at once, because it´s either a generic one or because my wife doesn´t want to bother with the technical stuff 😬
So now, when logged in as an admin user, when adding a playlist you can select users from your Jellyfin server which will also receive it.
Under Admin
you can also select users which will be preselected by default. These will be stored in the file settings.yaml
.
You can or should map this file to a file outside the container, so it will persist accross image updates (see compose sample above)
🆕 New env
var QUALITY_SCORE_THRESHOLD
Get a better control over the update_jellyfin_id_for_downloaded_tracks()
behaviour.
Until now this tasks performed a full update every 24h: This means, every track from every playlist was searched through the Jellyfin API with the hope of finding the same track but with a better quality. While this is ok and works fine for small libraries, this tasks eats a lot of power on large libraries and also takes time.
So there is now the new env
variable QUALITY_SCORE_THRESHOLD
(default: 1000.0
). When a track was once found with a quality score above 1000.0, Jellyplist wont try to perform another quality update
anymore on this track.
In order to be able to classify it a little better, here are a few common quality scores:
- spotDL downloaded track without yt-music premium:
< 300
- spotDL downloaded track with yt-music premium:
< 450
- flac
> 1000
Tip
Want to know what quality score (and many other details) a track has ? Just double-click the table row in the playlist details view to get all the info´s!
Other changes, improvements and fixes
- Fix for #38 and #22 , where the manual task starting was missing a return value
- Fixed an issue where the content-type of a playlist cover image, would cause the Jellyfin API Client to fail. Thanks @artyorsh
- Fixed missing lock keys to task manager and task status rendering
- Pinned postgres version to 17.2
- Enhanced error logging in tasks
- several fixes and improvements for the Jellyfin API Client
What's Changed
- merge back by @kamilkosek in #34
- case-insensitive image formats by @artyorsh in #37
- Merge dev into main by @kamilkosek in #54
Full Changelog: 0.1.8...v0.1.9
dev Release v0.1.9
Whats up in Jellyplist v0.1.9?
⚠️ BREAKING CHANGE: docker-compose.yml
Warning
In this release I´ve done some rework so now the setup is a bit easier, because you don´t have to spin up the -worker -beat container, these are now all in the default container and managed via supervisor. This means you have to update your docker-compose.yml
when updating!
So now your compose file should look more or less like this
services:
redis:
image: redis:7-alpine
container_name: redis
volumes:
- redis_data:/data
networks:
- jellyplist-network
postgres:
container_name: postgres-jellyplist
image: postgres:17.2
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
PGDATA: /data/postgres
volumes:
- /jellyplist_pgdata/postgres:/data/postgres
networks:
- jellyplist-network
restart: unless-stopped
jellyplist:
container_name: jellyplist
image: ${IMAGE}
depends_on:
- postgres
- redis
ports:
- "5055:5055"
networks:
- jellyplist-network
volumes:
- /jellyplist/cookies.txt:/jellyplist/cookies.txt
- /jellyplist/open.spotify.com_cookies.txt:/jellyplist/spotify-cookie.txt
- ${MUSIC_STORAGE_BASE_PATH}:${MUSIC_STORAGE_BASE_PATH}
env_file:
- .env
networks:
jellyplist-network:
driver: bridge
volumes:
postgres:
redis_data:
And the .env
File
IMAGE = ghcr.io/kamilkosek/jellyplist:latest
POSTGRES_USER = jellyplist
POSTGRES_PASSWORD = jellyplist
SECRET_KEY = supersecretkey # Secret key for session management
JELLYFIN_SERVER_URL = http://<jellyfin_server>:8096 # Default to local Jellyfin server
JELLYFIN_ACCESS_TOKEN = <jellyfin access token>
JELLYFIN_ADMIN_USER = <jellyfin admin username>
JELLYFIN_ADMIN_PASSWORD = <jellyfin admin password>
SPOTIFY_CLIENT_ID = <spotify client id>
SPOTIFY_CLIENT_SECRET = <spotify client secret>
JELLYPLIST_DB_HOST = postgres-jellyplist
JELLYPLIST_DB_USER = jellyplist
JELLYPLIST_DB_PASSWORD = jellyplist
LOG_LEVEL = INFO
LIDARR_API_KEY = <lidarr api key>
LIDARR_URL = http://<lidarr server>:8686
LIDARR_MONITOR_ARTISTS = false
SPOTIFY_COOKIE_FILE = '/jellyplist/spotify-cookie.txt'
MUSIC_STORAGE_BASE_PATH = '/storage/media/music'
🆕 Log Viewer
Under the Admin
Page there is now a tab called Logs
from where you can view the current logs, change the log-level on demand and copy a prepared markdown snippet ready to be pasted into a GitHub issue.
🆕 New env var´s, a bit more control over spotDL
SPOTDL_PROXY
Set a Proxy for spotDL. See https://spotdl.readthedocs.io/en/latest/usage/#command-line-options
SPOTDL_OUTPUT_FORMAT
Set the output folder and file name format for downloaded tracks via spotDL. Not all variables, which are supported by spotDL are supported by Jellyplist.
{title}
{artist}
{artists}
{album}
This way you will have a bit more controler over how the files are stored.
The complete output path is joined from MUSIC_STORAGE_BASE_PATH
and SPOTDL_OUTPUT_FORMAT
Other changes, improvements and fixes
- Fix for #38 and #22 , where the manual task starting was missing a return value
- Fixed an issue where the content-type of a playlist cover image, would cause the Jellyfin API Client to fail. Thanks @artyorsh
- Fixed missing lock keys to task manager and task status rendering
- Pinned postgres version to 17.2
Full Changelog: 0.1.8...v0.1.9-dev-1b95f20
Release 0.1.8
Whats up in Jellyplist 0.1.8?
Not much this time, just some small fixes and one enhancement.
🆕Jellyplist now checks for updates
Jellyplist now checks the GitHub releases for new version.
If a new version is available, you will notice the small badge on the lower left will pulsate slighty, so you don´t miss any new release 😄
If you don´t like that Jellyplist is doing this, you can opt out by setting this env var in your .env
file
CHECK_FOR_UPDATES = false
Other changes, improvements and fixes
- Fix for #30 , where the output path for spotDL wasn´t created correctly
Release 0.1.7
Whats up in Jellyplist 0.1.7?
Major overhaul
I´ve been working the past week to make this project work again, after Spotify announced to deprecate the playlist discover API´s , which were a crucial part of this project.
I also took this opportunity at the same time to do a major overhaul, on how Jellyplist gathers data from a music provider. Music provider API implementations must now implement defined abstract classes to work with Jellyplist, think of it like plugins. Jellyplist now, in theory, can gather data from any music provider - just the plugins must be written. It also doesn´t matter, if it have 1,2 or 10 Music Providers to playlists. So stay tuned for more to come.
The next ones will be Deezer and YTM
After the providers will be implemented, I will at some point do the same with the media backend - so Jellyplist will be able to support other media backends like Navidrome, Plex, Emby and so on...
🆕New API Implementation for Spotify
As mentioned above, I needed a new way to get playlists.
Now, to get them , you don´t need an API Key to authenticate, you even don´t need to be authenticated at all. If you like to have Playlists recommended or created for you, you can use authentication via a cookie.
To do this, add a env var to you .env
file:
SPOTIFY_COOKIE_FILE = '/jellyplist/spotify-cookie.txt'
And map the cookie from your local filesystem to the container path you´ve set in the .env
file
...
...
volumes:
- /your/local/path/open.spotify.com_cookies.txt:${SPOTIFY_COOKIE_FILE}
...
...
🆕Lidarr integration is here
To enable the Lidarr integration add these to your .env
file
LIDARR_API_KEY = aabbccddeeffgghh11223344 # self explaining
LIDARR_URL = http://<your_lidarr_ip>:8686 # too
LIDARR_MONITOR_ARTISTS = false # If false, only the corresponding
# album will be set to monitored in lidarr, if true the whole artist
# will be set as monitored. Be careful in the beginning as you might
# hammer your lidarr instance and you indexers. Defaults to false
After you enabled Lidarr integration, make sure to go to "Admin -> Lidarr" and set the default quality profile and music root folder.
With the Lidarr integration you get a nice workflow:
- Add Playlist
- Playlist gets downloaded via SpotDL and is available after some time
- At some point (every hour on x:50) the requests to Lidarr are made.
- Lidarr gets all files.
- Once a day Jellyplist is doing a full update on all tracks, and searches for the same track but with a better quality profile.
⚠️ New required env var
Ensure to add MUSIC_STORAGE_BASE_PATH
to your .env
file.
MUSIC_STORAGE_BASE_PATH = '/storage/media/music' # The base path where
# your music library is located.
# Must be the same value as your music library in jellyfin
Other changes, improvements and fixes
- UI/UX: The index page now has content. From there you can directly drop a playlist link
- UI/UX: The Search bar now works with the new API implementation
- UI/UX: A new
Browse All
(per Music Provider) Page from where you can discover playlists - UI/UX: Check technical details on a track. Just doubleclick a row in the details view of a playlist.
- UI/UX: Allow to link a track even it´s not marked as downloaded.
- UI/UX: Reworked celery task management and the /admin/tasks UI
Release 0.1.6
Whats up in Jellyplist 0.1.6?
🆕Better Linking (in preparation for Lidarr integration)
During the link-task (update_jellyfin_id_for_downloaded_tracks)
, where Jellyplist tries to link a Spotify-Track-Id
to a Jellyfin-Track-Id
it performs now a search and tries to find a best match from the results also considering quality aspects of a file.
You can also make use of ffprobe
, so jellyplist get´s more detailed information about the quality profile of a file.
To use ffprobe
set the environment variable FIND_BEST_MATCH_USE_FFPROBE
to true
otherwise jellyplist will use quality information provided by the Jellyfin API.
Fixes #14
In the Debug logs it will look like this:
find_best_match_from_jellyfin() ] DEBUG - Quality score for track Smalltown Boy: 4410.866669999999 [/storage/media/music/Bronski Beat/The Age of Reason (2017)/CD 01/Bronski Beat - The Age of Reason - 05 - Smalltown Boy.flac]
find_best_match_from_jellyfin() ] DEBUG - Quality score for track Smalltown Boy: 4100.6 [/storage/media/music/Bronski Beat/The Age of Consent (1984)/CD 01/Bronski Beat - The Age of Consent - 06 - Smalltown Boy.flac]
find_best_match_from_jellyfin() ] DEBUG - Quality score for track Smalltown Boy: 3240.48 [/storage/media/music/__jellyplist/5vmRQ3zELMLUQPo2FLQ76x.mp3]
What´s the benefit?
Once a day, the task update_jellyfin_id_for_downloaded_tracks
will do a full update on all tracks. This way you can listen to tracks and make use of the playlists until Lidarr provides you the same track but with better audio quality.
🆕Added REFRESH_LIBRARIES_AFTER_DOWNLOAD_TASK
When setting the new environment variable REFRESH_LIBRARIES_AFTER_DOWNLOAD_TASK
to true
, jellyplist will trigger a music library update on your Jellyfin server, in case you dont have Realtime Monitoring
enabled on your Jellyfin library.
Fixes #10
🆕Removed cookies.txt requirement
No need to use cookies.txt
file to download tracks via spotDL
Important
Not using a cookies.txt file will limit the bitrate of downloaded tracks to 128kbit/s
📻
🆕Added LOG_LEVEL
Via the environment variable LOG_LEVEL
you can control the log output now. The default python log levels are available:
- CRITICAL
- FATAL
- ERROR
- WARNING
- INFO
- DEBUG
- NOTSET
🆕Added the possibility for admins to release task lock´s
When a task will crash or whatsoever , the lock won´t be released and you have to wait for it to expire until you can run it manually. Now you can release it manually, in case you need it.
Important
You must be logged in as an admin
🆕Added the possibility for admins to remove playlists completely
This way the playlist will be removed from "monitoring" and also be removed from jellyfin.
Important
You must be logged in as an admin
🆕Allow manual track re-linking
In case something went wrong and you want to assign another Jellyfin track to a Spotify-Track-Id you can do it now manually.
Just go to "View Playlist Details", in the table where the tracks are listed, hold the CTRL
Key while clicking on the Play from Jellyfin button. You will be presented with the search modal and can choose whatever track you like.
Fixex #13
🆕Added a badge on the lower left corner indicating the current version
⚒️Overall improvements in logging
Changed log format and also added debug logging where (I think) it´s appropriate.
🐛 Bugfixes
Release 0.1.5
Release 0.1.4
Release 0.1.3
What's Changed
- Merge dev into main by @kamilkosek in #1
- Merge 0.1.3 into main by @kamilkosek in #2
New Contributors
- @kamilkosek made their first contribution in #1
Full Changelog: 0.1.2...0.1.3
Release 0.1.2
Full Changelog: https://github.com/kamilkosek/jellyplist/commits/0.1.2