mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-11-12 20:15:10 +00:00
Set muxing.track_names to native to name an unnamed track in its own language (中文(繁體), Português (Portugal)) in place of English. The same script and region rules apply. --list, the muxed names and the REST API track_name follow the option. A test fixture resets the muxing options, so a local unshackle.yaml cannot change test results.
180 lines
6.5 KiB
Python
180 lines
6.5 KiB
Python
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
import pytest
|
|
from langcodes import Language
|
|
|
|
from unshackle.core import binaries
|
|
from unshackle.core.config import config
|
|
from unshackle.core.tracks import Audio, Subtitle, Tracks, Video
|
|
from unshackle.core.utilities import language_name, multi_script_languages, with_script
|
|
|
|
|
|
def sub(lang: str, name: Optional[str] = None, sdh: bool = False) -> Subtitle:
|
|
return Subtitle(id_="s", url="https://x/s", codec=Subtitle.Codec.WebVTT, language=lang, name=name, sdh=sdh)
|
|
|
|
|
|
def test_multi_script_languages_come_from_cldr() -> None:
|
|
assert {"zh", "yue", "sr"} <= multi_script_languages()
|
|
assert not {"en", "pt", "ja"} & multi_script_languages()
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("tag", "expected"),
|
|
[
|
|
("zh", "zh"),
|
|
("zh-TW", "zh-Hant-TW"),
|
|
("zh-CN", "zh-Hans-CN"),
|
|
("zh-HK", "zh-Hant-HK"),
|
|
("zh-SG", "zh-Hans-SG"),
|
|
("zh-Hant", "zh-Hant"),
|
|
("yue-HK", "yue-Hant-HK"),
|
|
("sr-ME", "sr-Latn-ME"),
|
|
("sr-RS", "sr-Cyrl-RS"),
|
|
("pa-PK", "pa-Arab-PK"),
|
|
("ms-MY", "ms-MY"),
|
|
("en-US", "en-US"),
|
|
("und-TW", "und-TW"),
|
|
("und", "und"),
|
|
],
|
|
)
|
|
def test_with_script(tag: str, expected: str) -> None:
|
|
assert str(with_script(Language.get(tag))) == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("tag", "expected"),
|
|
[
|
|
("zh-Hant-TW", "Chinese (Traditional)"),
|
|
("zh-Hans-CN", "Chinese (Simplified)"),
|
|
("zh-Hant-HK", "Chinese (Traditional, Hong Kong)"),
|
|
("zh-TW", "Chinese (Taiwan)"),
|
|
("pt-BR", "Portuguese"),
|
|
("pt-PT", "Portuguese (Portugal)"),
|
|
("en-US", "English"),
|
|
("en-GB", "English (United Kingdom)"),
|
|
("ja-JP", "Japanese"),
|
|
("fr-CA", "French (Canada)"),
|
|
("ar-001", "Arabic"),
|
|
("es-419", "Spanish (Latin America)"),
|
|
("en", "English"),
|
|
("de-DE", "German"),
|
|
("en-ZZ", "English"),
|
|
("en-XA", "English"),
|
|
("en-Zzzz", "English"),
|
|
("sq-XK", "Albanian (Kosovo)"),
|
|
("mn-Mong-CN", "Mongolian (China)"),
|
|
("und", None),
|
|
("qaa", None),
|
|
("x-foo", None),
|
|
],
|
|
)
|
|
def test_language_name(tag: str, expected: Optional[str]) -> None:
|
|
assert language_name(Language.get(tag)) == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("tag", "expected"),
|
|
[
|
|
("zh-Hant-TW", "中文(繁體)"),
|
|
("zh-Hans-CN", "中文(简体)"),
|
|
("zh-Hant-HK", "中文(繁體,香港)"),
|
|
("zh-Hans-MO", "中文(简体,澳门)"),
|
|
("zh-TW", "中文(台灣)"),
|
|
("zh-HK", "中文(香港)"),
|
|
("cmn-Hant", "中文(繁體)"),
|
|
("yue-Hant", "粵語(繁體)"),
|
|
("sr-ME", "Srpski (Crna Gora)"),
|
|
("ka", "ქართული"),
|
|
("hy", "Հայերեն"),
|
|
("pt-BR", "Português"),
|
|
("pt-PT", "Português (Portugal)"),
|
|
("es-419", "Español (Latinoamérica)"),
|
|
("sr-Latn-ME", "Srpski (latinica, Crna Gora)"),
|
|
("ja-JP", "日本語"),
|
|
("en-GB", "English (United Kingdom)"),
|
|
("en-HK", "English (Hong Kong)"),
|
|
("qaa", None),
|
|
],
|
|
)
|
|
def test_native_language_name(tag: str, expected: Optional[str], monkeypatch: pytest.MonkeyPatch) -> None:
|
|
monkeypatch.setattr(config, "muxing", {"track_names": "native"})
|
|
assert language_name(Language.get(tag)) == expected
|
|
|
|
|
|
def test_native_subtitle_name_keeps_the_flag(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
monkeypatch.setattr(config, "muxing", {"track_names": "native"})
|
|
assert sub("zh-TW", sdh=True).get_track_name() == "中文(繁體) (SDH)"
|
|
assert sub("zh", name="Mandarin").get_track_name() == "Mandarin"
|
|
|
|
|
|
def test_subtitle_names_and_tags_the_script_but_keeps_its_language() -> None:
|
|
track = sub("zh-TW")
|
|
assert track.name is None
|
|
assert track.get_track_name() == "Chinese (Traditional)"
|
|
assert str(track.mux_language) == "zh-Hant-TW"
|
|
assert str(track.language) == "zh-TW"
|
|
|
|
|
|
def test_subtitle_flag_follows_the_default_name() -> None:
|
|
assert sub("zh-CN", sdh=True).get_track_name() == "Chinese (Simplified) (SDH)"
|
|
|
|
|
|
def test_audio_gets_no_script() -> None:
|
|
track = Audio(id_="a", url="https://x/a", codec=Audio.Codec.AAC, language="zh-TW", bitrate=1)
|
|
assert track.get_track_name() == "Chinese (Taiwan)"
|
|
assert str(track.mux_language) == "zh-TW"
|
|
|
|
|
|
def test_a_service_name_wins() -> None:
|
|
assert sub("zh", name="简体中文").get_track_name() == "简体中文"
|
|
|
|
|
|
def test_mkvmerge_gets_the_subtitle_script_and_name(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
class Stop(Exception):
|
|
pass
|
|
|
|
captured: list[list[str]] = []
|
|
|
|
def fake_popen(args: list[str], **kwargs: object) -> None:
|
|
captured.append(args)
|
|
raise Stop
|
|
|
|
monkeypatch.setattr("unshackle.core.tracks.tracks.subprocess.Popen", fake_popen)
|
|
monkeypatch.setattr(binaries, "MKVToolNix", Path("mkvmerge"))
|
|
video = Video(id_="v", url="https://x/v", codec=Video.Codec.AVC, language="zh-TW", width=1920, height=1080)
|
|
audio = Audio(id_="a", url="https://x/a", codec=Audio.Codec.AAC, language="zh-TW", bitrate=1)
|
|
subtitle = sub("zh-TW")
|
|
for track, file in ((video, "v.mp4"), (audio, "a.mp4"), (subtitle, "s.vtt")):
|
|
track.path = tmp_path / file
|
|
track.path.write_bytes(b"\x00" * 16)
|
|
|
|
with pytest.raises(Stop):
|
|
Tracks([video, audio, subtitle]).mux("T", delete=False, output_path=tmp_path / "o.mkv")
|
|
|
|
def last_option(file: str, flag: str) -> str:
|
|
"""Return the value of the last flag given before the file, which is the one mkvmerge applies to it."""
|
|
before = captured[0][: captured[0].index(str(tmp_path / file))]
|
|
return before[len(before) - before[::-1].index(flag)]
|
|
|
|
assert last_option("s.vtt", "--language") == "0:zh-Hant-TW"
|
|
assert last_option("s.vtt", "--track-name") == "0:Chinese (Traditional)"
|
|
assert last_option("a.mp4", "--language") == "0:zh-TW"
|
|
|
|
|
|
def test_the_default_name_follows_a_later_language_change() -> None:
|
|
track = sub("yue")
|
|
track.language = Language.get("zh-Hant")
|
|
assert track.get_track_name() == "Chinese (Traditional)"
|
|
|
|
|
|
def test_a_language_assigned_as_text_later_is_parsed() -> None:
|
|
track = sub("pt")
|
|
track.language = "pt-PT"
|
|
assert track.language == Language.get("pt-PT")
|
|
assert track.get_track_name() == "Portuguese (Portugal)"
|
|
assert str(track) == "SUB | [VTT] | pt-PT | Portuguese (Portugal)"
|
|
track.language = None
|
|
assert str(track.language) == "und"
|
|
assert track.get_track_name() is None
|