fixed a bug

This commit is contained in:
2026-08-18 20:54:42 +08:00
parent f5c6717186
commit 1fb3146590
5 changed files with 238 additions and 123 deletions

View File

@@ -22,48 +22,61 @@ def _silence(seconds: float) -> np.ndarray:
return np.zeros(int(seconds * SAMPLE_RATE))
def test_document_from_transcript_splits_sentences_at_periods(tmp_path):
def test_document_from_transcript_splits_sentences_at_punctuation(tmp_path):
samples = np.concatenate(
[
_speech(2.0),
_silence(0.2),
_speech(2.0),
_silence(0.2),
_speech(1.6),
_speech(8.0),
_speech(1.5),
_speech(10.5),
_speech(4.0),
]
).astype(np.float32)
wav = tmp_path / "audio.wav"
wav.write_bytes(_wav_bytes(samples, SAMPLE_RATE))
transcript = Transcript(
text="Hello world. Good day everyone. Nice to meet you.",
text=(
"So I've been single for about four years now and I find it hard to meet "
"a guy especially in California. I've tried dating apps, I've met friends "
"through friends, I've done online dating and I just feel like most of the "
"guys that I meet aren't serious about a relationship."
),
segments=[
TranscriptionSegment(
start_seconds=0.0,
end_seconds=2.0,
text="Hello world.",
words=[
WordTimestamp(0.0, 0.6, "Hello"),
WordTimestamp(0.7, 1.5, "world."),
],
end_seconds=8.0,
text=(
"So I've been single for about four years now and I find it hard "
"to meet a guy especially in"
),
),
TranscriptionSegment(
start_seconds=2.2,
end_seconds=5.5,
text="Good day everyone. Nice to meet you.",
words=[
WordTimestamp(2.2, 2.8, "Good"),
WordTimestamp(2.9, 3.5, "day"),
WordTimestamp(3.6, 4.2, "everyone."),
WordTimestamp(4.4, 4.9, "Nice"),
WordTimestamp(5.0, 5.5, "you."),
],
start_seconds=8.0,
end_seconds=9.5,
text="California.",
words=[WordTimestamp(8.0, 9.5, "California.")],
),
TranscriptionSegment(
start_seconds=9.5,
end_seconds=20.0,
text=(
"I've tried dating apps, I've met friends through friends, "
"I've done online dating"
),
),
TranscriptionSegment(
start_seconds=20.0,
end_seconds=24.0,
text=(
"and I just feel like most of the guys that I meet aren't serious "
"about a relationship."
),
),
],
)
document = document_from_transcript(
video_hash=VIDEO_HASH,
duration_ms=6000,
duration_ms=24000,
transcript=transcript,
language="en",
audio_path=wav,
@@ -71,14 +84,18 @@ def test_document_from_transcript_splits_sentences_at_periods(tmp_path):
assert document.algorithm_version == MOSS_ALGORITHM_VERSION
assert [sentence.text for sentence in document.sentences] == [
"Hello world.",
"Good day everyone.",
"Nice to meet you.",
(
"So I've been single for about four years now and I find it hard to meet "
"a guy especially in California."
),
(
"I've tried dating apps, I've met friends through friends, I've done "
"online dating and I just feel like most of the guys that I meet aren't "
"serious about a relationship."
),
]
assert document.sentences[0].start_ms == 0
assert document.sentences[0].end_ms == 1500
assert document.sentences[1].start_ms == 2200
assert document.sentences[1].end_ms == 4200
assert document.sentences[2].start_ms == 4200
assert document.sentences[2].end_ms == 5500
assert document.sentences[0].end_ms == 9500
assert document.sentences[1].start_ms == 9500
assert document.sentences[1].end_ms == 24000
assert all(sentence.reference_speech_duration_ms > 0 for sentence in document.sentences)

View File

@@ -11,7 +11,7 @@ from sentence_api.transcription import (
_parse_json_segments,
_plan_chunks,
_parse_word_timestamps,
split_segment_by_periods,
split_sentences_at_punctuation,
_wav_bytes,
_wav_duration_seconds,
)
@@ -195,7 +195,59 @@ def test_parse_word_timestamps_ignores_invalid_entries():
assert _parse_word_timestamps("nope") is None
def test_split_segment_by_periods_uses_word_timestamps():
def test_split_sentences_merges_segments_without_punctuation():
segments = [
TranscriptionSegment(
start_seconds=0.0,
end_seconds=8.0,
text=(
"So I've been single for about four years now and I find it hard "
"to meet a guy especially in"
),
),
TranscriptionSegment(
start_seconds=8.0,
end_seconds=9.5,
text="California.",
words=[WordTimestamp(8.0, 9.5, "California.")],
),
TranscriptionSegment(
start_seconds=9.5,
end_seconds=20.0,
text=(
"I've tried dating apps, I've met friends through friends, "
"I've done online dating"
),
),
TranscriptionSegment(
start_seconds=20.0,
end_seconds=24.0,
text=(
"and I just feel like most of the guys that I meet aren't serious "
"about a relationship."
),
words=[WordTimestamp(20.0, 24.0, "relationship.")],
),
]
sentences = split_sentences_at_punctuation(segments)
assert [(s.text, s.start_seconds, s.end_seconds) for s in sentences] == [
(
"So I've been single for about four years now and I find it hard to meet "
"a guy especially in California.",
0.0,
9.5,
),
(
"I've tried dating apps, I've met friends through friends, I've done "
"online dating and I just feel like most of the guys that I meet aren't "
"serious about a relationship.",
9.5,
24.0,
),
]
def test_split_sentences_uses_word_timestamps_within_segment():
segment = TranscriptionSegment(
start_seconds=0.0,
end_seconds=4.0,
@@ -209,7 +261,7 @@ def test_split_segment_by_periods_uses_word_timestamps():
WordTimestamp(3.9, 4.0, "you."),
],
)
sentences = split_segment_by_periods(segment)
sentences = split_sentences_at_punctuation([segment])
assert [(s.text, s.start_seconds, s.end_seconds) for s in sentences] == [
("Hello world.", 0.0, 1.5),
("Good day.", 1.5, 3.2),
@@ -217,27 +269,46 @@ def test_split_segment_by_periods_uses_word_timestamps():
]
def test_split_segment_by_periods_falls_back_to_proportional():
def test_split_sentences_splits_at_question_marks():
segment = TranscriptionSegment(
start_seconds=10.0,
end_seconds=20.0,
text="First sentence. Second sentence. Third.",
start_seconds=0.0,
end_seconds=10.0,
text="Really? Wait a minute. What about now?",
)
sentences = split_segment_by_periods(segment)
sentences = split_sentences_at_punctuation([segment])
assert [s.text for s in sentences] == [
"First sentence.",
"Second sentence.",
"Third.",
"Really?",
"Wait a minute.",
"What about now?",
]
assert sentences[0].start_seconds == 0.0
assert sentences[0].end_seconds == sentences[1].start_seconds
assert sentences[1].end_seconds == sentences[2].start_seconds
assert sentences[2].end_seconds == 10.0
def test_split_sentences_falls_back_to_proportional():
segments = [
TranscriptionSegment(
start_seconds=10.0, end_seconds=14.0, text="This is the first"
),
TranscriptionSegment(
start_seconds=14.0,
end_seconds=18.0,
text="sentence. And this is the second one.",
),
]
sentences = split_sentences_at_punctuation(segments)
assert [s.text for s in sentences] == [
"This is the first sentence.",
"And this is the second one.",
]
assert sentences[0].start_seconds == 10.0
assert sentences[1].start_seconds == sentences[0].end_seconds
assert sentences[2].end_seconds == 20.0
assert sentences[0].end_seconds > 10.0
assert sentences[1].end_seconds < 20.0
assert sentences[0].end_seconds < sentences[1].end_seconds
assert sentences[0].end_seconds == sentences[1].start_seconds
assert sentences[1].end_seconds == 18.0
def test_split_segment_by_periods_falls_back_when_word_ends_are_invalid():
def test_split_sentences_falls_back_when_word_ends_are_invalid():
segment = TranscriptionSegment(
start_seconds=0.0,
end_seconds=2.0,
@@ -247,30 +318,37 @@ def test_split_segment_by_periods_falls_back_when_word_ends_are_invalid():
WordTimestamp(2.6, 3.0, "Two."),
],
)
sentences = split_segment_by_periods(segment)
sentences = split_sentences_at_punctuation([segment])
assert [s.text for s in sentences] == ["One.", "Two."]
assert sentences[0].end_seconds == sentences[1].start_seconds
assert sentences[1].end_seconds == 2.0
def test_split_segment_by_periods_keeps_segment_without_period():
def test_split_sentences_keeps_incomplete_tail_as_sentence():
segment = TranscriptionSegment(
start_seconds=1.0, end_seconds=2.0, text="no period here"
)
assert split_segment_by_periods(segment) == [segment]
sentences = split_sentences_at_punctuation([segment])
assert [(s.text, s.start_seconds, s.end_seconds) for s in sentences] == [
("no period here", 1.0, 2.0)
]
assert split_sentences_at_punctuation([]) == []
def test_split_segment_by_periods_handles_ellipsis_and_dots_only():
def test_split_sentences_handles_ellipsis_and_dots_only():
segment = TranscriptionSegment(
start_seconds=0.0,
end_seconds=2.0,
text="Wait... What? ...",
)
sentences = split_segment_by_periods(segment)
assert [s.text for s in sentences] == ["Wait...", "What? ..."]
sentences = split_sentences_at_punctuation([segment])
assert [s.text for s in sentences] == ["Wait...", "What?"]
assert sentences[0].start_seconds == 0.0
assert sentences[0].end_seconds == sentences[1].start_seconds
assert sentences[1].end_seconds == 2.0
assert split_sentences_at_punctuation(
[TranscriptionSegment(0.0, 1.0, "...")]
) == []
def test_post_audio_requests_word_timestamps_and_falls_back(monkeypatch):