#!/bin/bash # Install dependencies: # sudo dnf install ffmpeg mkvtoolnix jq # tesseract tesseract-langpack-eng tesseract-langpack-deu # Konfiguration INPUT_DIR="$1" # Verzeichnis mit den MKV-Dateien OUTPUT_DIR="$2" # Verzeichnis für die komprimierten Dateien RF_VALUE=20 # Qualität (niedriger = bessere Qualität) AAC_BITRATE_DEFAULT="192k" # Standard-Bitrate für Stereo AAC-Tonspuren echo "Eingabeverzeichnis: $INPUT_DIR" echo "Ausgabeverzeichnis: $OUTPUT_DIR" audio_file=$(mktemp) map_file=$(mktemp) crop_file=$(mktemp) mkdir -p "$OUTPUT_DIR" # Schleife über alle MKV-Dateien for file in "$INPUT_DIR"/*.mkv; do # Dateiname ohne Verzeichnis und Erweiterung filename=$(basename -- "$file") name="${filename%.*}" echo "Verarbeite Datei: $filename" #JSON-Daten extrahieren JSON=$(mkvmerge -J "$file") ( for lang in "ger" "eng"; do # Spur-IDs extrahieren SPUR_IDS=$(echo "$JSON" | jq -r \ --arg lang "$lang" \ '.tracks[] | select(.type == "subtitles" and .codec == "HDMV PGS" and .properties.language == $lang) | .id') TEMP_DIR=$(mktemp -d) # Temporäres Verzeichnis für die Dateigrößenanalyse declare -A FILE_SIZES # Array für die Zuordnung von Spur-ID zu Dateigröße # Untertitel extrahieren und Dateigrößen ermitteln for ID in $SPUR_IDS; do OUTPUT_FILE="$TEMP_DIR/$lang.$ID.pgs" echo "Extrahiere Untertitel (Sprache: $lang) - Spur-ID: $ID" mkvextract tracks "$file" "$ID:$OUTPUT_FILE" if [[ -f "$OUTPUT_FILE" ]]; then FILE_SIZE=$(stat -c%s "$OUTPUT_FILE") # Größe der Datei in Bytes FILE_SIZES["$ID"]=$FILE_SIZE else echo "Fehler: Die Datei $OUTPUT_FILE wurde nicht extrahiert!" fi done # Sortiere Spur-IDs nach Dateigröße (aufsteigend) SORTED_IDS=$(for id in "${!FILE_SIZES[@]}"; do echo "$id ${FILE_SIZES[$id]}"; done | sort -k2 -n | awk '{print $1}') INDEX=0 for ID in $SORTED_IDS; do OUTPUT_FILE="$OUTPUT_DIR/${filename%.*}.$lang" # Benennung basierend auf der Indexposition nach der Sortierung if [ $INDEX -eq 0 ]; then # Kleinste Datei → "forced" OUTPUT_FILE="$OUTPUT_FILE.forced.pgs" elif [ $INDEX -eq $((${#SORTED_IDS[@]} - 1)) ]; then # Größte Datei → "hearing_impaired" (optional) OUTPUT_FILE="$OUTPUT_FILE.hi.pgs" else # Übrige Dateien → "regular" OUTPUT_FILE="$OUTPUT_FILE.pgs" fi # Überprüfen, ob die Datei existiert und umbenennen if [[ -f "$TEMP_DIR/$lang.$ID.pgs" ]]; then mv "$TEMP_DIR/$lang.$ID.pgs" "$OUTPUT_FILE" echo "Benenne Spur-ID $ID als $OUTPUT_FILE" else echo "Fehler: Die Datei für Spur-ID $ID existiert nicht!" fi INDEX=$((INDEX + 1)) done # Temporäres Verzeichnis entfernen rm -r "$TEMP_DIR" done ) & ( # Audio-Streams verarbeiten audio_options="" map_options="" audio_index=0 # Zählt die AAC-Audiospuren # Liste für Tonspuren pro Sprache declare -A audio_tracks # Ausgabe der gesamten ffmpeg-Informationen über Audio-Streams echo "Extrahiere Audio-Streams für $filename:" audio_info=$(ffmpeg -analyzeduration 200000000 -probesize 100000000 -i "$file" 2>&1 | grep "Audio") # Analysiere die Track-Informationen while IFS= read -r track_info; do echo "Track info: $track_info" index=$(echo "$track_info" | grep -oP '(?<=Stream #0:)\d+') codec=$(echo "$track_info" | grep -oP '(?<=Audio: )[^ ,]+') lang=$(echo "$track_info" | awk -F'[()]' '{print $2}') bitrate=$(echo "$track_info" | grep -oP '\d{3,4} kb/s' | grep -oP '\d+' || echo "0") channels=$(echo "$track_info" | grep -oP '\d+\.\d+') channel_layout=$(echo "$track_info" | grep -oP '\d+\.\d+\(.*?\)' | sed 's/^[^(]*//;s/[()]//g') echo "Index: $index, Codec: $codec, Sprache: $lang, Bitrate: ${bitrate}kbps, Kanäle: $channels, Layout: $channel_layout" # Nur relevante Sprachen verarbeiten if [[ "$lang" == "deu" || "$lang" == "eng" ]]; then # High-Resolution Audio (z.B. DTS-HD MA oder TrueHD) if [[ "$codec" == "dts" || "$codec" == "truehd" ]]; then echo "DTS oder TrueHD gefunden, extrahiere Audiospur" mkvextract "$file" tracks $index:"$OUTPUT_DIR/${name}.${lang}.mka" # Füge die AAC-Spur für die MKV-Datei hinzu (192kbps Stereo) audio_options+=" -c:a:$audio_index aac -b:a:$audio_index 192k -ac:a:$audio_index 2 -metadata:s:a:$audio_index language=\"$lang\" -metadata:s:a:$audio_index title=\"Stereo\"" map_options+=" -map 0:$index" audio_index=$((audio_index + 1)) else # Speichere alle relevanten Spuren zur späteren Filterung audio_tracks["$lang"]+="$index:$bitrate:$codec:$channels:$channel_layout " fi fi done <<< "$audio_info" # Filtere die Spuren mit der höchsten Bitrate pro Sprache for lang in "${!audio_tracks[@]}"; do best_track=$(echo "${audio_tracks[$lang]}" | tr ' ' '\n' | sort -t':' -k2 -nr | head -n 1) best_index=$(echo "$best_track" | cut -d':' -f1) best_bitrate=$(echo "$best_track" | cut -d':' -f2) best_codec=$(echo "$best_track" | cut -d':' -f3) best_channels=$(echo "$best_track" | cut -d':' -f4) best_layout=$(echo "$best_track" | cut -d':' -f5) # Fallback-Bitrate auf 192kbps, wenn keine Bitrate ermittelt werden konnte if [[ "$best_bitrate" == "0" ]]; then best_bitrate="192" echo "Keine Bitrate gefunden, Fallback auf 192kbps" fi # Kanal-Layout setzen if [[ "$best_layout" == "side" || "$best_channels" == "6.0" ]]; then title="Surround 5.1" best_layout="5.1" # Ersetze "side" durch "5.1" else title="Stereo" best_layout="stereo" # Für alles andere Stereo als Fallback fi echo "Verwende beste Spur für $lang: Index $best_index, Bitrate ${best_bitrate}kbps, Codec $best_codec, Kanäle: $best_channels, Layout: $best_layout" audio_options+=" -c:a:$audio_index aac -b:a:$audio_index ${best_bitrate}k -metadata:s:a:$audio_index language=\"$lang\" -metadata:s:a:$audio_index bitrate=\"$bitrate\" -metadata:s:a:$audio_index title=\"$title\" -channel_layout:a:$audio_index \"$best_layout\"" map_options+=" -map 0:$best_index" audio_index=$((audio_index + 1)) done # Ausgabe der finalen Optionen für ffmpeg echo "Map-Optionen: $map_options" echo "Audio-Optionen: $audio_options" # Ergebnisse speichern echo "$audio_options" > "$audio_file" echo "$map_options" > "$map_file" ) & ( echo "Versuche schwarze Balken zu finden und zu entfernen" crop=$(ffmpeg -i "$file" -vf cropdetect -f null - 2>&1 | grep -oP "crop=\d+:\d+:\d+:\d+" | tail -1) crop_options="" # Überprüfen, ob Werte gefunden wurden if [ -n "$crop" ]; then echo "Gefundene Crop-Werte: $crop" # Anwenden der Crop-Werte crop_options=" -vf \"$crop\"" else echo "Keine Crop-Werte gefunden!" fi echo "$crop_options" > "$crop_file" ) & wait # Ergebnisse einlesen audio_options=$(cat "$audio_file") map_options=$(cat "$map_file") crop_options=$(cat "$crop_file") #debug="-b:v 5M -maxrate 6M -bufsize 10M -g 48 -bf 3" additional_options="-profile:v main -level 4.1 -preset slow $debug" ffmpeg_cmd="ffmpeg -loglevel warning -analyzeduration 200000000 -probesize 100000000 -i \"$file\"$crop_options -c:v h264_nvenc -cq $RF_VALUE $additional_options $map_options $audio_options -c:s copy -map 0:v -map_metadata -1 \"$OUTPUT_DIR/${name}.mkv\"" echo "Führe folgenden Befehl aus: $ffmpeg_cmd" eval $ffmpeg_cmd echo "Komprimierte Datei erstellt: $OUTPUT_DIR/${name}.mkv" echo "" done 2>&1 | tee convert.log # Temporäre Dateien aufräumen rm "$audio_file" "$map_file" "$crop_file"