Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions core/segment_tts.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ def analyze(self, text: str, index: int, total: int) -> Tuple[str, float]:
if re.search(rule["pattern"], text):
candidates.append((rule["type"], rule["confidence"]))

# 位置规则兜底:最后一个 segment 如果没有被关键词/正则覆盖,默认 cta
if index == total - 1 and not any(t == "cta" for t, _ in candidates):
pos_rules = self.rules.get("position_rules", {})
if "last" in pos_rules:
candidates.append((pos_rules["last"]["type"], pos_rules["last"]["confidence"]))

if not candidates:
# 默认:中间段为 narrative
if 0 < index < total - 1:
Expand All @@ -127,6 +133,13 @@ def analyze(self, text: str, index: int, total: int) -> Tuple[str, float]:

# 选择置信度最高的类型
best_type, best_conf = max(candidates, key=lambda x: x[1])

# Guard:非最后一个 segment 不允许被推断为 cta
# CTA 只能出现在视频结尾,避免中间段被误标为行动号召
if best_type == "cta" and index < total - 1:
# 降级为 narrative,置信度中等
return "narrative", 0.5

return best_type, best_conf


Expand Down
14 changes: 14 additions & 0 deletions extensions/storyboard/storyboard_ai.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,20 @@ def _infer_segment_type(self, text: str, index: int, total: int) -> str:
if candidates:
return max(candidates, key=lambda x: x[1])[0]

# 位置规则兜底
pos_rules = self.rules.get("position_rules", {})
if index == 0 and "first" in pos_rules:
candidates.append((pos_rules["first"]["type"], pos_rules["first"]["confidence"]))
if index == total - 1 and "last" in pos_rules:
candidates.append((pos_rules["last"]["type"], pos_rules["last"]["confidence"]))

if candidates:
best_type, _ = max(candidates, key=lambda x: x[1])
# Guard:非最后一个 segment 不允许被推断为 cta
if best_type == "cta" and index < total - 1:
return "narrative"
return best_type

# 简单回退
if index == 0:
return "hook"
Expand Down
4 changes: 2 additions & 2 deletions rules/segment_types.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
},
"last": {
"type": "cta",
"confidence": 0.6,
"description": "最后一段默认为 cta,但如果有 CTA 关键词则 confidence 更高"
"confidence": 0.9,
"description": "最后一段默认为 cta,confidence 确保结尾引导"
}
},
"keyword_rules": [
Expand Down
53 changes: 53 additions & 0 deletions scripts/fix_cta_overuse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env python3
"""
修复 segments.json 中 CTA 过多的问题

用法:
python scripts/fix_cta_overuse.py output/rsi_cn/segments.json

逻辑:
- 只有最后一个 segment 允许类型为 "cta"
- 其他被误标为 "cta" 的 segment 降级为 "narrative"
"""

import json
import sys
from pathlib import Path


def fix_cta_overuse(segments_path: str):
path = Path(segments_path)
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)

segments = data.get("segments", [])
if not segments:
print("No segments found")
return

total = len(segments)
fixed = 0

for i, seg in enumerate(segments):
if seg.get("segment_type") == "cta" and i < total - 1:
seg["segment_type"] = "narrative"
seg["segment_type_confidence"] = 0.5
fixed += 1
print(f" Fixed {seg['id']}: cta -> narrative")

if fixed > 0:
# 备份原文件
backup_path = path.with_suffix(".json.bak")
path.rename(backup_path)
with open(path, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print(f"\nFixed {fixed} segment(s). Original backed up to {backup_path.name}")
else:
print("No overuse CTA segments found. All good!")


if __name__ == "__main__":
if len(sys.argv) < 2:
print(f"Usage: python {sys.argv[0]} <segments.json>")
sys.exit(1)
fix_cta_overuse(sys.argv[1])
Loading