diff --git a/video-ai-system/engines/ep01_shot03_production.py b/video-ai-system/engines/ep01_shot03_production.py index 257578e..50892e5 100644 --- a/video-ai-system/engines/ep01_shot03_production.py +++ b/video-ai-system/engines/ep01_shot03_production.py @@ -72,18 +72,15 @@ class EP01Shot03ProductionCLI: print(f" Dry Run: {self.dry_run}") def _load_config(self): - """加载 E1-SHOT03 配置""" - config_file = self.config_dir / "EP01-SHOT01-06-MAPPING.hdlp" + """加载 E1-SHOT03 配置,从剧本原文+分镜文件读取真实台词""" + script_file = PROJECT_ROOT.parent / "动态漫:《付费才能修仙?我的宗门全免费》.md" + mapping_file = self.config_dir / "EP01-SHOT01-06-MAPPING.hdlp" + storyboard_file = PROJECT_ROOT / "data" / "ep01-storyboard.json" - if not config_file.exists(): - print(f"⚠️ 配置不存在: {config_file}") - return self._default_config() - - # 简单解析 HLDP 文件 config = { "shot_id": "E1-SHOT03", "prompt": "", - "duration": 5, + "duration": 3, "resolution": "720p", "character": "CHAR-003-SuBai", "props": ["PROP-TDZ-PLAQUE"], @@ -92,12 +89,44 @@ class EP01Shot03ProductionCLI: "emotion": "苏白·大声·自信" } - with open(config_file, "r", encoding="utf-8") as f: - content = f.read() + # 1. 从剧本原文读取真实台词 + if script_file.exists(): + with open(script_file, "r", encoding="utf-8") as f: + script_text = f.read() - # 找 E1-SHOT03 段落 - if "E1-SHOT03" in content: - lines = content.split("\n") + # 匹配 SHOT03 对应的剧本段落 + import re + # 找"苏白(大声):"后面的台词 + dialogue_matches = re.findall(r'苏白[((][^))]*[))]\s*[::]\s*(.+?)(?:\n|$)', script_text) + if dialogue_matches: + config["dialogue"] = dialogue_matches[0] # 第一句:未来的天下第一宗!天道宗开门收徒啦! + print(f" 📖 剧本台词(第1句): {config['dialogue']}") + # 拼接多句台词 + if len(dialogue_matches) >= 2: + config["dialogue_all"] = dialogue_matches + print(f" 📖 全部{len(dialogue_matches)}句: {' | '.join(dialogue_matches[:3])}") + + # 2. 从分镜文件读取镜头信息 + if storyboard_file.exists(): + with open(storyboard_file, "r", encoding="utf-8") as f: + storyboard = json.load(f) + for shot in storyboard.get("shots", []): + if shot.get("shotId") == "E1-SHOT03": + config["action"] = shot.get("action", "") + config["camera"] = shot.get("camera", "") + config["emotion"] = shot.get("emotionMarker", config["emotion"]) + config["duration"] = shot.get("duration", config["duration"]) + config["sourceLine"] = shot.get("sourceLine", "") + print(f" 🎬 分镜: {config.get('action', '')[:60]}") + break + + # 3. 从HLDP映射文件读取镜头参数(不覆盖剧本台词) + SCRIPT_PROTECTED = {"dialogue", "dialogue_all", "action", "camera", "emotion", "sourceLine", "duration"} + if mapping_file.exists(): + with open(mapping_file, "r", encoding="utf-8") as f: + mapping_content = f.read() + if "E1-SHOT03" in mapping_content: + lines = mapping_content.split("\n") in_shot = False for line in lines: if "E1-SHOT03" in line: @@ -107,21 +136,20 @@ class EP01Shot03ProductionCLI: break if ":" in line: key, _, val = line.partition(":") - config[key.strip()] = val.strip() - - # 如果没找到台词,使用默认 - if not config.get("dialogue"): - config["dialogue"] = "未来的天下第一宗!" + key = key.strip() + if key not in SCRIPT_PROTECTED: + config[key] = val.strip() + # 构造提示词 if not config.get("prompt"): - config["prompt"] = "苏白站在天道宗牌匾下,自信地说:未来的天下第一宗!" + action = config.get("action", "苏白站在天道宗牌匾下自信喊话") + dialogue = config.get("dialogue", "未来的天下第一宗!") + config["prompt"] = f"{action},大声说:{dialogue}" - print(f" ✓ 配置已加载") - print(f" 提示词: {config['prompt'][:60]}...") - print(f" 台词: {config['dialogue']}") + print(f" ✅ 配置已加载 (来源: 剧本原文 + 分镜 + 映射)") + print(f" 台词: {config['dialogue'][:50]}") print(f" 情感: {config['emotion']}") - - return config + print(f" 时长: {config['duration']}s") def _default_config(self): """默认配置"""