Display Original Filenames in Jellyfin

Preface

The recommended usage of Jellyfin is that users create folders according to the media rules and place media files in them. After that, the media titles are automatically generated based on the metadata obtained from the scraper. However, this rule is so compulsory that this simple functionality of using the original file name as the title is not even available. While manual updating media titles is possible, it can be cumbersome.

To fit this demand, I have created a script using jellyfin-apiclient-python to batch rename all media in a specific media library. Additionally, this article explores some previous solutions, none of which were satisfactory in my opinion.

Existing Solution 1

When creating a media library, choose ‘Music Videos’ as its content type and select ‘Prefer embedded titles over filenames’.

What is this “embedded title”? Open the ‘Properties’ of a video and go to ‘Details’.

image-20240217135326419

Any content in the ‘Title’ field will be displayed as the media title in Jellyfin without any modifications. However, this approach has two issues:

1️⃣ For most anime published, the values of their ‘Title’ are their series names, as shown in the image, lacking episode numbers, making it hard for me to distinguish.

This issue can be easily solved by copying the file name to ‘Title’ or clearing the ‘Title’ field. In either case, the original filename will be displayed eventually. For automation in Python, the mutagen module is handy to use.

2️⃣ Media libraries of type ‘Music Videos’ cannot display folder structures, which I find unacceptable. In fact, only ‘Mixed Movies and Shows’ will be presented in a pure folder format.

Existing Solution 2

Directly modify the database, as referenced in ‘Manually Correcting Titles to File (Folder) Names’

Bypassing the Service Tier to directly manipulate the database is too risky. I will never use this approach.

My Solution

Since directly manipulating the database in Solution 2 is bad, why not use the Jellyfin API?

The first step is to find which API corresponds to the required functionality. Instead of referring to the official documentation first, inspect the browser’s network traffic in Developer tools and then refer to the documentation. However, in most cases, the documentation is still useless, because there is no description. Under such circumstances, we need perform experiments to guess the usage of an API.

Fortunately, jellyfin-apiclient-python provides a ready-made API, eliminating the need to start from requests. I quickly completed the script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
from jellyfin_apiclient_python import JellyfinClient
from jellyfin_apiclient_python.api import API


def rename_to_filename(jellyfin: API, item_id: str):
metadata: dict = jellyfin.get_item(item_id)
assert metadata['Id'] == item_id

assert len(metadata['MediaSources']) == 1
path: str = metadata['MediaSources'][0]['Path']
filename = path.split('/')[-1]

# Only modify Name, keep other info unchanged
metadata.update({'Name': filename})
return jellyfin.items('/' + item_id, action='POST', params=None, json=metadata)


def rename_items_in_library(jellyfin: API, library_id: str):
# get_items_by_letter recursively retrieves elements in all subfolders
res = jellyfin.get_items_by_letter(parent_id=library_id)
res = res['Items']
item_count = 0
for r in res:
if r['Type'] == 'Folder':
continue
rename_to_filename(jellyfin, r['Id'])
item_count += 1

print(f'total renamed item count: {item_count}')


client = JellyfinClient()
# Modify these client infos as needed; it doesn't affect the result
client.config.app('pycharm', '0.0.1', 'pycharm', 'kufhskdf')
client.config.data["auth.ssl"] = True
client.authenticate({"Servers": [
{
"AccessToken": "xxx", # Create one in 'Dashboard | API Keys'
"address": "zzz", # Jellyfin server address
"DateLastAccessed": 0,
"UserId": "yyy" # This user should have the privilege to manage media library
}
]}, discover=False)

print(client.logged_in)

rename_items_in_library(client.jellyfin, 'uuu') # Fill in the media library ID

By the way, the documentation for this module is also poor; I only figured out how to connect to the server through Issues.

My Jellyfin server’s certificate is self-signed, and it seems Python’s SSL cannot use the certificates installed on OS. We can resolve this by setting the environment variable REQUESTS_CA_BUNDLE=<certificate_path>.

My solution perfectly addresses the drawbacks of the two aforementioned solutions.

References