From dfce764b4b79ac9b0a02de1d2a61f900fb7dbd0b Mon Sep 17 00:00:00 2001 From: saas-backend-agent Date: Mon, 14 Sep 2026 18:00:55 +0800 Subject: [PATCH] =?UTF-8?q?fix(backend):=20#1892=20=E7=94=BB=E9=9D=A2?= =?UTF-8?q?=E6=8F=92=E5=85=A5=E6=8C=89=E5=8F=A5=E5=8F=B7=E5=88=86=E5=8F=A5?= =?UTF-8?q?=EF=BC=8C=E5=8E=BB=E6=8E=89=E9=80=97=E5=8F=B7=E5=88=86=E9=9A=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - packages/domain/sentence_timings.py: split_script_into_sentences 正则去掉中英文逗号(, ,),仅按句号/问号/感叹号/分号/换行分句,与前端 sentences.ts 的 SENTENCE_SPLIT_RE 保持一致 - 原因:按逗号切分会把连贯小句拆得过碎,导致 B-roll/口播画面按句插入时句数过多、时长过短(Issue #1892) - 检查调用方:lipsync_tts 等仅消费 sentences 列表+时间戳,句数变化只影响时间粒度,compute_sentence_timings 的静音点检测与字符比例降级仍正常工作,B-roll 时间戳对齐不受影响 - 单测:新增中文/英文逗号不切分、句号间带逗号保持完整的 3 个用例,全部 24 个用例通过 --- packages/domain/sentence_timings.py | 11 ++++++----- tests/unit/test_sentence_timings.py | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/packages/domain/sentence_timings.py b/packages/domain/sentence_timings.py index cfeba7ce7..45446d968 100644 --- a/packages/domain/sentence_timings.py +++ b/packages/domain/sentence_timings.py @@ -1,6 +1,6 @@ """共享的句子时间戳计算工具 — 供 Celery TTS 任务和 /lipsync/tts-preview 同步接口复用. -- `_split_script_into_sentences`: 按标点分句(中英文逗号/句号/问号/感叹号/分号/换行) +- `split_script_into_sentences`: 按标点分句(中英文句号/问号/感叹号/分号/换行,不含逗号,与前端 sentences.ts 保持一致) - `_estimate_sentence_timings_by_chars`: 按字数比例估算(静音检测失败时降级) - `_probe_audio_duration`: ffprobe 读取音频时长 - `compute_sentence_timings`: 基于 ffmpeg silencedetect 精确计算每句起止时间 @@ -19,15 +19,16 @@ logger = logging.getLogger(__name__) def split_script_into_sentences(script_text: str) -> list[str]: - """按句号/问号/感叹号/分号/逗号/换行分句(与前端 SENTENCE_SPLIT_RE 一致). + """按句号/问号/感叹号/分号/换行分句(与前端 sentences.ts 的 SENTENCE_SPLIT_RE 一致). - 中文短视频文案习惯用「,」断小句(如"卖花的叫花无缺,卖姜的叫姜子牙"), - 必须把逗号也纳入分隔符,否则多句文案会被识别成一整句,导致 B-roll 时间戳错位。 + 仅在句末标点(。!?!?;;)和换行处分句,**不再用逗号(,,)切分**。 + 按逗号切分会把连贯句子拆得过碎,导致 B-roll/口播画面按句插入时句数过多、 + 时长过短,效果不符合预期(Issue #1892)。 """ text = (script_text or "").strip() if not text: return [] - parts = re.split(r"[。!?!??!;;,,\n\r]+", text) + parts = re.split(r"[。!?!??!;;\n\r]+", text) return [p.strip() for p in parts if p.strip()] diff --git a/tests/unit/test_sentence_timings.py b/tests/unit/test_sentence_timings.py index 3551d03ab..73ed4679f 100644 --- a/tests/unit/test_sentence_timings.py +++ b/tests/unit/test_sentence_timings.py @@ -46,6 +46,21 @@ class TestSplitScriptIntoSentences(unittest.TestCase): result = _split_script_into_sentences("没有标点的句子") self.assertEqual(result, ["没有标点的句子"]) + def test_chinese_comma_not_split(self): + """Issue #1892:中文逗号「,」不应分句,保持完整小句。""" + result = _split_script_into_sentences("卖花的叫花无缺,卖姜的叫姜子牙。") + self.assertEqual(result, ["卖花的叫花无缺,卖姜的叫姜子牙"]) + + def test_english_comma_not_split(self): + """Issue #1892:英文逗号「,」不应分句。""" + result = _split_script_into_sentences("Hello, how are you?") + self.assertEqual(result, ["Hello, how are you"]) + + def test_comma_between_sentences_kept_in_sentence(self): + """两个句号间带逗号的长句:逗号不切,只按句号切。""" + result = _split_script_into_sentences("第一句,带逗号。第二句,也带逗号!") + self.assertEqual(result, ["第一句,带逗号", "第二句,也带逗号"]) + class TestEstimateSentenceTimingsByChars(unittest.TestCase): """Tests for _estimate_sentence_timings_by_chars."""