Erpropte relativ zuverlässige Version für Blurays
This commit is contained in:
commit
12c4b47419
|
@ -0,0 +1,211 @@
|
||||||
|
#!/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"
|
Loading…
Reference in New Issue