69 lines
2.0 KiB
Python
69 lines
2.0 KiB
Python
# Copyright 2026 Umbra Tools (umbratools.com)
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
from __future__ import annotations
|
|
|
|
import numpy as np
|
|
import soundfile as sf
|
|
|
|
from umbraaudio.assembly import AudioStitcher
|
|
from umbraaudio.generation.scene_break import (
|
|
SCENE_BREAK_SILENCE_MS,
|
|
is_scene_break,
|
|
needs_silence,
|
|
write_scene_break_audio,
|
|
)
|
|
|
|
|
|
def test_is_scene_break_by_text() -> None:
|
|
assert is_scene_break("<<<>>>")
|
|
assert is_scene_break(" <<<>>> ")
|
|
|
|
|
|
def test_is_scene_break_by_type() -> None:
|
|
assert is_scene_break("", "scene_break")
|
|
assert not is_scene_break("Hello", "dialogue")
|
|
assert is_scene_break("<<<>>>", "narration")
|
|
|
|
|
|
def test_write_scene_break_audio(tmp_path) -> None:
|
|
out = tmp_path / "utt_0000.wav"
|
|
assert needs_silence(out)
|
|
|
|
write_scene_break_audio(out, sample_rate=24000)
|
|
|
|
assert out.exists()
|
|
data, sr = sf.read(str(out))
|
|
assert sr == 24000
|
|
expected = int(24000 * SCENE_BREAK_SILENCE_MS / 1000)
|
|
assert abs(len(data) - expected) < 5
|
|
assert np.allclose(data, 0.0)
|
|
assert not needs_silence(out)
|
|
|
|
|
|
def test_zero_byte_file_is_stale(tmp_path) -> None:
|
|
out = tmp_path / "utt_0000.wav"
|
|
out.write_bytes(b"")
|
|
assert needs_silence(out)
|
|
|
|
|
|
def test_stitch_includes_scene_break_silence(tmp_path) -> None:
|
|
tone = np.full(2400, 0.1, dtype=np.float32)
|
|
before = tmp_path / "utt_0000.wav"
|
|
scene = tmp_path / "utt_0001.wav"
|
|
after = tmp_path / "utt_0002.wav"
|
|
sf.write(str(before), tone, 24000)
|
|
sf.write(str(after), tone, 24000)
|
|
write_scene_break_audio(scene, sample_rate=24000)
|
|
|
|
output = tmp_path / "ch1_full.wav"
|
|
AudioStitcher().stitch_utterances([before, scene, after], output)
|
|
|
|
data, sr = sf.read(str(output))
|
|
assert sr == 24000
|
|
gap = int(24000 * 500 / 1000)
|
|
scene_samples = int(24000 * SCENE_BREAK_SILENCE_MS / 1000)
|
|
expected = 2400 + gap + scene_samples + gap + 2400
|
|
assert abs(len(data) - expected) < 10
|
|
assert np.allclose(data[2400 + gap : 2400 + gap + scene_samples], 0.0)
|