"""Enforce default Jellyfin user preferences via the API. Iterates all users and sets preferFmp4HlsContainer in their DisplayPreferences if not already enabled. Idempotent. """ import json import os import sys import time import urllib.request from pathlib import Path JELLYFIN_URL = os.environ.get("JELLYFIN_URL", "http://127.0.0.1:8096") def get_api_key(): cred_dir = os.environ["CREDENTIALS_DIRECTORY"] return Path(cred_dir, "jellyfin-api-key").read_text().strip() def api(method, path, data=None): url = f"{JELLYFIN_URL}{path}" sep = "&" if "?" in url else "?" url += f"{sep}api_key={get_api_key()}" body = json.dumps(data).encode() if data else None req = urllib.request.Request(url, data=body, method=method) if body: req.add_header("Content-Type", "application/json") with urllib.request.urlopen(req) as resp: if resp.status == 204: return None return json.loads(resp.read()) def wait_healthy(timeout=120): deadline = time.monotonic() + timeout while time.monotonic() < deadline: try: req = urllib.request.Request(f"{JELLYFIN_URL}/health") with urllib.request.urlopen(req, timeout=5) as resp: if resp.read().decode().strip() == "Healthy": return except Exception: pass time.sleep(2) print("Jellyfin did not become healthy in time", file=sys.stderr) sys.exit(1) # Preferences to enforce: (key, desired_value) DEFAULTS = [ ("preferFmp4HlsContainer", "true"), ] def main(): wait_healthy() users = api("GET", "/Users") if not users: print("No users found, nothing to do") return for user in users: user_id = user["Id"] name = user["Name"] prefs = api( "GET", f"/DisplayPreferences/usersettings?userId={user_id}&client=emby", ) custom = prefs.get("CustomPrefs", {}) changed = False for key, value in DEFAULTS: if custom.get(key) != value: custom[key] = value changed = True if not changed: print(f"{name}: already up to date") continue prefs["CustomPrefs"] = custom api( "POST", f"/DisplayPreferences/usersettings?userId={user_id}&client=emby", prefs, ) print(f"{name}: updated preferences") if __name__ == "__main__": main()