Files
talkscore-asr/tests/test_turns.py
T
Vladimir BryzgalovandClaude Opus 5 f2f266ba1c Устойчивое распознавание длинных реплик
На Windows реплика в 190 секунд роняет энкодер GigaAM в свёртке, хотя на
macOS та же самая проходит: пределы у сборок onnxruntime разные и заранее
неизвестны. Вместо подбора константы кусок при ошибке делится пополам и
пробуется снова, до пяти уровней. Базовый размер куска снижен со 150 до 60
секунд - с запасом под любую сборку.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-15 23:37:17 +05:00

88 lines
3.1 KiB
Python

"""Тесты склейки сегментов диаризации в реплики и нарезки длинных кусков."""
from app.turns import Segment, chunk_ranges, merge_turns, speech_stats
def seg(start, end, speaker):
return Segment(start=start, end=end, speaker=speaker)
class TestMergeTurns:
def test_merges_adjacent_segments_of_same_speaker(self):
turns = merge_turns([seg(0, 2, 0), seg(2.3, 4, 0)], gap=0.8)
assert len(turns) == 1
assert turns[0].start == 0 and turns[0].end == 4
def test_keeps_separate_when_gap_is_large(self):
turns = merge_turns([seg(0, 2, 0), seg(5, 6, 0)], gap=0.8)
assert len(turns) == 2
def test_never_merges_different_speakers(self):
turns = merge_turns([seg(0, 2, 0), seg(2.1, 4, 1)], gap=0.8)
assert len(turns) == 2
assert [t.speaker for t in turns] == [0, 1]
def test_empty_input(self):
assert merge_turns([], gap=0.8) == []
def test_preserves_order(self):
turns = merge_turns([seg(0, 1, 0), seg(2, 3, 1), seg(4, 5, 0)], gap=0.5)
assert [t.start for t in turns] == [0, 2, 4]
class TestChunkRanges:
def test_short_turn_is_single_chunk(self):
assert chunk_ranges(10.0, 20.0, max_len=150) == [(10.0, 20.0)]
def test_long_turn_is_split(self):
chunks = chunk_ranges(0.0, 400.0, max_len=150)
assert len(chunks) == 3
assert chunks[0] == (0.0, 150.0)
assert chunks[-1][1] == 400.0
def test_chunks_are_contiguous(self):
chunks = chunk_ranges(5.0, 500.0, max_len=150)
for a, b in zip(chunks, chunks[1:]):
assert a[1] == b[0]
def test_no_chunk_exceeds_limit(self):
"""Главное требование: GigaAM падает на кусках длиннее 200 секунд."""
for a, b in chunk_ranges(0.0, 1000.0, max_len=150):
assert b - a <= 150
def test_exact_boundary_is_not_split(self):
assert chunk_ranges(0.0, 150.0, max_len=150) == [(0.0, 150.0)]
class TestSpeechStats:
def test_counts_share_per_speaker(self):
stats = speech_stats([seg(0, 30, 0), seg(30, 10 + 60, 1)])
assert stats["speakers"] == 2
def test_total_speech_time(self):
stats = speech_stats([seg(0, 10, 0), seg(20, 30, 1)])
assert stats["speech_sec"] == 20
def test_share_sums_to_one_hundred(self):
stats = speech_stats([seg(0, 25, 0), seg(25, 100, 1)])
total = sum(s["share_pct"] for s in stats["by_speaker"])
assert round(total) == 100
def test_empty_segments(self):
stats = speech_stats([])
assert stats["speakers"] == 0
assert stats["speech_sec"] == 0
class TestChunkLimit:
def test_default_chunk_is_conservative(self):
"""Пределы у разных сборок onnxruntime разные, берём с запасом."""
from app.pipeline import MAX_CHUNK_SEC
assert MAX_CHUNK_SEC <= 60
def test_long_turn_split_below_limit(self):
from app.pipeline import MAX_CHUNK_SEC
for a, b in chunk_ranges(0.0, 600.0, max_len=MAX_CHUNK_SEC):
assert b - a <= MAX_CHUNK_SEC