guanghulab/video-ai-system/tools/char004_gen_r4.py
冰朔 6e06ebe6f2
Some checks failed
自动更新代码和重启 / update-and-restart (push) Has been cancelled
CI检查 + 自动部署 / check (push) Has been cancelled
CI检查 + 自动部署 / deploy (push) Has been cancelled
D157 · CHAR-004 R5剧本锚定版 · .code-map新增VA-60/VA-05-X映射 · 闸门0规则封装
2026-07-01 15:21:13 +08:00

86 lines
4.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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())