Zum Inhalt springen

Script fehlende Serienepisoden ermitteln

Aus LHlab Wiki

Mit folgendem Script lassen sich fehlende Episoden einer Serie ermitteln. Hierzu wird das lokale Verzeichnis gegen die TheMovieDB API geprüft und abgeglichen. Der TMDB API Key muss unter ~/tmdb.key abgelegt sein.

Es wird zuerst versucht über den aktuellen Verzeichnisnamen sowie ggf. vorhandener tvshow.nfo (inkl. YEAR Element) die Serie zu ermitteln. Sollten mehrere Ergebnisse bei TMDB gefunden werden, erfolgt eine Auswahl:

# Suche mit Ordnernamen; ergibt mehrere Treffer mit manueller ID Abfrage
root@media-cleaner:/mnt/uncleaned/tvshows/How I Met Your Mother# ~/missing_episodes.sh 
Serienname: How I Met Your Mother
TMDb Suchergebnisse:
1100: How I Met Your Mother (2005)
85267: How I Met Your Mother (2010)
Bitte die ID der gewünschten Serie eingeben:

# -------------------------------------------------------------------------------------------------
# Suche mit Erscheinungsjahr aus der lokalen tvshow.nfo; ergibt nur einen Treffer
# und wird automatisch ausgewählt

root@media-cleaner:/mnt/uncleaned/tvshows/How I Met Your Mother# ~/missing_episodes.sh 
Serienname: How I Met Your Mother
Jahr gefunden: 2005
Ein Ergebnis gefunden, automatisch gewählt: ID 1100
=== Season 1 (22 von 22 Episoden) ===
Ep      Titel                                              Status MediaInfo
--------------------------------------------------------------------
1x1     Verliebt, verlobt, versagt                             720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x2     Die lila Giraffe                                       720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x3     Frauen, Flieger, Freiheit                              720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x4     Gutes altes Hemd                                       720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x5     Von Tänzern und Tauben                                 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x6     Die Kürbis-Schlampe                                    720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x7     Kakerlake liebt Maus                                   720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x8     Das Duell                                              720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x9     Wohltaten und Untaten                                  720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x10    Der Ananas-Vorfall                                     720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x11    Silvesterlaune                                         720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x12    Hochzeitsgast plus eins                                720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x13    Traum und Wirklichkeit                                 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x14    Nur nichts überstürzen                                 720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x15    Spieleabend                                            720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x16    Maßgeschneidert                                        720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x17    Leben unter Gorillas                                   720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x18    Der Anständige                                         720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x19    Eine nette Nutte                                       720 (AVC) (mkv) | de: AC-3 2en: AC-3 6
1x20    Nur zwei Monate                                        
1x21    Das Super-Date                                         
1x22    Letzter Versuch                                    
#!/bin/bash
TMDB_KEY=$(<~/tmdb.key)
CURRENT_PATH=$(pwd)
EXTENSIONS=("mp4" "mkv" "avi" "mov" "flv" "wmv" "m4v" "mpeg" "mpg")

# Serienname oder TMDb-ID
if [[ "$CURRENT_PATH" =~ \{tmdb-([0-9]+)\} ]]; then
    TMDB_ID="${BASH_REMATCH[1]}"
    echo "TMDb-ID im Ordner gefunden: $TMDB_ID"
else
    SERIES_NAME=$(basename "$CURRENT_PATH")
    YEAR=""
    if [[ -f "tvshow.nfo" ]]; then
        YEAR=$(xmllint --xpath 'string(/tvshow/year)' tvshow.nfo 2>/dev/null)
        TITLE=$(xmllint --xpath 'string(/tvshow/title)' tvshow.nfo 2>/dev/null)
        [[ -n "$TITLE" ]] && SERIES_NAME="$TITLE"
    fi
    echo "Serienname: $SERIES_NAME"
    [[ -n "$YEAR" ]] && echo "Jahr gefunden: $YEAR"

    SEARCH_URL="https://api.themoviedb.org/3/search/tv?api_key=$TMDB_KEY&query=$(echo "$SERIES_NAME" | sed 's/ /%20/g')"
    [[ -n "$YEAR" ]] && SEARCH_URL+="&first_air_date_year=$YEAR"

    TMDB_SEARCH=$(curl -s "$SEARCH_URL")
    RESULTS_COUNT=$(echo "$TMDB_SEARCH" | jq '.total_results // 0')

    if [[ "$RESULTS_COUNT" -eq 0 ]]; then
        echo "❌ Keine Serie gefunden."
        exit 1
    elif [[ "$RESULTS_COUNT" -eq 1 ]]; then
        TMDB_ID=$(echo "$TMDB_SEARCH" | jq -r '.results[0].id')
        echo "Ein Ergebnis gefunden, automatisch gewählt: ID $TMDB_ID"
    else
        echo "TMDb Suchergebnisse:"
        echo "$TMDB_SEARCH" | jq -r '.results[] | "\(.id): \(.name) (\(.first_air_date[0:4]))"'
        read -rp "Bitte die ID der gewünschten Serie eingeben: " TMDB_ID
    fi
fi

# Staffeln holen
SERIES=$(curl -s "https://api.themoviedb.org/3/tv/$TMDB_ID?api_key=$TMDB_KEY&language=de")
SEASONS=$(echo "$SERIES" | jq -c '.seasons[]?')

echo "--------------------------------------"
while IFS= read -r SEASON; do
    SEASON_NUM=$(echo "$SEASON" | jq -r '.season_number')
    SEASON_NAME="Season $SEASON_NUM"

    # Episoden abrufen
    SEASON_JSON=$(curl -s "https://api.themoviedb.org/3/tv/$TMDB_ID/season/$SEASON_NUM?api_key=$TMDB_KEY&language=de")
    TOTAL_EPS=$(echo "$SEASON_JSON" | jq '.episodes | length // 0')
    LOCAL_COUNT=$(find . -type f -iname "*S$(printf "%02d" "$SEASON_NUM")E*.*" | wc -l | tr -d ' ')

    echo "=== $SEASON_NAME ($LOCAL_COUNT von $TOTAL_EPS Episoden) ==="
    printf "%-7s %-50s %-6s %s\n" "Ep" "Titel" "Status" "MediaInfo"
    printf "%s\n" "--------------------------------------------------------------------"

    if [[ "$TOTAL_EPS" -eq 0 ]]; then
        continue
    fi

    EPISODES=$(echo "$SEASON_JSON" | jq -c '.episodes[]?')
    echo "$EPISODES" | while IFS= read -r EP; do
        EP_NUM=$(echo "$EP" | jq -r '.episode_number // 0')
        EP_NAME=$(echo "$EP" | jq -r '.name // "Unknown"')
        STATUS="❌"
        MI=""

        # Datei suchen
        FILE=""
        for ext in "${EXTENSIONS[@]}"; do
            MATCH=$(find . -type f -iname "*S$(printf "%02d" "$SEASON_NUM")E$(printf "%02d" "$EP_NUM")*.$ext" | head -n1)
            if [[ -n "$MATCH" ]]; then
                FILE="$MATCH"
                STATUS="✅"
                break
            fi
        done
        

        # MediaInfo kompakt
        if [[ -n "$FILE" ]]; then
            VID=$(mediainfo --Inform="Video;%Height% (%Format%)" "$FILE" 2>/dev/null)
            EXT=$(echo "$FILE" | awk -F. '{print $NF}')
            AUDIO_LINES=$(mediainfo --Inform="Audio;%Language%: %Format% %Channel(s)%" "$FILE" 2>/dev/null)
            AUDIO=""
            if [[ -n "$AUDIO_LINES" ]]; then
                while IFS= read -r line; do
                    LANG=$(echo "$line" | cut -d: -f1)
                    VAL=$(echo "$line" | cut -d: -f2- | xargs)
                    AUDIO+="$LANG: $VAL | "
                done <<< "$AUDIO_LINES"
                AUDIO=${AUDIO::-3}
            fi
            MI="$VID ($EXT) | $AUDIO"
        fi

        printf "%-7s %-50s %-6s %s\n" "${SEASON_NUM}x${EP_NUM}" "$EP_NAME" "$STATUS" "$MI"
    done
done <<< "$SEASONS"