Files
simonkoson ede30d3043 feat: CCA 唱词助手子项目 v3 — 脚本版流水线完成
新增 cca/ 子项目:编导A稿+人声音频 → ASR+AI校对+AI折行 → 5段SRT字幕。
- 讯飞录音文件转写标准版(热词注入)
- DeepSeek AI校对(严格纪律:只改错别字/术语/填充词,不润色)
- DeepSeek AI折行(语义断句,≤14字/行)
- 节目结构自动切分(导视/正片×3/预告)
- 绝对时间戳SRT输出(大洋系统兼容)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-04 15:25:08 +08:00

137 lines
5.0 KiB
Python

# -*- coding: utf-8 -*-
"""
本地测试 — 不需要讯飞凭证
用模拟的 ASR 数据测试折行引擎和 SRT 生成
"""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent / "src"))
from line_breaker import break_sentence, clean_punctuation, process_sentences
from srt_writer import write_srt, ms_to_srt_time
from segment_splitter import split_into_segments, find_segment_boundaries
def test_clean_punctuation():
print("=== 测试标点清理 ===")
cases = [
('对于战后日本而言,重新武装最大的限制不是工业能力,而是政治约束。', '对于战后日本而言重新武装最大的限制不是工业能力而是政治约束'),
('这是“和平宪法”的约束', '这是“和平宪法”的约束'),
('你好!世界?', '你好世界'),
]
for input_text, expected in cases:
result = clean_punctuation(input_text)
status = "✓" if result == expected else "✗"
print(f" {status} 输入: {input_text}")
print(f" 结果: {result}")
if result != expected:
print(f" 期望: {expected}")
print()
def test_break_sentence():
print("=== 测试折行 ===")
cases = [
"对于战后日本而言重新武装最大的限制不是工业能力而是政治约束",
"各位观众你们好欢迎收看军事科技我是主持人蓝皓",
"F-35B隐身战斗机",
"日本通过从美国引进F-35战机和战斧巡航导弹等先进装备迅速获得了第五代战机远程精确打击能力",
]
for text in cases:
lines = break_sentence(text)
print(f" 输入 ({len(text)}字): {text}")
for line in lines:
print(f" → [{len(line):2d}字] {line}")
# 验证每行不超过14字
for line in lines:
assert len(line) <= 14, f"超过14字: {line} ({len(line)}字)"
print()
def test_process_sentences():
print("=== 测试完整折行流程 ===")
# 模拟 ASR 句子(参照 data/1.srt 内容)
sentences = [
(8520, 8840, "", 0), # 空句
(8880, 9880, "各位观众你们好", 1),
(9920, 11320, "欢迎收看军事科技", 1),
(11360, 12280, "我是主持人蓝皓", 1),
(12320, 13120, " ", 0), # 空白
(13160, 14400, "日本国会参议院", 1),
(14440, 16000, "今天上午6月26日表决通过了", 1),
(16040, 18480, "防卫省设置法修正案等法案", 1),
# 模拟 >2秒空白
(22000, 24320, "这是日本自1954年", 1),
(24360, 29040, "成立陆上海上航空自卫队以来", 1),
]
result = process_sentences(sentences)
print(f" 输入 {len(sentences)} 句 → 输出 {len(result)} 行")
for start, end, text in result:
time_str = f"{ms_to_srt_time(start)} --> {ms_to_srt_time(end)}"
print(f" {time_str} {text if text else '[空白]'}")
print()
def test_segment_detection():
print("=== 测试节目结构识别 ===")
sentences = [
(0, 5000, "本期军事科技将为您介绍", 1),
(5000, 8000, "日本军备的发展历程", 1),
(8880, 9880, "各位观众你们好", 1),
(9920, 11320, "欢迎收看军事科技", 1),
(11360, 12280, "我是主持人蓝皓", 1),
(13000, 50000, "正片内容一", 1),
(50000, 100000, "正片内容二", 2),
(100000, 150000, "正片内容三", 1),
(150000, 200000, "正片内容四", 2),
(200000, 250000, "正片内容五", 1),
(250000, 300000, "正片内容六", 2),
(300000, 310000, "好了观众朋友们感谢您持续关注国防军事频道军事科技", 1),
(310000, 320000, "下期我们将继续关注", 1),
(320000, 330000, "某某话题", 1),
]
start_idx, end_idx = find_segment_boundaries(sentences)
print(f" 正片开始: 第{start_idx}句 = {sentences[start_idx][2]}")
print(f" 正片结束: 第{end_idx}句 = {sentences[end_idx][2]}")
segments = split_into_segments(sentences)
for name, seg in segments:
if seg:
print(f" [{name}] {len(seg)}句, 时间 {ms_to_srt_time(seg[0][0])} ~ {ms_to_srt_time(seg[-1][1])}")
else:
print(f" [{name}] 空")
print()
def test_srt_output():
print("=== 测试 SRT 输出 ===")
subtitle_lines = [
(8880, 9880, "各位观众你们好"),
(9920, 11320, "欢迎收看《军事科技》"),
(11360, 12280, "我是主持人蓝皓"),
(12320, 13120, ""), # 空白行
(13160, 14400, "日本国会参议院"),
]
output_path = Path(__file__).parent / "output" / "test.srt"
output_path.parent.mkdir(exist_ok=True)
write_srt(subtitle_lines, str(output_path))
# 读回来检查
content = output_path.read_text(encoding="utf-8")
print(content[:500])
print()
if __name__ == "__main__":
test_clean_punctuation()
test_break_sentence()
test_process_sentences()
test_segment_detection()
test_srt_output()
print("=== 全部测试完成 ===")