The remote had one commit this branch did not (03f8a85), which adds the
Apache-2.0 LICENSE, the NOTICE and SPDX headers to every .py and .sh
file. The merge was clean - the headers sit at the top of each file and
my changes are further down.
The new files this branch added (languages.py, translations.py, the
cluster package, the new tests and scripts) were written after the
merge base, so the licence commit never saw them. They now carry the
same header, so the convention holds across the whole tree.
Nothing else changed. 883 tests passed / 8 failed - the same 8
pre-existing failures.
299 lines
12 KiB
Python
299 lines
12 KiB
Python
# Copyright 2026 Umbra Tools (umbratools.com)
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
from umbraaudio.generation.staleness import is_current, marker_path, write_marker
|
|
|
|
if TYPE_CHECKING:
|
|
from pathlib import Path
|
|
|
|
|
|
def test_marker_path(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0003.wav"
|
|
assert marker_path(wav) == tmp_path / "utt_0003.wav.txt"
|
|
|
|
|
|
def test_missing_wav_is_stale(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0000.wav"
|
|
assert is_current("Hello", wav) is False
|
|
|
|
|
|
def test_existing_wav_without_marker_is_stale(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0000.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
assert is_current("Hello", wav) is False
|
|
|
|
|
|
def test_matching_text_is_current(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0001.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
write_marker("Google uses Android.", wav, speaker="Narrator")
|
|
assert is_current("Google uses Android.", wav, speaker="Narrator") is True
|
|
|
|
|
|
def test_changed_speaker_is_stale(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0005.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
write_marker("Same words.", wav, speaker="Kabir")
|
|
assert is_current("Same words.", wav, speaker="Nanny") is False
|
|
|
|
|
|
def test_legacy_plain_text_marker_is_stale(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0006.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
marker_path(wav).write_text("Same words.", encoding="utf-8")
|
|
assert is_current("Same words.", wav, speaker="Kabir") is False
|
|
|
|
|
|
def test_marker_keeps_text_without_speaker_given(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0007.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
write_marker("Only text recorded.", wav, speaker="Narrator")
|
|
assert is_current("Only text recorded.", wav) is True
|
|
|
|
|
|
def test_changed_text_is_stale(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0002.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
write_marker("Old sentence from a previous segmentation.", wav, speaker="Narrator")
|
|
assert is_current("New sentence from re-segmentation.", wav, speaker="Narrator") is False
|
|
|
|
|
|
def test_write_marker_creates_sidecar(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0004.wav"
|
|
write_marker("Some text", wav, speaker="Narrator")
|
|
marker = marker_path(wav).read_text(encoding="utf-8")
|
|
assert marker == '{"speaker": "Narrator", "text": "Some text"}'
|
|
|
|
|
|
def test_voice_fingerprint_in_marker(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0010.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
ref = tmp_path / "female_ref.wav"
|
|
ref.write_bytes(b"RIFF-female-voice-data")
|
|
write_marker("Hello there.", wav, speaker="Nanny", voice_ref=ref)
|
|
marker = marker_path(wav).read_text(encoding="utf-8")
|
|
assert '"voice_fp":' in marker
|
|
|
|
|
|
def test_voice_fingerprint_mismatch_is_stale(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0011.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
ref_old = tmp_path / "old_ref.wav"
|
|
ref_old.write_bytes(b"RIFF-old-male-voice")
|
|
ref_new = tmp_path / "new_ref.wav"
|
|
ref_new.write_bytes(b"RIFF-new-female-voice")
|
|
write_marker("Same line.", wav, speaker="Nanny", voice_ref=ref_old)
|
|
assert is_current("Same line.", wav, speaker="Nanny", voice_ref=ref_new) is False
|
|
|
|
|
|
def test_voice_fingerprint_match_is_current(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0012.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
ref = tmp_path / "same_ref.wav"
|
|
ref.write_bytes(b"RIFF-same-voice")
|
|
write_marker("Same line.", wav, speaker="Nanny", voice_ref=ref)
|
|
assert is_current("Same line.", wav, speaker="Nanny", voice_ref=ref) is True
|
|
|
|
|
|
def test_voice_fingerprint_skipped_when_no_ref(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0013.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
ref = tmp_path / "the_ref.wav"
|
|
ref.write_bytes(b"RIFF-voice")
|
|
write_marker("With fp.", wav, speaker="Nanny", voice_ref=ref)
|
|
assert is_current("With fp.", wav, speaker="Nanny") is True
|
|
|
|
|
|
def test_voice_fingerprint_stale_when_ref_deleted(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0014.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
ref = tmp_path / "deleted_ref.wav"
|
|
ref.write_bytes(b"RIFF-data")
|
|
write_marker("Gone ref.", wav, speaker="Nanny", voice_ref=ref)
|
|
ref.unlink()
|
|
assert is_current("Gone ref.", wav, speaker="Nanny", voice_ref=ref) is False
|
|
|
|
|
|
def test_changed_instruct_is_stale(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0015.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
write_marker("Same words.", wav, speaker="Narrator", instruct="speak softly")
|
|
assert is_current("Same words.", wav, speaker="Narrator", instruct="speak loudly") is False
|
|
|
|
|
|
def test_matching_instruct_is_current(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0016.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
write_marker("Same words.", wav, speaker="Narrator", instruct="speak softly")
|
|
assert is_current("Same words.", wav, speaker="Narrator", instruct="speak softly") is True
|
|
|
|
|
|
def test_marker_without_instruct_matches_no_instruct_call(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0017.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
write_marker("Plain line.", wav, speaker="Narrator")
|
|
assert is_current("Plain line.", wav, speaker="Narrator") is True
|
|
|
|
|
|
def test_marker_without_instruct_stale_when_instruct_expected(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0018.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
write_marker("Plain line.", wav, speaker="Narrator")
|
|
assert is_current("Plain line.", wav, speaker="Narrator", instruct="speak softly") is False
|
|
|
|
|
|
def test_instruct_recorded_in_marker(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0019.wav"
|
|
write_marker("Some text", wav, speaker="Narrator", instruct="speak softly")
|
|
marker = marker_path(wav).read_text(encoding="utf-8")
|
|
assert marker == '{"speaker": "Narrator", "text": "Some text", "instruct": "speak softly"}'
|
|
|
|
|
|
def test_matching_fx_version_is_current(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0020.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
write_marker("Same words.", wav, speaker="Narrator", fx_version=1)
|
|
assert is_current("Same words.", wav, speaker="Narrator", fx_version=1) is True
|
|
|
|
|
|
def test_fx_version_mismatch_is_stale(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0021.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
write_marker("Same words.", wav, speaker="Narrator", fx_version=1)
|
|
assert is_current("Same words.", wav, speaker="Narrator", fx_version=2) is False
|
|
|
|
|
|
def test_marker_without_fx_stale_when_fx_expected(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0022.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
write_marker("Same words.", wav, speaker="Narrator")
|
|
assert is_current("Same words.", wav, speaker="Narrator", fx_version=1) is False
|
|
|
|
|
|
def test_fx_marked_audio_stale_for_plain_calls(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0023.wav"
|
|
wav.write_bytes(b"RIFF....")
|
|
write_marker("Same words.", wav, speaker="Narrator", fx_version=1)
|
|
assert is_current("Same words.", wav, speaker="Narrator") is False
|
|
|
|
|
|
def test_sha256_is_recorded_at_generation(tmp_path: Path) -> None:
|
|
"""Controller §5.2: every blob carries its own content hash from birth."""
|
|
import hashlib
|
|
import json
|
|
|
|
wav = tmp_path / "utt_0030.wav"
|
|
wav.write_bytes(b"RIFF-final-bytes")
|
|
write_marker("Same words.", wav, speaker="Hallr")
|
|
payload = json.loads(marker_path(wav).read_text())
|
|
assert payload["sha256"] == hashlib.sha256(b"RIFF-final-bytes").hexdigest()
|
|
|
|
|
|
def test_sha256_is_the_post_processed_bytes_not_the_raw_output(tmp_path: Path) -> None:
|
|
"""The hash must describe the delivered artifact, after effects are applied."""
|
|
import hashlib
|
|
import json
|
|
|
|
wav = tmp_path / "utt_0031.wav"
|
|
raw = b"RIFF-raw-tts"
|
|
wav.write_bytes(raw)
|
|
# Post-processing rewrites the file, exactly as apply_effects_to_file does.
|
|
wav.write_bytes(raw + b"-EFFECTED")
|
|
write_marker("Same words.", wav, speaker="Xylia", effects=["raspy"])
|
|
payload = json.loads(marker_path(wav).read_text())
|
|
assert payload["sha256"] == hashlib.sha256(raw + b"-EFFECTED").hexdigest()
|
|
assert payload["effects"] == ["raspy"]
|
|
|
|
|
|
def test_source_unit_key_is_recorded_so_audio_names_its_source_unit(tmp_path: Path) -> None:
|
|
import json
|
|
|
|
wav = tmp_path / "utt_0032.wav"
|
|
wav.write_bytes(b"RIFF")
|
|
write_marker("Same words.", wav, speaker="Hallr", source_unit_key="abc123")
|
|
payload = json.loads(marker_path(wav).read_text())
|
|
assert payload["source_unit_key"] == "abc123"
|
|
|
|
|
|
def test_sha256_verification_is_opt_in_and_detects_tampering(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0033.wav"
|
|
wav.write_bytes(b"RIFF-original")
|
|
write_marker("Same words.", wav, speaker="Narrator")
|
|
# Not verified by default: hashing every file on every validation pass is too slow.
|
|
assert is_current("Same words.", wav, speaker="Narrator") is True
|
|
assert is_current("Same words.", wav, speaker="Narrator", verify_sha256=True) is True
|
|
wav.write_bytes(b"RIFF-tampered")
|
|
assert is_current("Same words.", wav, speaker="Narrator") is True
|
|
assert is_current("Same words.", wav, speaker="Narrator", verify_sha256=True) is False
|
|
|
|
|
|
def test_language_recorded_in_marker(tmp_path: Path) -> None:
|
|
import json
|
|
|
|
wav = tmp_path / "utt_0040.wav"
|
|
wav.write_bytes(b"RIFF")
|
|
write_marker("Hola, amigo.", wav, speaker="Kabir", language="es")
|
|
payload = json.loads(marker_path(wav).read_text())
|
|
assert payload["language"] == "es"
|
|
|
|
|
|
def test_omitting_language_keeps_markers_byte_identical(tmp_path: Path) -> None:
|
|
"""Existing callers pass no language; their markers must not change shape."""
|
|
import json
|
|
|
|
wav = tmp_path / "utt_0041.wav"
|
|
write_marker("Some text", wav, speaker="Narrator")
|
|
payload = json.loads(marker_path(wav).read_text())
|
|
assert "language" not in payload
|
|
|
|
|
|
def test_changed_language_is_stale(tmp_path: Path) -> None:
|
|
"""A retagged line must re-render even when its text is untouched.
|
|
|
|
The audio is wrong (English phonology) while the text is identical, so only
|
|
the language in the marker can invalidate it (spec 31 section 10).
|
|
"""
|
|
wav = tmp_path / "utt_0042.wav"
|
|
wav.write_bytes(b"RIFF")
|
|
write_marker("Bonjour, ami.", wav, speaker="Kabir", language="en")
|
|
assert is_current("Bonjour, ami.", wav, speaker="Kabir", language="en") is True
|
|
assert is_current("Bonjour, ami.", wav, speaker="Kabir", language="fr") is False
|
|
|
|
|
|
def test_matching_language_is_current(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0043.wav"
|
|
wav.write_bytes(b"RIFF")
|
|
write_marker("Hola, amigo.", wav, speaker="Kabir", language="es")
|
|
assert is_current("Hola, amigo.", wav, speaker="Kabir", language="es") is True
|
|
|
|
|
|
def test_legacy_english_marker_stays_current(tmp_path: Path) -> None:
|
|
"""Markers written before the language tag exist stay valid.
|
|
|
|
Absence means English, so ~4,300 existing clips are not invalidated by this
|
|
feature.
|
|
"""
|
|
wav = tmp_path / "utt_0044.wav"
|
|
wav.write_bytes(b"RIFF")
|
|
write_marker("Hello there.", wav, speaker="Narrator")
|
|
assert is_current("Hello there.", wav, speaker="Narrator", language="en") is True
|
|
|
|
|
|
def test_legacy_marker_is_stale_when_a_foreign_language_is_expected(tmp_path: Path) -> None:
|
|
wav = tmp_path / "utt_0045.wav"
|
|
wav.write_bytes(b"RIFF")
|
|
write_marker("Hola, amigo.", wav, speaker="Kabir")
|
|
assert is_current("Hola, amigo.", wav, speaker="Kabir", language="es") is False
|
|
|
|
|
|
def test_language_not_compared_when_caller_omits_it(tmp_path: Path) -> None:
|
|
"""Callers not yet language-aware keep working exactly as before."""
|
|
wav = tmp_path / "utt_0046.wav"
|
|
wav.write_bytes(b"RIFF")
|
|
write_marker("Same words.", wav, speaker="Narrator", language="es")
|
|
assert is_current("Same words.", wav, speaker="Narrator") is True
|