feat(sprachen): Rippy fragt vor dem Rip, welche Sprachen du willst
Ampel / ampel (push) Successful in 29s
Ampel / ampel (push) Successful in 29s
Commander-Anforderung: "Die Disc hat Material in X Sprachen und X Untertiteln -
Rippy muss VOR dem Rip fragen: Was genau willst du haben? In der Automatik muss
das ebenfalls einstellbar sein."
Die Auskunft lag laengst vor und wurde weggeworfen: Derselbe Titel-Scan, der die
Titel-Tabelle fuellt, liefert in derselben makemkvcon-Ausgabe die Streams mit.
Ein zweiter Info-Lauf haette eine Minute Wartezeit gekostet - jetzt kommt beides
aus einem Aufruf.
Format an der Akira-Blu-ray im Laufwerk gemessen (AGENTS Regel D):
SINFO:<titel>,<stream>,<attribut>,<code>,"<wert>"
1 = Typ ("Audio"/"Subtitles"), 3 = Sprachcode, 4 = Sprachname,
6 = Codec, 14 = Kanaele, 30 = Beschreibung
DIE FALLE dabei: Die Sprache steht in 3/4, NICHT in 28/29. Die tragen auf JEDEM
Stream "eng"/"English" - auch auf einer deutschen Tonspur und auf dem
Videostream; das ist MakeMKVs eigene Anzeigesprache. Wer 28 nimmt, haelt jede
Disc fuer englisch. Ein Test haelt das fest.
Angewendet wird die Wahl bei der KOMPRESSION, nicht beim Rippen - drei Gruende:
der Rip bleibt vollstaendig und verlustfrei (Muss-Feature laut KONZEPT); HandBrake
hat dafuer dokumentierte Schalter (--audio-lang-list / --subtitle-lang-list, die
genau die ISO-639-2-Codes nehmen, die MakeMKV liefert - beides gegengeprueft);
und wer spaeter andere Sprachen will, komprimiert neu statt die Disc wieder
einzulegen. Genau das sagt der Dialog auch, sonst glaubt man, es werde
unvollstaendig gerippt.
Nichts angeklickt heisst "alles behalten" - das Verhalten von vorher. Auch die
Einstellung ist bewusst LEER vorbelegt: Ein stilles "deu" wuerde bei einem
japanischen Original die Originaltonspur wegwerfen, ohne dass jemand gefragt hat.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -464,3 +464,131 @@ def test_auswurf_ohne_laufwerk_wirft_nicht():
|
||||
assert ripping.wirf_disc_aus(
|
||||
"/dev/sr9", ioctl_fn=lambda *a: 0, oeffnen=oeffnen_kaputt,
|
||||
schliessen=lambda fd: None, warten=lambda s: None) is False
|
||||
|
||||
|
||||
# --- Sprachen der Disc: gemessen an der Akira-Blu-ray (26.07.2026) -----------
|
||||
#
|
||||
# Woertlich aus `makemkvcon -r --noscan info dev:/dev/sr0` im Worker-Container
|
||||
# der Rippy-VM, gekuerzt auf die Attribute, die Rippy liest (AGENTS Regel D).
|
||||
|
||||
SINFO_ECHT = """SINFO:0,0,1,6201,"Video"
|
||||
SINFO:0,0,19,0,"1920x1080"
|
||||
SINFO:0,0,28,0,"eng"
|
||||
SINFO:0,0,29,0,"English"
|
||||
SINFO:0,1,1,6202,"Audio"
|
||||
SINFO:0,1,3,0,"deu"
|
||||
SINFO:0,1,4,0,"German"
|
||||
SINFO:0,1,6,0,"DTS-HD MA"
|
||||
SINFO:0,1,14,0,"2"
|
||||
SINFO:0,1,28,0,"eng"
|
||||
SINFO:0,1,29,0,"English"
|
||||
SINFO:0,1,30,0,"DTS-HD MA Stereo German"
|
||||
SINFO:0,2,1,6202,"Audio"
|
||||
SINFO:0,2,3,0,"jpn"
|
||||
SINFO:0,2,4,0,"Japanese"
|
||||
SINFO:0,2,6,0,"DTS-HD MA"
|
||||
SINFO:0,2,14,0,"6"
|
||||
SINFO:0,2,30,0,"DTS-HD MA 5.1 Japanese"
|
||||
SINFO:0,3,1,6203,"Subtitles"
|
||||
SINFO:0,3,3,0,"deu"
|
||||
SINFO:0,3,4,0,"German"
|
||||
SINFO:0,3,6,0,"PGS"
|
||||
SINFO:1,0,1,6202,"Audio"
|
||||
SINFO:1,0,3,0,"eng"
|
||||
SINFO:1,0,4,0,"English"
|
||||
SINFO:1,0,6,0,"AC3"
|
||||
"""
|
||||
|
||||
|
||||
def test_streams_werden_nach_typ_getrennt():
|
||||
from ripping import parse_stream_info
|
||||
|
||||
je_titel = parse_stream_info(SINFO_ECHT)
|
||||
assert set(je_titel) == {0, 1}
|
||||
assert [a["lang"] for a in je_titel[0]["audio"]] == ["deu", "jpn"]
|
||||
assert [u["lang"] for u in je_titel[0]["untertitel"]] == ["deu"]
|
||||
assert je_titel[0]["audio"][1]["kanaele"] == "6"
|
||||
assert je_titel[0]["audio"][0]["codec"] == "DTS-HD MA"
|
||||
|
||||
|
||||
def test_die_sprache_steht_in_attribut_3_nicht_28():
|
||||
"""DIE Falle: 28/29 tragen auf JEDEM Stream "eng"/"English" - auch auf einer
|
||||
deutschen Tonspur und auf dem Videostream. Das ist MakeMKVs Anzeigesprache.
|
||||
Wer 28 nimmt, haelt jede Disc fuer englisch."""
|
||||
from ripping import parse_stream_info
|
||||
|
||||
deutsche_spur = parse_stream_info(SINFO_ECHT)[0]["audio"][0]
|
||||
assert deutsche_spur["lang"] == "deu"
|
||||
assert deutsche_spur["sprache"] == "German"
|
||||
|
||||
|
||||
def test_video_taucht_nicht_als_tonspur_auf():
|
||||
from ripping import parse_stream_info
|
||||
|
||||
je_titel = parse_stream_info(SINFO_ECHT)
|
||||
assert all(a["typ"] == "Audio" for a in je_titel[0]["audio"])
|
||||
|
||||
|
||||
def test_sprachen_werden_ueber_alle_titel_vereinigt():
|
||||
"""Vor dem Rip zaehlt nicht "Titel 3 Stream 7", sondern was die DISC hat."""
|
||||
from ripping import parse_stream_info, sprachen_zusammenfassen
|
||||
|
||||
s = sprachen_zusammenfassen(parse_stream_info(SINFO_ECHT))
|
||||
assert [a["lang"] for a in s["audio"]] == ["deu", "jpn", "eng"]
|
||||
assert [a["sprache"] for a in s["audio"]] == ["German", "Japanese", "English"]
|
||||
assert [u["lang"] for u in s["untertitel"]] == ["deu"]
|
||||
# deu kommt in Titel 0 einmal vor
|
||||
assert s["audio"][0]["spuren"] == 1
|
||||
|
||||
|
||||
def test_leere_ausgabe_gibt_leere_sprachen():
|
||||
from ripping import parse_stream_info, sprachen_zusammenfassen
|
||||
|
||||
assert parse_stream_info("") == {}
|
||||
assert sprachen_zusammenfassen({}) == {"audio": [], "untertitel": []}
|
||||
assert sprachen_zusammenfassen(None) == {"audio": [], "untertitel": []}
|
||||
|
||||
|
||||
# --- Sprachliste aus den Einstellungen --------------------------------------
|
||||
|
||||
|
||||
def test_sprachliste_raeumt_auf():
|
||||
from ripping import sprachliste
|
||||
|
||||
assert sprachliste("deu, eng , ,DEU") == ["deu", "eng"]
|
||||
assert sprachliste(["deu", "deu", "jpn"]) == ["deu", "jpn"]
|
||||
assert sprachliste("") == []
|
||||
assert sprachliste(None) == []
|
||||
|
||||
|
||||
def test_grossschreibung_macht_die_auswahl_nicht_unwirksam():
|
||||
"""HandBrake will ISO-639-2 klein. Ein "DEU" aus einem Eingabefeld darf nicht
|
||||
still die ganze Auswahl aushebeln."""
|
||||
from ripping import sprachliste
|
||||
|
||||
assert sprachliste("DEU,ENG") == ["deu", "eng"]
|
||||
|
||||
|
||||
# --- Das HandBrake-Kommando -------------------------------------------------
|
||||
|
||||
|
||||
def test_handbrake_kommando_ohne_auswahl_bleibt_wie_bisher():
|
||||
from ripping import build_handbrake_cmd
|
||||
|
||||
cmd = build_handbrake_cmd("/a.mkv", "/b.mkv", "H.265 MKV 1080p30")
|
||||
assert "--audio-lang-list" not in cmd
|
||||
assert "--subtitle-lang-list" not in cmd
|
||||
assert "--all-audio" in cmd and "--all-subtitles" in cmd
|
||||
|
||||
|
||||
def test_handbrake_kommando_mit_sprachauswahl():
|
||||
"""--audio-lang-list zusammen mit --all-audio heisst laut HandBrake-Hilfe:
|
||||
alle Tonspuren, die zu einer der Sprachen passen."""
|
||||
from ripping import build_handbrake_cmd
|
||||
|
||||
cmd = build_handbrake_cmd("/a.mkv", "/b.mkv", "H.265 MKV 1080p30",
|
||||
audio_sprachen=["deu", "jpn"],
|
||||
untertitel_sprachen=["deu"])
|
||||
assert cmd[cmd.index("--audio-lang-list") + 1] == "deu,jpn"
|
||||
assert cmd[cmd.index("--subtitle-lang-list") + 1] == "deu"
|
||||
assert "--all-audio" in cmd and "--all-subtitles" in cmd
|
||||
|
||||
Reference in New Issue
Block a user