Category: Jellyfin

Jellyfin – Migrating Users

I’m moving from a Windows based instance of Jellyfin to a containerized instance within CasaOS, and I wanted to preserve user data (including view history). Here’s how I did it:

  • Confirm both your source and destination Jellyfin are the same version
  • Export the UserDatas table from library.db for your source instance. You can use DB Browser for SQLite to achieve this – remember to check “Column names in first line”
  • On your destination server, make a backup of library.db and jellyfin.db
  • Again using DB Browser, open the library.db of your destination server. Drop the UserDatas table and import csv created in the prior step to recreate the table (remember to check that the first line contains the column names)
  • Copy jellyfin.db from your source server and overwrite the db from the destination with it. This is important, as this file contains user history data
  • Fire your new Jellyfin instance up and attempt to log in with an existing user

 

CasaOS – Tinkering

Somewhere in my intertoobs wanderings I came across CasaOS and, given I had an idle Pi 4 laying around, I decided to poke at it. After all, if it works worth a damn it could help consolidate all the disparate systems I have running locally.

CasaOS is basically a slick Docker manager that rides atop another OS. Getting it up and running on the Pi with a fresh Raspbian install was painless. Simple configs, like mounting network shares, is a breeze. So far I have the following running in it:

  • PiHole – Installed without a hitch. If this runs well it’ll replace the standalone PiHole Pi 3 I have running.
  • Calibre Web – Also installed without a hitch. Love this, because I hate running the Calibre thick client full time on my server simply for its web interface. Not a lot of instructions on this one – just make sure you have your library mounted and defined as a volume in the container settings.
  • Jellyfin – Another painless install (make sure to mount your files volume as described in the above Calibre Web settings). I installed this as a replacement for my current Jellyfin music server, which runs standalone in a fully fledged VM, gobbling unnecessary resources. But I stopped it midway through indexing my gajillion files because I discovered:
  • Navidrome – Will it be better than Jellyfin for audio? I don’t know, but I’m giving it a shot.  Currently still indexing – on directory number 12406. Heh. Now, Navidrome wouldn’t run initially, and CasaOS kept screaming that it was unhealthy. Its log filled with “exec /app/navidrome: exec format.” I discovered that the image I was pulling isn’t the most recent. I exported the ComposeFile from within the settings of the failed install, uninstalled it, and updated the image source in the ComposeFile to point to “ghcr.io/navidrome/navidrome:develop.” I then imported the file (Custom Install > Import from within the App Store) and it installed fine
  • Memos – Completely painless install. Came across this randomly and figured maybe it’d replace my TiddlyWiki instance running on my server. We’ll see.
  • Mealie – I ran across this neat app via some Youtubers Apps of The Year vid and was intrigued. An app that’ll scrape a online recipe page, pull the pertinent details of the recipe and ditch all the ads and fluff? Yes please! However, Mealie wasn’t in the default app store for CasaOS. I found CoolStore for Casa and added it as a source. From there Mealie installed no problem, and now I have a slew of other apps to sift through as well. Perhaps Casa can even replace my standalone VPN Pi. We shall see.

Jellyfin as a Music Server – Duplicates

Updated query for better detail!

1
2
3
4
5
6
7
8
9
10
11
12
SELECT a.artists,a.album,a.IndexNumber,a.name,a.path
FROM TypedBaseItems a
JOIN (SELECT name, album, IndexNumber
FROM TypedBaseItems
WHERE album IS NOT NULL
AND IsFolder = 0
GROUP BY name, album, IndexNumber
HAVING COUNT(*) > 1 ) b
ON a.name = b.name
AND a.album = b.album
AND a.IndexNumber = b.IndexNumber
ORDER BY a.artists, a.album, a.IndexNumber, a.name

I run 2 Jellyfin servers – one for video, and one for music. In the world of streaming I’m old school in that I still curate a huge library of audio files. I don’t like being at the whim of streaming services, I don’t like how they treat artists, and I don’t like how I’m limited to artists on their platforms. I listen to a lot of obscure music across nearly all genres, and quite a bit of it can’t be found on *any* streaming service.

Jellyfin isn’t the perfect solution for a music server, but so far it’s the best I’ve found. Admittedly I may be biased due to my familiarity with the product, but every time I come across an alternative I give it a go only to wind up back at Jellyfin. Over the course of decades I’ve wound up with many duplicates in my library and, because often they aren’t identical in name or size, it’s not easy to identify them. The other day, as I saw yet another double listing for an album in Jellyfin, it dawned on me: Jellyfin knows these are dupes. Can I leverage it to my advantage?

Indeed I can.

First you’ll need DB Browser for SQLite. It’s free. Then you’ll want to locate your database file for Jellyfin. I’m running on Windows, and my path is

C:\Users\USERNAME\AppData\Local\Jellyfin\data\library.db

For the purpose of learning, I recommend making a copy of this file elsewhere to tinker with. If you accidentally change data in it, you could sink yourself.  Everything happening below is strictly reading data, not manipulating, but still. You’ll have to shut Jellyfin down to access this file in DB Browser. Open it up, head to the Execute SQL tab, slap this query in, and execute it.

1
2
3
4
5
6
7
8
9
10
SELECT a.artists,a.album,a.name,a.path
FROM TypedBaseItems a
JOIN (SELECT name, album
FROM TypedBaseItems
WHERE album IS NOT NULL
GROUP BY name, album
HAVING COUNT(*) > 1 ) b
ON a.name = b.name
AND a.album = b.album
ORDER BY a.name

This will return you a comma delimited list of dupes. It’s keying off of song title and album title. Mind you, it’s not perfect. It’s going to find dupes that aren’t here and there, especially on boxed sets and compilations where there might be multiple takes of the same tune. You could obviously add in track number (IndexNumber in the database) and leverage IsFolder to skip directory names (1 is yes, 0 is no), but for my purposes the above gave me accurate enough data to sort in a Google spreadsheet and start hacking away at my duplicates.