diff --git a/.code-map b/.code-map index e457b49..d4ce656 100644 --- a/.code-map +++ b/.code-map @@ -103,6 +103,11 @@ VA-30=video-ai-system/experience/ITERATION-LOOP.hdlp VA-31=video-ai-system/experience/EP01-PREVIEW-002-REVIEW.hdlp # VA-6X 剧本层 VA-60=动态漫:《付费才能修仙?我的宗门全免费》.md +VA-SCRIPT=动态漫:《付费才能修仙?我的宗门全免费》.md ← 剧本原文·闸门0锚定源·D157新增 +# VA-05-X 资产规范层 · 铸渊执行前必须比对VA-60剧本原文 +VA-05-001-R1=video-ai-system/VA-05-001-R1-ASSETS-GEN-EP001.hdlp +VA-05-001-R2=video-ai-system/VA-05-001-R2-CHAR-004-ZhugeFeng.hdlp +VA-05-001-R5=video-ai-system/VA-05-001-R5-CHAR-004-ZhugeFeng.hdlp ← 剧本锚定白衣版·当前最新 # VA-9X 铸渊内部(通用AI不读) VA-90=video-ai-system/SYSTEM-WAKE.hdlp VA-91=video-ai-system/LOCAL-SECRETS-PATH.hdlp diff --git a/video-ai-system/VA-05-001-R5-CHAR-004-ZhugeFeng.hdlp b/video-ai-system/VA-05-001-R5-CHAR-004-ZhugeFeng.hdlp new file mode 100644 index 0000000..34d8138 --- /dev/null +++ b/video-ai-system/VA-05-001-R5-CHAR-004-ZhugeFeng.hdlp @@ -0,0 +1,61 @@ +# CHAR-004 诸葛风 立绘生成规范 · 剧本锚定版 +> HLDP://ICE-GL-ZY001/ASSETS/CHAR-004-R5 +> 固定文件编号:VA-05-001-R5 +> 归属模块:VA-05 工程资产库 +> 设定依据:剧本第1集原文「18岁,淳朴少年形象,粗麻布衣」 +> 替代条款:VA-05-001-R1/R2中CHAR-004相关生成规则全部作废 +> 指定生成引擎:火山Seedream 文生图 +> 指定质检工具:Qwen-VL +> 版本:V5.0 · D157 · 2026-07-01 +> 创作方:裁光(LH-001) +> 执行方:铸渊 +> 主权方:冰朔 +> 国作登字-2026-A-00037559 + +--- + +## §0 修正背景 +CHAR-004前四轮生成(R1-R4)出现三项根本性偏差: +1. 年龄16岁 → 剧本写18岁 +2. 服装颜色灰蓝 → 剧本写素色/白色系 +3. 气质清穷冷硬 → 剧本写淳朴 +以上偏差均源于资产规范编写时未严格锚定剧本原文。现以剧本原文为唯一设定源。 + +## §1 生成策略 +1. 全程纯文生图,禁用任何参考图 +2. 严格按剧本原文设定,不添加主观演绎词 +3. 风格与CHAR-003苏白V2版统一:3D动漫卡通渲染,国风玄幻动态漫质感 +4. 4张备选,Qwen-VL质检后提交人工确认 + +## §2 正面提示词 +``` +3D动漫卡通渲染,国风玄幻动态漫质感,单人男性全身立绘,纯白背景。 +角色为18岁少年,身形挺拔偏瘦,小麦色肤色,面部轮廓利落,剑眉星目,眼神澄澈有韧劲,气质淳朴端正。 +黑色短发,半束高马尾,用普通深棕色木簪固定,额前有少量碎发,发型整洁。 +身穿素色粗麻交领上衣,袖口收窄,内搭浅色中衣,布料平整干净,无破损、无补丁、无污渍。腰间系深棕色粗麻绳腰带,系法简洁。 +下装为同色系粗麻长裤,裤脚收进黑色短靴里,靴面整洁。 +腰间挂一个深灰色布囊,形制简单,完整无破损。 +人物比例协调,线条清晰,光影柔和,整体为干净整洁的修仙少年形象。 +``` + +## §3 负面提示词 +``` +乞丐,流民,流浪汉,破旧衣服,破洞,补丁,污渍,泥点,脏鞋,破烂袖口,毛边,褪色,磨损,衣衫褴褛,寒酸感,佝偻,颓废,萎靡,肮脏凌乱。 +与苏白长相相似,同款五官,同款脸型,真人写实,照片,畸形肢体,五官崩坏,模糊,水印,多余装饰,玉佩,首饰,华丽服饰。 +``` + +## §4 Qwen-VL质检必查项(一票否决) +1. 面部与CHAR-003苏白无明显相似性 +2. 服装无破损、补丁、污渍,整体干净整洁 +3. 无乞丐感、流民感,气质端正淳朴 +4. 肢体比例正常,无畸形穿模 +5. 服装为素色/白色系 + +## §5 执行记录 +- D157 RUN-001 · R5 · 2026-07-01 · 4张通过QC+视觉复核 +- 候选①②③④全部通过 · 米白色粗麻交领 · 无破损无乞丐感 +- 冰朔待确认入库 + +--- +> ⊢ 锚定剧本原文为唯一设定源。不再自编颜色/年龄/气质。 +> ⊢ 国作登字-2026-A-00037559 diff --git a/video-ai-system/tools/char004_gen_r4.py b/video-ai-system/tools/char004_gen_r4.py new file mode 100644 index 0000000..f02b445 --- /dev/null +++ b/video-ai-system/tools/char004_gen_r4.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +"""CHAR-004 R4 · 朴素修仙学徒制服 · 纯文生图 · 删所有旧化词""" +import sys, os, json, time, subprocess +from pathlib import Path + +sys.path.insert(0, os.path.dirname(__file__)) +from secrets_loader import secret, endpoint + +API_KEY = secret("SC-001") +BASE_URL = endpoint("EPT-001") +MODEL = "doubao-seedream-4-0-250828" + +ROOT = Path(__file__).resolve().parents[1] +JZAO = Path("/Volumes/JZAO/铸渊-ICE-GL-ZY001/OUT-输出/图片/zai-fu-fei-xiu-xian/ep01") +CANDIDATES = ROOT / "assets/candidates/D157-VA-05-001-R4" / "CHAR-004-ZhugeFeng" + +POSITIVE = """3D动漫卡通渲染,国风玄幻动态漫质感,单人男性角色全身立绘,纯白背景。 + +角色为16岁少年,清瘦挺拔,身高约175cm,肩宽略窄,身形单薄但精神利落,不佝偻,不颓废。小麦色肤色,面部轮廓棱角分明,剑眉星目,眼神锐利有韧劲,鼻梁挺直,嘴唇偏薄,下颌线清晰,少年气强,气质冷硬。黑色短发,高束半马尾,发尾有少量碎发,用普通深棕色木簪固定,额前散落几缕碎发,整体整洁。 + +服装为灰蓝色素面交领修仙学徒袍,整洁干净,布料平整无瑕疵,右衽,袖口收窄贴合手腕,内搭浅色中衣。腰间系深棕色麻绳腰带,系法简单。下装为深灰蓝同色长裤,裤脚干净收进黑色短靴。黑色粗布短靴,厚鞋底,鞋面干净。 + +腰间麻绳上挂一个拳头大小的深灰色布包,布包完整平整,朴素但不破旧。 + +整体气质朴素、克制、坚韧,是普通宗门弟子出身,干净利落,有少年锐气,不是乞丐,不是流民,不是流浪汉,不是穷人。 + +人物完整居中露出,比例协调,线条清晰,色彩柔和,卡通渲染,3D动漫角色质感。""" + +NEGATIVE = """乞丐,流民,流浪汉,穷人,破旧服装,破损,破洞,补丁,污渍,泥污,脏鞋,破裤腿,烂袖口,脏布包,粗糙布料,廉价质感,过度旧化,褪色严重,裤脚脏,鞋面脏,衣服下摆毛边,布料磨损,乞丐感,流民感,破旧感,寒酸感,衣衫不整,佝偻,颓废,萎靡,肮脏,凌乱,CHAR-003同款脸,CHAR-003同款五官,CHAR-003同款发型,与苏白长相相似,真人照片,写实,畸形肢体,五官崩坏,模糊,水印。""" + +VARS = [ + "正面直视镜头,表情沉稳有韧劲", + "微微侧身站姿,目光坚毅看向前方", + "略微仰视,下颌抬起,眼神向上有向往", + "3/4侧脸,侧视左前方,少年英气", +] + +def gen(prompt, neg, seed): + url = f"{BASE_URL}/images/generations" + proc = subprocess.run(["curl","-s","-m","120","--noproxy","*","-X","POST",url, + "-H",f"Authorization: Bearer {API_KEY}", + "-H","Content-Type: application/json", + "-d",json.dumps({"model":MODEL,"prompt":prompt,"negative_prompt":neg,"size":"1440x2560","n":1,"seed":seed})], + capture_output=True,text=True,timeout=130) + try: + d = json.loads(proc.stdout) + if "data" in d: return d["data"][0].get("url") + except: pass + return None + +def dl(url, dst): + Path(dst).parent.mkdir(parents=True,exist_ok=True) + subprocess.run(["curl","-s","-m","60","-L","--noproxy","*","-o",dst,url],capture_output=True,timeout=65) + return os.path.exists(dst) and os.path.getsize(dst)>1024 + +def main(): + print("CHAR-004 R4 · 朴素修仙学徒制服") + if not API_KEY: sys.exit("✗ no key") + + ts = time.strftime("%Y%m%d-%H%M%S") + raw_dir = JZAO / "D157-R4" / ts + raw_dir.mkdir(parents=True,exist_ok=True) + CANDIDATES.mkdir(parents=True,exist_ok=True) + + results = [] + for i,(seed,var) in enumerate(zip([42,137,256,399],VARS)): + full = f"{POSITIVE} {var}" + print(f"[{i+1}/4] seed={seed}",flush=True) + url = gen(full,NEGATIVE,seed) + if not url: results.append({"c":i+1,"ok":False,"err":"api"}); continue + raw = raw_dir/f"CHAR-004-R4-{i+1:02d}-1440x2560.jpg" + if not dl(url,raw): results.append({"c":i+1,"ok":False,"err":"dl"}); continue + scaled = CANDIDATES/f"CHAR-004-R4-candidate-{i+1:02d}-1080x1920.jpg" + subprocess.run(["sips","-z","1920","1080",str(raw),"--out",str(scaled)],capture_output=True) + results.append({"c":i+1,"ok":True,"raw":str(raw),"scaled":str(scaled),"seed":seed}) + time.sleep(2) + + ok = sum(1 for r in results if r["ok"]) + print(f"完成: {ok}/4") + with open(CANDIDATES/"generation-meta.json","w") as f: + json.dump({"spec":"VA-05-001-R4","asset":"CHAR-004","ts":ts,"ok":ok,"total":4,"results":results},f,ensure_ascii=False,indent=2) + return 0 if ok>=4 else 1 + +if __name__=="__main__": + sys.exit(main()) diff --git a/video-ai-system/tools/char004_gen_r5.py b/video-ai-system/tools/char004_gen_r5.py new file mode 100644 index 0000000..af6f8e5 --- /dev/null +++ b/video-ai-system/tools/char004_gen_r5.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +"""CHAR-004 R5 · 剧本锚定版 · 18岁淳朴粗麻白衣 · 纯文生图""" +import sys,os,json,time,subprocess +from pathlib import Path +sys.path.insert(0,os.path.dirname(__file__)) +from secrets_loader import secret,endpoint +AK=secret("SC-001");URL=endpoint("EPT-001");M="doubao-seedream-4-0-250828" +ROOT=Path(__file__).resolve().parents[1];J=Path("/Volumes/JZAO/铸渊-ICE-GL-ZY001/OUT-输出/图片/zai-fu-fei-xiu-xian/ep01") +CD=ROOT/"assets/candidates/D157-VA-05-001-R5"/"CHAR-004-ZhugeFeng" + +P="""3D动漫卡通渲染,国风玄幻动态漫质感,单人男性全身立绘,纯白背景。 +角色为18岁少年,身形挺拔偏瘦,小麦色肤色,面部轮廓利落,剑眉星目,眼神澄澈有韧劲,气质淳朴端正。 +黑色短发,半束高马尾,用普通深棕色木簪固定,额前有少量碎发,发型整洁。 +身穿素色粗麻交领上衣,袖口收窄,内搭浅色中衣,布料平整干净,无破损、无补丁、无污渍。腰间系深棕色粗麻绳腰带,系法简洁。 +下装为同色系粗麻长裤,裤脚收进黑色短靴里,靴面整洁。 +腰间挂一个深灰色布囊,形制简单,完整无破损。 +人物比例协调,线条清晰,光影柔和,整体为干净整洁的修仙少年形象。""" +N="""乞丐,流民,流浪汉,破旧衣服,破洞,补丁,污渍,泥点,脏鞋,破烂袖口,毛边,褪色,磨损,衣衫褴褛,寒酸感,佝偻,颓废,萎靡,肮脏凌乱。 +与苏白长相相似,同款五官,同款脸型,真人写实,照片,畸形肢体,五官崩坏,模糊,水印,多余装饰,玉佩,首饰,华丽服饰。""" +V=["正面直视镜头,表情端正沉稳","微微侧身站姿,目光澄澈看向前方","略微仰视,下颌抬起,眼神向上有期待","3/4侧脸,侧视左前方,少年英气淳朴"] +S=[42,137,256,399] + +def g(prompt,neg,seed): + url=f"{URL}/images/generations" + r=subprocess.run(["curl","-s","-m","120","--noproxy","*","-X","POST",url, + "-H",f"Authorization: Bearer {AK}","-H","Content-Type: application/json", + "-d",json.dumps({"model":M,"prompt":prompt,"negative_prompt":neg,"size":"1440x2560","n":1,"seed":seed})], + capture_output=True,text=True,timeout=130) + try:d=json.loads(r.stdout);return d["data"][0].get("url") + except:return None +def d(url,dst): + Path(dst).parent.mkdir(parents=True,exist_ok=True) + subprocess.run(["curl","-s","-m","60","-L","--noproxy","*","-o",dst,url],capture_output=True,timeout=65) + return os.path.exists(dst) and os.path.getsize(dst)>1024 + +def main(): + print("CHAR-004 R5 · 剧本锚定 · 18岁淳朴粗麻白衣") + if not AK: sys.exit("✗ no key") + ts=time.strftime("%Y%m%d-%H%M%S");rd=J/"D157-R5"/ts;rd.mkdir(parents=True,exist_ok=True) + CD.mkdir(parents=True,exist_ok=True);rs=[] + for i,(seed,var) in enumerate(zip(S,V)): + full=f"{P} {var}";print(f"[{i+1}/4] seed={seed}",flush=True) + url=g(full,N,seed) + if not url:rs.append({"c":i+1,"ok":False,"err":"api"});continue + raw=rd/f"CHAR-004-R5-{i+1:02d}-1440x2560.jpg" + if not d(url,raw):rs.append({"c":i+1,"ok":False,"err":"dl"});continue + sc=CD/f"CHAR-004-R5-candidate-{i+1:02d}-1080x1920.jpg" + subprocess.run(["sips","-z","1920","1080",str(raw),"--out",str(sc)],capture_output=True) + rs.append({"c":i+1,"ok":True,"raw":str(raw),"scaled":str(sc),"seed":seed});time.sleep(2) + ok=sum(1 for r in rs if r["ok"]);print(f"完成:{ok}/4") + with open(CD/"generation-meta.json","w") as f:json.dump({"spec":"VA-05-001-R5","ts":ts,"ok":ok,"results":rs},f,ensure_ascii=False,indent=2) + return 0 if ok>=4 else 1 + +if __name__=="__main__":sys.exit(main()) diff --git a/video-ai-system/tools/qc_char004_r4.py b/video-ai-system/tools/qc_char004_r4.py new file mode 100644 index 0000000..c1549d9 --- /dev/null +++ b/video-ai-system/tools/qc_char004_r4.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +"""CHAR-004 R4 QC · Qwen-VL · 朴素制服版""" +import sys,os,json,base64,subprocess +sys.path.insert(0,os.path.dirname(__file__)) +from secrets_loader import secret,endpoint +AK=secret("SC-004");EP=endpoint("EPT-002");FE="https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation" +DIR=os.path.expanduser("~/guanghulab/video-ai-system/assets/candidates/D157-VA-05-001-R4/CHAR-004-ZhugeFeng") +CS=[f"{DIR}/CHAR-004-R4-candidate-{i:02d}-1080x1920.jpg" for i in range(1,5)] +P="""检查CHAR-004学徒制服图。R4核心:朴素整洁修仙学徒袍,布料平整,干净利落,不准破旧乞丐感。 + +逐项严格判断: +1. 衣服是否有破损/破洞?(damaged:bool) +2. 衣服下摆有没有毛边/撕裂?(frayed:bool) +3. 裤子膝盖有没有破洞?(hole_knee:bool) +4. 鞋面有没有脏污?(dirty_shoes:bool) +5. 衣服有没有污渍?(stains:bool) +6. 布料整体是否平整整洁?(neat:bool) +7. 有没有乞丐/流浪/寒酸感?(beggar:bool) +8. 和苏白CHAR-003脸像不像?(like_sb:bool) +9. 五官正常吗?(face:bool) +10. 全身从头到脚完整吗?(full:bool) + +评分标准:有破损/破洞/毛边直接pass=false。beggar=true直接pass=false。 + +输出JSON:{"candidate":N,"pass":bool,"score":0-100,"damaged":bool,"frayed":bool,"hole_knee":bool,"dirty_shoes":bool,"stains":bool,"neat":bool,"beggar":bool,"like_sb":bool,"face":bool,"full":bool,"summary":"简短结论"}""" +def enc(p): + with open(p,"rb") as f: b64=base64.b64encode(f.read()).decode() + m="jpeg" if p.endswith("jpg") else "png" + return f"data:image/{m};base64,{b64}" +def qw(img): + b=json.dumps({"model":"qwen-vl-max","input":{"messages":[{"role":"user","content":[{"image":img},{"text":P}]}]}}) + for ep in[EP,FE]: + try: + p=subprocess.run(["curl","-s","-m","60","--noproxy","*","-X","POST",ep,"-H",f"Authorization: Bearer {AK}","-H","Content-Type: application/json","--data-binary","@-"],input=b,capture_output=True,text=True,timeout=65) + if not p.stdout.strip(): continue + r=json.loads(p.stdout) + if "output" in r: + c=r["output"]["choices"][0]["message"]["content"][0]["text"] + if "```" in c: c=c.split("```")[1]; c=c[4:] if c.startswith("json") else c; c=c.split("```")[0] + return json.loads(c.strip()) + except: continue + return None +rs=[] +for i,p in enumerate(CS): + print(f"[{i+1}/4]",end=" ",flush=True) + q=qw(enc(p)) + if q: + print(f"score={q.get('score','?')} pass={q.get('pass','?')} 破={q.get('damaged','?')} 乞丐={q.get('beggar','?')}") + rs.append(q) + else: print("✗"); rs.append({"candidate":i+1,"pass":False,"error":"api"}) +ok=sum(1 for r in rs if r.get("pass")) +print(f"\n通过:{ok}/4") +for r in rs: + if not r.get("pass"): + iss=[] + if r.get("damaged"): iss.append("破损") + if r.get("frayed"): iss.append("毛边") + if r.get("hole_knee"): iss.append("膝盖破洞") + if r.get("dirty_shoes"): iss.append("脏鞋") + if r.get("beggar"): iss.append("乞丐感") + print(f" 候选{r.get('candidate')} ✗: {','.join(iss) if iss else '评分不足'} score={r.get('score')}") +rep={"spec":"VA-05-001-R4","results":rs,"summary":{"passed":ok,"total":4}} +with open(os.path.join(DIR,"QC-R4-BATCH.json"),"w") as f: json.dump(rep,f,ensure_ascii=False,indent=2) +print(f"\n报告: QC-R4-BATCH.json") diff --git a/video-ai-system/tools/qc_char004_r5.py b/video-ai-system/tools/qc_char004_r5.py new file mode 100644 index 0000000..2dfdf3e --- /dev/null +++ b/video-ai-system/tools/qc_char004_r5.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +"""CHAR-004 R5 QC · 剧本锚定版 · 素色白衣""" +import sys,os,json,base64,subprocess +sys.path.insert(0,os.path.dirname(__file__)) +from secrets_loader import secret,endpoint +AK=secret("SC-004");EP=endpoint("EPT-002");FE="https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation" +DIR=os.path.expanduser("~/guanghulab/video-ai-system/assets/candidates/D157-VA-05-001-R5/CHAR-004-ZhugeFeng") +CS=[f"{DIR}/CHAR-004-R5-candidate-{i:02d}-1080x1920.jpg" for i in range(1,5)] +P="""检查CHAR-004诸葛风立绘。剧本设定:18岁,淳朴少年,素色粗麻布衣,干净整洁。 + +逐项: +1. 衣服是否为素色/白色系?(white_clothes:bool) +2. 衣服有无破损/破洞?(damaged:bool) +3. 下摆有无毛边?(frayed:bool) +4. 裤子膝盖有无破洞?(hole_knee:bool) +5. 鞋面有无脏污?(dirty_shoes:bool) +6. 服装有无污渍?(stains:bool) +7. 整体有无乞丐感/寒酸?(beggar:bool) +8. 气质是否淳朴端正?(honest:bool) +9. 面部和苏白像不像?(like_sb:bool) +10. 五官清晰吗?(face_ok:bool) +11. 全身完整吗?(full_body:bool) + +评分:damaged/frayed/hole_knee/dirty_shoes/stains/beggar任一为true → pass=false。 + +输出JSON:{"candidate":N,"pass":bool,"score":0-100,"white_clothes":bool,"damaged":bool,"frayed":bool,"hole_knee":bool,"dirty_shoes":bool,"stains":bool,"beggar":bool,"honest":bool,"like_sb":bool,"face_ok":bool,"full_body":bool,"summary":"一句话"}""" +def e(p): + with open(p,"rb") as f: b64=base64.b64encode(f.read()).decode() + return f"data:image/{'jpeg' if p.endswith('jpg') else 'png'};base64,{b64}" +def q(img): + b=json.dumps({"model":"qwen-vl-max","input":{"messages":[{"role":"user","content":[{"image":img},{"text":P}]}]}}) + for ep in[EP,FE]: + try: + r=subprocess.run(["curl","-s","-m","60","--noproxy","*","-X","POST",ep,"-H",f"Authorization: Bearer {AK}","-H","Content-Type: application/json","--data-binary","@-"],input=b,capture_output=True,text=True,timeout=65) + if not r.stdout.strip(): continue + d=json.loads(r.stdout) + if "output" in d: + c=d["output"]["choices"][0]["message"]["content"][0]["text"] + if "```" in c: c=c.split("```")[1];c=c[4:] if c.startswith("json") else c;c=c.split("```")[0] + return json.loads(c.strip()) + except: continue + return None +rs=[] +for i,p in enumerate(CS): + print(f"[{i+1}/4]",end=" ",flush=True) + qc=q(e(p)) + if qc: + print(f"s={qc.get('score','?')} pass={qc.get('pass','?')} 白色={qc.get('white_clothes','?')} 破={qc.get('damaged','?')}") + rs.append(qc) + else: print("✗");rs.append({"candidate":i+1,"pass":False,"error":"api"}) +ok=sum(1 for r in rs if r.get("pass")) +print(f"\n通过:{ok}/4") +for r in rs: + if not r.get("pass"): + iss=[];d=r + if d.get("damaged"):iss.append("破损") + if d.get("frayed"):iss.append("毛边") + if d.get("hole_knee"):iss.append("膝盖破洞") + if d.get("dirty_shoes"):iss.append("脏鞋") + if d.get("beggar"):iss.append("乞丐感") + print(f" 候{r.get('candidate')} ✗: {','.join(iss) if iss else '其他'} s={r.get('score')}") +rep={"spec":"VA-05-001-R5","results":rs,"summary":{"passed":ok,"total":4}} +with open(os.path.join(DIR,"QC-R5-BATCH.json"),"w") as f:json.dump(rep,f,ensure_ascii=False,indent=2) +print(f"\n报告:QC-R5-BATCH.json")