#!/usr/bin/env python3
from pathlib import Path
import subprocess, os, json, re, datetime

BASE = Path('/Users/bot1/Volumes/root_for_ai/AI工作区/通用_产品宣传视频_古钱币杜邦纸钱袋包_20260530_1702/outputs/dreamina-seedance2-storyboard3-two-5s-segments-20260530')
BIN = '/Users/bot1/.hermes/profiles/video/home/.local/bin/dreamina'
CROPS = BASE/'crops'
segments = [
    {
        'id': '3-1-1_to_3-1-2',
        'first': CROPS/'分镜3-1-1.png',
        'last': CROPS/'分镜3-1-2.png',
        'prompt': '''使用分镜3-1-1作为首帧、分镜3-1-2作为尾帧，生成一段5秒、3:4竖版、连续单画面视频。两张图只作为首尾状态参考，成片不要出现九宫格、分镜板、拼贴图、画中画、边框或文字说明。

首帧画面：浅米色桌面上有三枚拟人化古钱币小角色正在快速逃跑：金色裂纹圆片、灰银桥形币、绿色长柄铲形币。它们保留各自钱币身体、短圆手脚和旧金属质感，身体前倾，脚步急促，桌面上有轻微速度线和尘团。

动作过程：镜头跟随三枚钱币小角色向前逃跑，随后来自前方或侧前方的钱袋包方向出现柔和吸引力。三枚钱币先继续奔跑，然后身体被轻轻拉起，运动方向从贴着桌面奔跑逐渐变成向前上方漂移。它们边缘开始散出细小金色光点，光尘围绕身体旋转，但钱币形状仍然能辨认。

尾帧画面：三枚钱币被引力吸起，周围出现金色光点和光尘，金色裂纹圆片在前景，灰银桥形币悬在中上方，绿色长柄铲形币在侧后方。整体是暖金色光效与浅米色桌面环境。

保真要求：三枚逃跑钱币以参考图为准：金色裂纹圆片、灰银桥形币、绿色长柄铲形币，不新增其他主角，不把它们统一成圆形方孔钱。吸引力只表现为漂移和金色光尘，不出现机械装置。

避免：不要一开始就直接变成光点；不要让钱币消失太早；不要飞得过高或变成舞蹈；不要新增文字、水印、UI、边框；不要BGM，只要奔跑、轻微尘土、吸力和环境声。'''
    },
    {
        'id': '3-2-1_to_3-2-2',
        'first': CROPS/'分镜3-2-1.png',
        'last': CROPS/'分镜3-2-2.png',
        'prompt': '''使用分镜3-2-1作为首帧、分镜3-2-2作为尾帧，生成一段5秒、3:4竖版、连续单画面视频。两张图只作为首尾状态参考，成片不要出现九宫格、分镜板、拼贴图、画中画、边框或文字说明。

首帧画面：黄色杜邦纸钱袋包局部进入画面，能看到黄色织物质感、黑色/棕色肩带、金属扣、上方开口和椭圆形手提孔，包身下部已有发光圆点和钱币形纹样。金色光点从画面外沿着引力方向飞向包身。

动作过程：承接上一段，三枚钱币已经化成金色光点，光点流从前方/侧前方飞向黄色钱袋包。不要把钱袋包做成怪物嘴巴或吸尘器，只用柔和引力、金色粒子流和光点进入包身来表达吸收。光点贴近包身后逐渐沉入织物表面，在包身上点亮已有纹样：圆点、圆形方孔钱币图案、长柄铲形图案。镜头从包身局部慢慢推进并平移到更完整的产品展示角度。

尾帧画面：黄色钱袋包更完整地进入画面，棕色肩带横跨前景，包身圆点和钱币图案微微亮起，周围保留暖金色光点。产品结构清楚：黄色织物、椭圆手提孔、肩带、金属扣和包身纹样。

保真要求：钱袋包以参考图中的黄色杜邦纸包为准，保持黄色织物质感、椭圆手提孔、棕色肩带、金属扣、包身圆点和钱币形图案。光点最终成为包身已有纹样，不新增巨大logo或分镜里没有的大图案。

避免：不要让钱袋包变成怪物嘴巴、吸尘器或机械装置；不要让完整硬币角色继续在包外乱跑；不要新增文字、水印、UI、边框；不要让光点遮住手提孔、肩带和金属扣；不要BGM，只要光点流动、轻微吸入和环境声。'''
    }
]

BASE.mkdir(parents=True, exist_ok=True)
results=[]
env=os.environ.copy(); env['HOME']='/Users/bot1'
for seg in segments:
    seg_dir = BASE/('segment_'+seg['id'].replace('-', '_'))
    seg_dir.mkdir(parents=True, exist_ok=True)
    prompt_path = seg_dir/(seg['id']+'_prompt.txt')
    prompt_path.write_text(seg['prompt'], encoding='utf-8')
    cmd=[BIN,'frames2video','--first',str(seg['first']),'--last',str(seg['last']),'--prompt',seg['prompt'],'--duration','5','--video_resolution','1080p','--model_version','seedance2.0_vip','--poll','8']
    proc=subprocess.run(cmd,text=True,capture_output=True,env=env,timeout=240)
    (seg_dir/'submit_stdout.log').write_text(proc.stdout,encoding='utf-8')
    (seg_dir/'submit_stderr.log').write_text(proc.stderr,encoding='utf-8')
    text=proc.stdout+'\n'+proc.stderr
    data=None
    try: data=json.loads(proc.stdout)
    except Exception: data={}
    def rgx(p):
        m=re.search(p,text); return m.group(1) if m else None
    status={
        'segment':seg['id'],
        'submitted_at':datetime.datetime.now().astimezone().isoformat(),
        'first':str(seg['first']),
        'last':str(seg['last']),
        'prompt_file':str(prompt_path),
        'duration':5,
        'model_version':'seedance2.0_vip',
        'video_resolution':'1080p',
        'submit_id':data.get('submit_id') or rgx(r'"submit_id"\s*:\s*"([^"]+)"'),
        'gen_status':data.get('gen_status') or rgx(r'"gen_status"\s*:\s*"([^"]+)"'),
        'credit_count':data.get('credit_count') or rgx(r'"credit_count"\s*:\s*([0-9]+)'),
        'returncode':proc.returncode,
    }
    (seg_dir/'submit_status.json').write_text(json.dumps(status,ensure_ascii=False,indent=2),encoding='utf-8')
    print(json.dumps(status,ensure_ascii=False))
    results.append(status)
    if proc.returncode!=0 or not status['submit_id'] or status['gen_status']=='fail':
        raise SystemExit(f"submit failed: {seg['id']}")
(BASE/'submit_results.json').write_text(json.dumps(results,ensure_ascii=False,indent=2),encoding='utf-8')
print('ALL_SUBMITTED')
print(json.dumps(results,ensure_ascii=False,indent=2))
