Script-Time: Dateien für Mediaserver umbenennen

Automatisierte Filmunbenennung via TMDB API für Kodi und Jellyfin

Script-Time: Dateien für Mediaserver umbenennen
Photo by Mohammad Rahmani / Unsplash

Der folgende Artikel beschreibt ein Bash-Skript, das Videodateien automatisch umbenennt, indem es aus dem Dateinamen einen Suchbegriff extrahiert und über die TMDB API den korrekten Filmtitel ermittelt. Anschließend wird die Datei auf Basis der Auswahl umbenannt. Einen ähnlichen Artikel habe ich bereits für Film-Serien geschrieben, da mir das Einlegen meiner Blueray-Disks langsam die Nerven strapazierte:

Script-Time: Optimale Dateinamen für Jellyfin
Vorschläge für Mediendateien leicht gemacht

Überblick und Funktionsweise

Das Skript automatisiert den Umbenennungsprozess von Videodateien für Medienserver wie Kodi und Jellyfin.

Es durchsucht das aktuelle Verzeichnis nach Videodateien, ermöglicht die Auswahl über ein dialogbasiertes Menü, erstellt eine Suchanfrage aus dem Dateinamen, ruft passende Filmtitel über die TMDB API ab und benennt die Datei entsprechend um. Somit wählen die Parser von KODI, XBMC, Plex oder auch Jellyfin für die Meta-Informationen immer die korrekten Titel aus:

Auswahl und Verarbeitung der Videodateien

Zunächst wird mittels des Befehls find eine Liste der relevanten Videodateien (z. B. .mp4, .mkv, .avi, .mpg) im aktuellen Verzeichnis erstellt. Die Dateien werden zeilenweise in ein Array eingelesen, sodass sie später im Auswahlmenü zur Verfügung stehen. Ist das Array leer, wird eine Meldung ausgegeben und das Skript pausiert, um dem Nutzer die Möglichkeit zu geben, das Problem zu erkennen.

# Erstellen einer Liste der Videodateien
video_files=()
while IFS= read -r -d '' file; do
    video_files+=("$file")
done < <(find . -maxdepth 1 -type f \( -iname "*.mp4" -o -iname "*.mkv" -o -iname "*.avi" -o -iname "*.mpg" \) -print0)

Dialog-basierte Auswahl und Ausgabe

Das Tool dialog wird genutzt, um eine übersichtliche Menügesteuerte Auswahl der gefundenen Videodateien bereitzustellen. Hierbei werden Parameter wie Höhe, Breite und die Anzahl der Optionen dynamisch angepasst. Nach der Auswahl wird der Name der gewählten Datei ausgegeben und der nächste Verarbeitungsschritt eingeleitet.

# Menü-Optionen vorbereiten und Dialog starten
menu_options=()
for i in "${!video_files[@]}"; do
    menu_options+=($i "${video_files[$i]}")
done

file_choice=$(dialog --clear \
                --backtitle "Dateiauswahl" \
                --title "Wähle eine Video-Datei" \
                --menu "Verfügbare Dateien:" \
                $dialog_height $dialog_width $dialog_choice_height \
                "${menu_options[@]}" \
                2>&1 >/dev/tty)

Erstellung der Suchanfrage

Nach der Dateiauswahl wird der Dateiname weiterverarbeitet, um einen sinnvollen Suchbegriff zu generieren. Dieses Script habe ich auf meinem KODI-Server entwickelt. Mittels sed werden überflüssige Informationen wie Dateiendungen, Jahreszahlen und Sonderzeichen entfernt. Gleichzeitig erfolgt eine Überprüfung, ob ein API-Schlüssel in der Kodi-Konfiguration vorhanden ist; falls nicht, wird ein Standardwert gesetzt.

# Dateiinformationen extrahieren und Suchanfrage erstellen
selected_file="${video_files[$file_choice]}"
file_basename="$(basename "$selected_file" | sed -e 's/\..*//')"
file_extension="$(basename "$selected_file" | sed -e 's/.*\.//')"
search_query=$(echo "$file_basename" | sed -E 's/([0-9]{4}).*/\1/' | sed -E 's/[\._%\/]/ /g;s/[0-9-]//g')

# API-Key extrahieren oder Standardwert verwenden
api_key=$(grep -Eo "api_key=[0-9a-f]*" /home/osmc/.kodi/addons/metadata.themoviedb.org/tmdb.xml 2> /dev/null | sort -u)
api_key=${api_key:-f090bb54758cabf231fb605d3e3e0468}

Filmtitelsuche via TMDB API

Mit dem erstellten Suchbegriff wird über wget eine HTTP-Anfrage an die TMDB API gestellt. Die Rückgabe, im JSON-Format, wird mithilfe von jq verarbeitet, um die relevanten Informationen (Filmtitel und Veröffentlichungsdatum) zu extrahieren. Das Ergebnis wird formatiert und in einem weiteren Dialog-Menü angezeigt, sodass der korrekte Filmtitel ausgewählt werden kann.

# Suche nach passenden Filmtiteln über die TMDB API
movie_names=()
while read movie_info; do
    movie_names+=("$movie_info")
done < <(wget -qO - --header="Accept: application/json; charset=UTF-8" \
    "http://api.themoviedb.org/3/search/movie?query=$(echo $search_query | sed -e 's/_/+/g;s/ /+/g')&api_key=${api_key}&language=de" \
    | jq -r '.results[] | "\(.title)|\(.release_date)"' \
    | sed -e 's/ /_/g;s/\:/_-/;s/|/ /;s/ \(....\)-..-../_\(\1\)/' \
    | sort )

Umbenennung der Datei

Wurde ein Filmtitel ausgewählt, erfolgt die Umbenennung der ursprünglichen Datei. Dabei wird der gewählte Titel als neuer Dateiname übernommen und die ursprüngliche Dateiendung beibehalten. Der Befehl mv setzt die Umbenennung um, und eine Bestätigung wird über eine Konsolenausgabe angezeigt.

# Datei umbenennen, falls eine Auswahl getroffen wurde
if [ -n "$name_choice" ]; then
    new_filename="${movie_names[$name_choice]}"
    mv "$selected_file" "${new_filename}.${file_extension}"
    echo "Datei wurde umbenannt in: ${new_filename}.${file_extension}"
else
    echo "Keine Umbenennung vorgenommen."
fi

Das ganze Script

Nach der Erklärung der einzelnen Aufgaben kommt hier nun das ganze Script, das man in dem Verzeichnis aufrufen sollte, wo die anzupassenden Medien liegen:

moviequery(){
# Erstellen einer Liste der .mkv und .mp4 Dateien im aktuellen Verzeichnis
video_files=()
while IFS= read -r -d '' file; do
    video_files+=("$file")
done < <(find . -maxdepth 1 -type f \( -iname "*.mp4" -o -iname "*.mkv" -o -iname "*.avi" -o -iname "*.mpg" \) -print0)

# Überprüfen, ob Video-Dateien vorhanden sind
if [ ${#video_files[@]} -eq 0 ]; then
    echo "Keine .mkv oder .mp4 Dateien im aktuellen Verzeichnis gefunden."
    sleep 5
fi

# Variablen für dialog
dialog_height=15
dialog_width=60
dialog_choice_height=${#video_files[@]}
dialog_backtitle="Dateiauswahl"
dialog_title="Wähle eine Video-Datei"
dialog_menu="Verfügbare Dateien:"

# Menü-Optionen vorbereiten
menu_options=()
for i in "${!video_files[@]}"; do
    menu_options+=($i "${video_files[$i]}")
done

# Dialog starten und die Auswahl speichern
file_choice=$(dialog --clear \
                --backtitle "$dialog_backtitle" \
                --title "$dialog_title" \
                --menu "$dialog_menu" \
                $dialog_height $dialog_width $dialog_choice_height \
                "${menu_options[@]}" \
                2>&1 >/dev/tty)

clear

# Wenn eine Auswahl getroffen wurde, zeige sie an
if [ -n "$file_choice" ]; then
    echo "Ausgewählte Datei: ${video_files[$file_choice]}"
else
    echo "Keine Auswahl getroffen."
    sleep 5
fi

# Originaldatei und Dateiinformationen extrahieren
selected_file="${video_files[$file_choice]}"
file_basename="$(basename "$selected_file" | sed -e 's/\..*//')"  # Name ohne Extension
file_extension="$(basename "$selected_file" | sed -e 's/.*\.//')"  # Nur die Extension
search_query=$(echo "$file_basename" | sed -E 's/([0-9]{4}).*/\1/' | sed -E 's/[\._%\/]/ /g;s/[0-9-]//g')

echo "Suchanfrage: $search_query"

# API-Key extrahieren oder Standardwert verwenden
api_key=$(grep -Eo "api_key=[0-9a-f]*" /home/osmc/.kodi/addons/metadata.themoviedb.org/tmdb.xml 2> /dev/null | sort -u)
api_key=${api_key:-f090bb54758cabf231fb605d3e3e0468}  # Standard-API-Schlüssel falls nicht vorhanden

# Suche nach passenden Filmtiteln über die TMDB API
movie_names=()
while read movie_info; do
    movie_names+=("$movie_info")
done < <(wget -qO - --header="Accept: application/json; charset=UTF-8" \
    "http://api.themoviedb.org/3/search/movie?query=$(echo $search_query | sed -e 's/_/+/g;s/ /+/g')&api_key=${api_key}&language=de" \
    | jq -r '.results[] | "\(.title)|\(.release_date)"' \
    | sed -e 's/ /_/g;s/\:/_-/;s/|/ /;s/ \(....\)-..-../_\(\1\)/' \
    | sort )

# Überprüfen, ob Video-Dateien vorhanden sind
if [ ${#movie_names[@]} -eq 0 ]; then
    echo "Keine .mkv oder .mp4 Dateien im aktuellen Verzeichnis gefunden."
    sleep 5
fi

# Menüoptionen für gefundene Filmtitel
movie_menu_options=()
for i in "${!movie_names[@]}"; do
    movie_menu_options+=($i "${movie_names[$i]}")
done

# Dialog starten und die Filmauswahl speichern
name_choice=$(dialog --clear \
                --backtitle "$selected_file" \
                --title "Wähle den neuen Namen" \
                --menu "Gefundene Namen:" \
                $dialog_height $dialog_width $dialog_choice_height \
                "${movie_menu_options[@]}" \
                2>&1 >/dev/tty)

clear

# Datei umbenennen, falls eine Auswahl getroffen wurde
if [ -n "$name_choice" ]; then
    new_filename="${movie_names[$name_choice]}"
    mv "$selected_file" "${new_filename}.${file_extension}"
    echo "Datei wurde umbenannt in: ${new_filename}.${file_extension}"
else
    echo "Keine Umbenennung vorgenommen."
fi
}

Fazit

Wenn makemkv_con mal wieder keine sinnvollen Informationen von der Blueray-Disk bekommen konnte, ist dies ein extrem leichter Weg, um seine Dateien den Namenskonventionen von KODI&Co. anzupassen.