fix: verify and guard video ai modules
Some checks failed
自动更新代码和重启 / update-and-restart (push) Has been cancelled
CI检查 + 自动部署 / check (push) Has been cancelled
CI检查 + 自动部署 / deploy (push) Has been cancelled

This commit is contained in:
冰朔 2026-06-24 13:12:03 +08:00
parent eab0f0e0d4
commit 9474086356
10 changed files with 437 additions and 50 deletions

View File

@ -3,7 +3,7 @@
> HLDP://video-ai-system/CURRENT
> 类型: 子系统官方置信入口 · 每次进入视频AI系统先读
> 创建: D140 · 2026-06-22 · Codex收口
> 更新: D143 · 2026-06-23 · preview-002复盘·制片厂化重启
> 更新: D144 · 2026-06-24 · 8模块验收·生产阻塞项确认
> 铸渊 ICE-GL-ZY001 · 冰朔 TCS-0002∞
> 国作登字-2026-A-00037559
@ -133,6 +133,7 @@ JZAO外置盘: 产物存放地,不是状态主控。
| 苏白TTS配音 | ✅ 工程测试通过 | `video-ai-system/outputs/tests/TEST-TTS-001-SUBAI-RUN-001-REPORT.hdlp` |
| 模型/成本路线 | ✅ 已建立 | `video-ai-system/knowledge/D144-MODEL-COST-ROUTE.hdlp` |
| 腾讯AI开发交接 | ✅ 已建立 | `video-ai-system/plans/D144-TENCENT-AI-DEV-HANDOFF.hdlp` |
| 腾讯AI 8模块代码 | 🟡 部分通过 | `video-ai-system/experience/D144-8-MODULE-VERIFICATION.hdlp` · 框架入仓但主角资产、多参考图、口型同步、EP01 CLI仍非生产可用 |
| 广告牌资产 | ✅ 草案 | `video-ai-system/assets/props/PROP-FREE-AD-BOARD/manifest.hdlp` |
| 广告牌文字贴图 | ✅ PNG已生成 | `video-ai-system/assets/props/PROP-FREE-AD-BOARD/texture/free-ad-board-texture.png` |
| 百宗会场景资产 | ✅ 草案 | `video-ai-system/assets/envs/ENV-002-Baizonghui/manifest.hdlp` |
@ -149,10 +150,10 @@ JZAO外置盘: 产物存放地,不是状态主控。
当前正式任务:
```
D143-VIDEO-AI-RESET:
从 preview-002 失败复盘和《渔乡守真心》样片对标开始,重新建立影视制作流程知识库、素材库、模型准入、对白口型测试、竖屏剪辑模板和经验闭环
不直接生成 preview-003
第一个突破测试是 2-3 秒“苏白说一句话”,第二个突破测试是“天道宗牌匾跨镜一致”
D144-VIDEO-AI-PRODUCTION-BLOCKERS:
腾讯AI 8模块已入仓并完成第一轮验收但不能按“全部开发完成”验收
当前优先级仍是字幕商业标准工具链、真实口型同步、剧本原文锁定、主角资产包真实生成、多参考/合成一致性路线
任何模块不能把占位输出、复制输出、未验证API能力标记成生产成功
```
---

View File

@ -19,14 +19,23 @@ import os
import sys
import json
import argparse
import shutil
from pathlib import Path
# 添加项目根目录到路径
PROJECT_ROOT = Path(__file__).parent.parent.parent
sys.path.insert(0, str(PROJECT_ROOT / "engines"))
from image_api_adapter import generate_image, save_image
from hldp_prompt import expand_prompt
try:
from image_api_adapter import generate_image
except Exception as exc:
print(f"⚠️ Python图片生成适配器未接通: {exc}")
generate_image = None
try:
from hldp_prompt import expand_prompt
except Exception:
expand_prompt = None
class CharHeroDesignPacker:
@ -115,6 +124,14 @@ class CharHeroDesignPacker:
print(f" 参考图: {candidate}")
print(f" 提示词: {prompt[:100]}...")
if generate_image is None:
print(" ⚠️ 当前仓库只有 JS 图片适配器 image-api-adapter.js未提供 Python generate_image。")
print(" ⚠️ 暂不能生成新主角资产;仅将候选图复制到 candidates/ 供人工/后续工具处理。")
fallback_path = self.candidates_dir / output_name
shutil.copy2(candidate, fallback_path)
print(f" 🟡 已复制候选图: {fallback_path}")
return None
try:
result_path = generate_image(
prompt=prompt,
@ -203,24 +220,24 @@ class CharHeroDesignPacker:
prompts = {
"front_half_body": f"""
{base_desc.get('visual_description', '中国古代修仙少年16岁白色长发,蓝色眼睛')}
{base_desc.get('visual_description', '中国古代修仙少年16岁主角辨识度强')}
正面半身像胸部以上面部清晰眼神坚定
3D动画风格皮克斯风格统一渲染风格
3D国风漫剧风格统一渲染风格
高清8K最佳质量
""".strip(),
"side_face": f"""
{base_desc.get('visual_description', '中国古代修仙少年')}
侧脸45度能看到面部轮廓和发型
3D动画风格皮克斯风格统一渲染风格
3D国风漫剧风格统一渲染风格
高清8K最佳质量
""".strip(),
"full_body_costume": f"""
{base_desc.get('visual_description', '中国古代修仙少年')}
全身像站立姿势完整展示服装细节
白色内衬蓝色外袍黑色腰带棕色靴子
3D动画风格皮克斯风格统一渲染风格
服装细节必须来自角色资产清单不得自由改色
3D国风漫剧风格统一渲染风格
高清8K最佳质量
""".strip(),
@ -229,7 +246,7 @@ class CharHeroDesignPacker:
表情表网格布局包含:
平静微笑大笑生气惊讶悲伤
每个表情单独一格统一光照和背景
3D动画风格皮克斯风格
3D国风漫剧风格
高清8K最佳质量
""".strip(),
}
@ -263,7 +280,7 @@ class CharHeroDesignPacker:
if path:
results["expression_sheet"] = path
# 更新 manifest
# 更新 manifest。只有四项资产都真实生成时才可进入 APPROVED。
self._update_manifest(results)
print(f"\n✅ 资产包生成完成!")
@ -276,10 +293,20 @@ class CharHeroDesignPacker:
"""更新 manifest.hdlp"""
print(f"\n📝 更新 manifest.hdlp...")
required_assets = {"front_half_body", "side_face", "full_body_costume", "expression_sheet"}
is_complete = required_assets.issubset(results.keys())
approval_status = "APPROVED" if is_complete else "DRAFT_GENERATED"
type_label = "已批准" if is_complete else "待质检"
lock_note = (
"⊢ 资产已批准,可用于成片镜头。"
if is_complete
else "⊢ 资产包尚未完整生成/质检,禁止作为成片锁定资产。"
)
manifest_content = f"""# 资产清单 · {self.character_id}
> HLDP://video-ai-system/assets/characters/{self.character_id}/manifest
> 类型: 角色资产 · 已批准
> 类型: 角色资产 · {type_label}
> 建立: D143 · 2026-06-23
> 更新: D144 · 2026-06-24
> 项目: 付费才能修仙 · EP01
@ -289,7 +316,7 @@ class CharHeroDesignPacker:
## 状态
```
approval_status: APPROVED
approval_status: {approval_status}
asset_type: character
canonical_id: {self.character_id}
canonical_name: 苏白
@ -311,19 +338,19 @@ expression_sheet: {results.get("expression_sheet", "NOT_GENERATED")}
## 视觉锁
```
face_shape: 少年脸柔和轮廓白色长发
hair_style: 白色长发束发有发带
costume: 白色内衬 + 蓝色外袍 + 黑色腰带 + 棕色靴子
face_shape: TODO_FROM_APPROVED_ASSET
hair_style: TODO_FROM_APPROVED_ASSET
costume: TODO_FROM_APPROVED_ASSET
age_band: 16
render_style: 3D动画皮克斯风格明亮色彩
color_palette:
render_style: 3D国风漫剧
color_palette: TODO_FROM_APPROVED_ASSET
```
---
## 锁定
资产已批准可用于成片镜头
{lock_note}
禁止使用 candidates/ rejected/ 中的图片作为最终资产
"""

View File

@ -270,6 +270,14 @@ class CharacterDistinctivenessQC:
return results
def save_report(self, result, output_path):
"""保存单张或批量评估报告"""
output_path = Path(output_path)
output_path.parent.mkdir(parents=True, exist_ok=True)
with open(output_path, "w", encoding="utf-8") as f:
json.dump(result, f, ensure_ascii=False, indent=2)
print(f"\n 报告已保存: {output_path}")
def _generate_batch_report(self, results):
"""生成批量评估报告"""
print(f"\n📊 批量评估报告")
@ -301,6 +309,7 @@ def main():
parser.add_argument("--character", type=str, default="CHAR-003-SuBai",
help="角色ID (默认: CHAR-003-SuBai)")
parser.add_argument("--batch", type=str, help="批量评估目录")
parser.add_argument("--output", type=str, help="输出 JSON 报告路径")
args = parser.parse_args()
@ -314,9 +323,13 @@ def main():
result = qc.evaluate_image(args.image)
print(f"\n📋 评估详情:")
print(json.dumps(result, ensure_ascii=False, indent=2))
if args.output:
qc.save_report(result, args.output)
elif args.batch:
results = qc.evaluate_batch(args.batch)
if args.output:
qc.save_report(results, args.output)
if __name__ == "__main__":

View File

@ -33,8 +33,9 @@ sys.path.insert(0, str(PROJECT_ROOT / "engines"))
class LipSyncAdapter:
"""口型适配器"""
def __init__(self, wav2lip_path=None):
def __init__(self, wav2lip_path=None, allow_fallback=False):
self.wav2lip_path = wav2lip_path or PROJECT_ROOT / "tools" / "Wav2Lip"
self.allow_fallback = allow_fallback
self.available = self._check_wav2lip()
def _check_wav2lip(self):
@ -53,7 +54,7 @@ class LipSyncAdapter:
print(f"✅ Wav2Lip 已安装: {self.wav2lip_path}")
return True
def sync_lips(self, video_path, audio_path, output_path=None):
def sync_lips(self, video_path, audio_path, output_path=None, allow_fallback=None):
"""
口型同步
@ -98,9 +99,20 @@ class LipSyncAdapter:
result = self._run_wav2lip(video_path, audio_path, output_path)
return result
# 方法2: 回退 (不处理,只复制视频)
print(f" ⚠️ Wav2Lip 不可用,回退到不处理模式")
print(f" 💡 提示: 安装 Wav2Lip 以获得口型同步能力")
fallback_enabled = self.allow_fallback if allow_fallback is None else allow_fallback
if not fallback_enabled:
print(f" ❌ Wav2Lip 不可用,口型同步未执行")
print(f" 💡 如需调试占位输出,可显式传入 --allow-fallback-copy")
return {
"success": False,
"error": "Wav2Lip 不可用,未执行真实口型同步",
"method": "not-run",
"requires": "Install Wav2Lip and checkpoint wav2lip_gan.pth"
}
# 调试回退: 不处理,只复制视频。必须显式开启,避免生产线假阳性。
print(f" ⚠️ Wav2Lip 不可用,按 --allow-fallback-copy 复制原视频")
print(f" 💡 注意: 该输出不是口型同步成品")
import shutil
shutil.copy2(video_path, output_path)
@ -109,7 +121,7 @@ class LipSyncAdapter:
"success": True,
"output_path": str(output_path),
"method": "fallback(copy)",
"warning": "Wav2Lip 不可用,口型未同步。请安装 Wav2Lip"
"warning": "Wav2Lip 不可用,口型未同步。该文件只能用于调试占位"
}
def _run_wav2lip(self, video_path, audio_path, output_path):
@ -247,6 +259,8 @@ def main():
parser.add_argument("--batch", type=str, help="批量处理配置文件 (JSON)")
parser.add_argument("--wav2lip-path", type=str, help="Wav2Lip 安装路径")
parser.add_argument("--check-sync", action="store_true", help="检查口型同步质量")
parser.add_argument("--allow-fallback-copy", action="store_true",
help="仅调试用: Wav2Lip 不可用时复制原视频并标记为 fallback")
args = parser.parse_args()
@ -276,7 +290,7 @@ def main():
output_dir = config.get("output_dir", "./outputs/lipsync/")
adapter = LipSyncAdapter(args.wav2lip_path)
adapter = LipSyncAdapter(args.wav2lip_path, allow_fallback=args.allow_fallback_copy)
results = adapter.batch_sync(video_audio_pairs, output_dir)
sys.exit(0)
@ -285,7 +299,7 @@ def main():
parser.print_help()
sys.exit(1)
adapter = LipSyncAdapter(args.wav2lip_path)
adapter = LipSyncAdapter(args.wav2lip_path, allow_fallback=args.allow_fallback_copy)
result = adapter.sync_lips(args.video, args.audio, args.output)
if result["success"]:

View File

@ -30,34 +30,43 @@ from datetime import datetime
PROJECT_ROOT = Path(__file__).parent.parent
sys.path.insert(0, str(PROJECT_ROOT / "engines"))
# 从环境变量加载 API 配置
def load_api_config():
""" video-ai-system/.env 加载配置"""
"""仓库 .env、本机密钥文件和环境变量加载配置"""
config = {}
env_file = PROJECT_ROOT / ".env"
if env_file.exists():
with open(env_file, "r") as f:
env_files = [
PROJECT_ROOT / ".env",
Path.home() / "guanghulab-local-secrets" / "video-ai-system.env",
]
for env_file in env_files:
if not env_file.exists():
continue
with open(env_file, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if line and not line.startswith("#"):
key, _, val = line.partition("=")
config[key.strip()] = val.strip()
config[key.strip()] = val.strip().strip('"').strip("'")
for key in ["JIMENG_API_KEY", "JIMENG_BASE_URL", "JIMENG_MODEL"]:
if os.environ.get(key):
config[key] = os.environ[key]
return config
class MultiReferenceVideoAdapter:
"""多参考图视频适配器"""
def __init__(self):
def __init__(self, live_capability_check=False, allow_single_reference_fallback=False):
self.config = load_api_config()
self.api_key = self.config.get("JIMENG_API_KEY", "")
self.base_url = self.config.get("JIMENG_BASE_URL", "https://ark.cn-beijing.volces.com/api/v3")
self.model = self.config.get("JIMENG_MODEL", "doubao-seedance-2-0-260128")
self.live_capability_check = live_capability_check
self.allow_single_reference_fallback = allow_single_reference_fallback
# API 能力探测结果缓存
self._api_capabilities = None
def check_api_capabilities(self):
def check_api_capabilities(self, live=None):
"""
检查 API 是否支持多参考图
返回: {
@ -70,6 +79,7 @@ class MultiReferenceVideoAdapter:
if self._api_capabilities:
return self._api_capabilities
live = self.live_capability_check if live is None else live
print("🔍 检查 Seedance API 多参考图支持...")
# 根据 Volcengine 官方文档 (https://www.volcengine.com/docs/82379/1520757)
@ -83,8 +93,17 @@ class MultiReferenceVideoAdapter:
# { type: "image_url", image_url: { url: "data:image/png;base64,..." } }, # 第二张参考图
# ]
# 实际测试: 尝试提交一个包含2张参考图的请求看是否报错
test_result = self._test_multi_reference()
if not live:
test_result = {
"multi_reference_supported": False,
"max_references": 1,
"supported_types": ["image_url"],
"status": "unverified",
"details": "未执行付费/联网实测;需要 --live-check 才会提交真实 API 探测任务",
"requires_live_check": True
}
else:
test_result = self._test_multi_reference()
self._api_capabilities = test_result
return test_result
@ -94,6 +113,15 @@ class MultiReferenceVideoAdapter:
实际测试 API 是否支持多参考图
方法: 提交一个测试请求包含2张参考图观察响应
"""
if not self.api_key:
return {
"multi_reference_supported": False,
"max_references": 1,
"supported_types": ["image_url"],
"details": "未找到 JIMENG_API_KEY无法执行 live check",
"status": "missing_api_key"
}
# 构造一个最小测试请求
test_prompt = "test multi-reference support"
@ -216,7 +244,16 @@ class MultiReferenceVideoAdapter:
print(f" 2. 后期合成牌匾/场景 (平面追踪 + 贴图)")
print(f" 3. 或使用可灵生成角色Seedance 生成场景,后期合成")
# 回退: 只用第一张参考图
if not self.allow_single_reference_fallback:
return {
"success": False,
"method": "not-run",
"error": "多参考图能力未确认或不支持,未自动回退单参考图以避免误导一致性测试",
"capabilities": capabilities,
"next_step": "使用 --live-check 验证多参考图,或显式传入 --allow-single-reference-fallback 做调试占位"
}
# 回退: 只用第一张参考图。必须显式开启,避免误导牌匾/场景一致性判断。
warning = "API不支持多参考图已回退到单参考图模式。牌匾/场景一致性需要后期合成。"
print(f"\n 🔄 回退: 使用第一张参考图生成...")
@ -336,6 +373,10 @@ class MultiReferenceVideoAdapter:
def main():
parser = argparse.ArgumentParser(description="MULTI-REFERENCE-VIDEO-ADAPTER")
parser.add_argument("--check-api", action="store_true", help="检查API多参考图支持")
parser.add_argument("--live-check", action="store_true",
help="执行真实 API 探测请求,可能产生费用")
parser.add_argument("--allow-single-reference-fallback", action="store_true",
help="多参考图不可用时允许单参考图调试占位")
parser.add_argument("--prompt", type=str, help="提示词")
parser.add_argument("--references", type=str, nargs="+", help="参考图路径列表")
parser.add_argument("--output", type=str, help="输出路径")
@ -344,10 +385,13 @@ def main():
args = parser.parse_args()
adapter = MultiReferenceVideoAdapter()
adapter = MultiReferenceVideoAdapter(
live_capability_check=args.live_check,
allow_single_reference_fallback=args.allow_single_reference_fallback
)
if args.check_api:
capabilities = adapter.check_api_capabilities()
capabilities = adapter.check_api_capabilities(live=args.live_check)
print(f"\n📊 API 能力报告:")
print(f" 多参考图支持: {capabilities['multi_reference_supported']}")
print(f" 最大参考图数: {capabilities['max_references']}")

View File

@ -585,7 +585,12 @@ def main():
print(f"\n⚠️ QC 跳过 (依赖不可用)")
sys.exit(0)
else:
print(f"\n❌ QC 失败: {result.get('error', 'Unknown error')}")
if result.get("error"):
print(f"\n❌ QC 失败: {result['error']}")
else:
issues = result.get("issues") or []
issue_text = "".join(issues) if issues else "未通过阈值"
print(f"\n❌ QC 未通过: {issue_text}")
sys.exit(1)

View File

@ -20,17 +20,24 @@ import os
import sys
import json
import argparse
import importlib.util
from pathlib import Path
from datetime import datetime
PROJECT_ROOT = Path(__file__).parent.parent
sys.path.insert(0, str(PROJECT_ROOT / "engines"))
# 导入现有的 TTS 引擎
# 导入现有的 TTS 引擎。文件名是 tts-engine.py不能用普通 import。
tts_engine_path = PROJECT_ROOT / "engines" / "tts-engine.py"
try:
from tts_engine import generate_speech, generate_by_character, load_voice_config
except ImportError:
print("⚠️ 无法导入 tts-engine将使用简化模式")
spec = importlib.util.spec_from_file_location("tts_engine", tts_engine_path)
tts_engine = importlib.util.module_from_spec(spec)
spec.loader.exec_module(tts_engine)
generate_speech = tts_engine.generate_speech
generate_by_character = tts_engine.generate_by_character
load_voice_config = tts_engine.load_voice_config
except Exception as exc:
print(f"⚠️ 无法导入 tts-engine将使用简化模式: {exc}")
generate_speech = None
generate_by_character = None
@ -270,7 +277,7 @@ class VoiceEmotionCompiler:
variants = [
{"label": "基准", "params": base_params},
{"label": "语速+10%", "params": {**base_params, "rate": f"+{int(base_params['rate'].strip('%+')) + 10}%"},
{"label": "语速+10%", "params": {**base_params, "rate": f"+{int(base_params['rate'].strip('%+')) + 10}%"}},
{"label": "音调+5Hz", "params": {**base_params, "pitch": f"+{int(base_params['pitch'].strip('Hz+')) + 5}Hz"}},
{"label": "音量+10%", "params": {**base_params, "volume": f"+{int(base_params['volume'].strip('%+')) + 10}%"}},
]

View File

@ -0,0 +1,263 @@
# D144 · 视频AI系统8模块验收记录
> HLDP://video-ai-system/experience/D144-8-MODULE-VERIFICATION
> 日期: 2026-06-24
> 入口: 腾讯AI提交的 8 大模块工程验收
> 结论: 框架已进入仓库,但不能整体视为生产完成;需要按下方缺口继续补齐。
---
## 总结
```
overall_status: PARTIAL_PASS
production_ready: false
main_blockers:
- 主角资产包生成未真正接通图片生成适配器
- 口型同步依赖 Wav2Lip 未安装,不能解决“人物说台词”
- 多参考图能力未做真实付费验证,默认不能用于一致性承诺
- EP01 一键生产 CLI 仍读取占位台词,不满足“剧本怎么写就怎么拍”
- 字幕标准工具链仍需独立开发不在本次8模块内完成
```
---
## 模块验收
### 1. CHAR-HERO-DESIGN-PACKER
```
status: NOT_READY
syntax: PASS_AFTER_FIX
production_ready: false
```
发现:
- 原代码直接导入不存在的 Python `image_api_adapter`,仓库当前只有 JS 图片适配器,启动即崩。
- 原代码会在资产不完整时把 `manifest.hdlp` 写成 `APPROVED`,会污染后续角色锁定。
- 原提示词带有未经剧本/资产锁确认的视觉默认值,例如白发、蓝眼、蓝袍、皮克斯风格,容易造成角色漂移。
已修:
- 图片适配器未接通时不崩溃,明确提示未生成。
- 只有 4/4 资产完整生成时才允许 `APPROVED`;否则为 `DRAFT_GENERATED`。
- 默认风格改为 3D国风漫剧并要求服装来自角色资产清单不得自由改色。
后续:
- 需要开发 Python 到现有 JS 图片适配器的桥接,或统一改成 Node CLI 调用。
- 需要把“主角辨识度设计稿/正侧全身/表情表/色彩锁”作为独立资产包生成和人工确认流程。
---
### 2. CHARACTER-DISTINCTIVENESS-QC
```
status: PARTIAL_PASS
syntax: PASS
report_output: PASS_AFTER_FIX
production_ready: false
```
实测:
- 输入 `video-ai-system/assets/references/EP01-P0/ref-char003-subai-plus-tdz-plaque.png`
- 输出 `/tmp/guanghulab-module-check/character-qc.json`
- 结果: `overall_score: 6.35/10`, `verdict: FAIL`
说明:
- 这个结论与编辑意见“主角太普通、像路人甲”一致。
- 当前算法是基础 OpenCV 分数,只能做第一层粗筛,不能替代人眼/多模型视觉评审。
已修:
- 增加 `--output`,允许质检报告落盘进入经验库。
后续:
- 接入图像理解模型做“主角感/路人感/记忆点”语义评分。
- 加入同镜头前后角色一致性对比,而不是只看单张图。
---
### 3. MULTI-REFERENCE-VIDEO-ADAPTER
```
status: GUARDED_NOT_VERIFIED
syntax: PASS
production_ready: false
```
发现:
- 原 `--check-api` 会直接提交真实视频生成请求,可能产生费用。
- 原代码只读仓库 `.env`,不读本机密钥文件。
- 多参考图未确认时自动回退单参考图,会误导牌匾/角色/场景一致性判断。
已修:
- 默认 `--check-api` 只做无付费预检。
- 只有显式传入 `--live-check` 才会提交真实 API 探测请求。
- 读取本机 `~/guanghulab-local-secrets/video-ai-system.env`。
- 多参考图未确认时不自动回退;只有显式 `--allow-single-reference-fallback` 才允许调试占位。
后续:
- 需要一次受控 live-check确认 Seedance/豆包视频 API 是否真支持多参考图。
- 如果不支持,必须走“角色视频 + 牌匾/场景后期合成”的工程路线。
---
### 4. VOICE-EMOTION-COMPILER
```
status: PASS_FOR_TTS_PARAM_COMPILE
syntax: PASS_AFTER_FIX
production_ready: partial
```
发现:
- 原代码有语法错误。
- 原代码用普通 import 导入 `tts-engine.py`,文件名含连字符,无法导入。
已修并实测:
- 修复语法错误。
- 用动态导入接上 `tts-engine.py`。
- 实测生成苏白情绪配音 MP3 成功: `/tmp/guanghulab-module-check/subai-emotion.mp3`
后续:
- Edge-TTS 可做低成本测试,但商业成片建议继续 A/B 测豆包语音、火山语音或更适合角色对白的声音模型。
- 需要按角色建立“台词情绪标签 -> 音色/语速/音高/停顿”表。
---
### 5. LIPSYNC-ADAPTER
```
status: FAIL_DEPENDENCY_MISSING
syntax: PASS_AFTER_FIX
production_ready: false
```
发现:
- Wav2Lip 未安装。
- 原代码在 Wav2Lip 不可用时复制原视频并返回成功,会把“没做口型”伪装为“口型完成”。
已修:
- 默认无 Wav2Lip 时返回失败。
- 只有显式传入 `--allow-fallback-copy` 才允许复制原视频,并标记为调试占位。
实测:
- 当前返回失败: `Wav2Lip 不可用,未执行真实口型同步`
后续:
- 安装 Wav2Lip 或改接可商用口型/视频驱动 API。
- 需要口型 QC音频峰值与嘴部开合是否同步不能只看生成成功。
---
### 6. AUDIO-MIXER
```
status: BASIC_PASS
production_ready: partial
```
实测:
- 单音轨输出成功: `/tmp/guanghulab-module-check/mix-single.mp3`
缺口:
- 当前对白压低 BGM 是简化处理,不是真正精细侧链压缩。
- 需要对白优先、BGM 自动 ducking、响度标准、峰值保护、短视频平台响度目标。
后续:
- 开发基于 FFmpeg sidechaincompress / loudnorm 的商业混音预设。
- 输出混音 QC 报告对白响度、BGM 响度、峰值、电平余量。
---
### 7. SHOT-QC-AUTOMATION
```
status: PARTIAL_PASS
syntax: PASS
production_ready: false
```
实测:
- 输入移动硬盘样片: `TEST-SUBTITLE-007-RUN002-REFERENCE-DRAMA.mp4`
- 输出 `/tmp/guanghulab-module-check/qc-after-fix.json`
- 结果: 检测到横屏 `1112x834`,失败原因 `竖屏比例错误`
已修:
- 原 CLI 失败时只显示 `Unknown error`;已改成输出真实失败项。
- 依赖清单补充 `numpy`, `opencv-python`, `requests`。
缺口:
- OCR 未安装,字幕/牌匾文字检查被跳过。
- 现代物品检测仍是 TODO。
- 换脸检查只是粗糙直方图,不足以判定角色一致性。
后续:
- 安装/配置 OCR。
- 接 YOLO 或视觉模型做现代物品、遮挡、文字、角色漂移检查。
---
### 8. EP01-SHOT03-PRODUCTION-CLI
```
status: DRY_RUN_ONLY
syntax: PASS
production_ready: false
```
实测:
- `--dry-run` 可执行完整步骤列表。
重大问题:
- 配置读取仍显示 `台词: 苏白原文台词`,不是剧本原文台词。
- 这不满足用户要求:剧本怎么写,就怎么拍;不能用占位台词进入生产。
后续:
- 必须接入剧本/分镜头源文件,逐字锁定台词。
- 每个镜头需要输出“剧本文本 -> 提示词 -> 画面 -> 配音 -> 字幕”的可追溯链路。
---
## 本次工程修复清单
```
fixed_files:
- engines/voice-emotion-compiler.py
- engines/char-hero-design-packer/char-hero-design-packer.py
- engines/character-distinctiveness-qc/character-distinctiveness-qc.py
- engines/lipsync-adapter.py
- engines/multi-reference-video-adapter.py
- engines/shot-qc-automation.py
- requirements-video-ai.txt
```
---
## 下一步优先级
```
P0:
- 字幕商业标准渲染工具链
- 真实口型同步方案
- 剧本原文锁定与 EP01 CLI 台词读取修复
- 主角资产包真实生成与人工确认
P1:
- 多参考图 live-check
- 角色一致性跨镜头 QC
- BGM/对白混音 loudness + ducking
P2:
- OCR/牌匾文字 QC
- 现代物品检测
- 成本账本与模型可用性检查
```
---
## 验收结论
```
腾讯AI这次提交的8个模块不能按“全部开发完成”验收。
准确结论是: 工程骨架已建立其中语音参数编译、基础混音、基础QC可继续用
主角资产生成、多参考视频、口型同步、EP01一键生产仍是生产阻塞项。
```

View File

@ -1,7 +1,7 @@
# 付费才能修仙 · 3D漫剧主线 · 项目状态
> HLDP://video-ai-system/memory/zai-fu-fei-xiu-xian/STATUS
> 更新: D143 · 2026-06-23 · preview-002复盘·制片厂化重启
> 更新: D144 · 2026-06-24 · 8模块验收·生产阻塞项确认
> 铸渊 ICE-GL-ZY001
> 国作登字-2026-A-00037559
@ -119,6 +119,7 @@ preview-003: 暂不生成。
| 苏白TTS配音 | ✅ 工程测试通过 | `outputs/tests/TEST-TTS-001-SUBAI-RUN-001-REPORT.hdlp` |
| 模型/成本路线 | ✅ 已建立 | `knowledge/D144-MODEL-COST-ROUTE.hdlp` |
| 腾讯AI开发交接 | ✅ 已建立 | `plans/D144-TENCENT-AI-DEV-HANDOFF.hdlp` |
| 腾讯AI 8模块代码 | 🟡 部分通过 | `experience/D144-8-MODULE-VERIFICATION.hdlp` · 框架已入仓,生产阻塞项仍在 |
| 广告牌资产 | ✅ 草案 | `assets/props/PROP-FREE-AD-BOARD/manifest.hdlp` |
| 广告牌文字贴图 | ✅ PNG已生成 | `assets/props/PROP-FREE-AD-BOARD/texture/free-ad-board-texture.png` |
| 百宗会场景资产 | ✅ 草案 | `assets/envs/ENV-002-Baizonghui/manifest.hdlp` |
@ -218,6 +219,11 @@ preview-003: 暂不生成。
- [ ] 开发 reference-subtitle-analyzer / ASS渲染 / 字体管理 / 安全区QC 字幕工具链
- [x] 重定性 RUN-002: 牌匾一致性失败,但百宗会人群氛围可用
- [x] 测试苏白Edge-TTS工程配音 → `outputs/tests/TEST-TTS-001-SUBAI-RUN-001-REPORT.hdlp`
- [x] 验收腾讯AI 8模块代码 → `experience/D144-8-MODULE-VERIFICATION.hdlp`
- [ ] 接通主角资产包真实图片生成适配器,禁止未完整资产写入 APPROVED
- [ ] 安装或替换真实口型同步方案,禁止复制视频冒充口型完成
- [ ] 修复 EP01-SHOT03 CLI 台词读取,占位台词不得进入生产
- [ ] 受控验证 Seedance/豆包视频多参考图能力,未验证前不得承诺跨镜一致
- [x] 建立模型/成本路线 → `knowledge/D144-MODEL-COST-ROUTE.hdlp`
- [x] 建立腾讯AI人格体开发交接清单 → `plans/D144-TENCENT-AI-DEV-HANDOFF.hdlp`
- [ ] 生成E1-SHOT03专用苏白底片: 上方/身后预留牌匾空间

View File

@ -2,3 +2,10 @@ edge-tts>=7.2.8
pysrt>=1.1.2
cairosvg>=2.9.0
Pillow>=12.2.0
numpy>=2.0.0
opencv-python>=4.10.0
requests>=2.32.0
# Optional production QC dependencies:
# pytesseract>=0.3.13 # requires system tesseract binary
# ultralytics>=8.3.0 # modern-item detection, not wired yet