"""Clip maitre d'Helene avec Veo 3.1 (image-to-video) — remplace l'etape payante Magic Hour.
La bouche sera ensuite repeinte par MuseTalk sur la vraie voix."""
import base64, json, os, pathlib, subprocess, sys, time

F = pathlib.Path("/Users/unctad/Claude/6 - Private/SCRC/VoxPopuli/member-app/companion/face")
SRC = F / "portrait-green.png"
OUT = F / "helene-master-veo.mp4"
MODEL = "veo-3.1-fast-generate-preview"  # defaut Frank 04-08-2026 : 0,10 $/s (0,80 $ le master de 8 s). Passer a veo-3.1-generate-preview (0,40 $/s) seulement pour un plan vu en grand.
API = "https://generativelanguage.googleapis.com/v1beta"

PROMPT = (
    "The woman speaks warmly and naturally to the camera, as if greeting someone she is happy "
    "to see. Her lips move continuously with speech, her eyes are alive and look straight into "
    "the lens, she blinks naturally a few times, her head moves very slightly. Calm, friendly, "
    "sincere expression, a soft smile. "
    "The camera is completely static, no zoom, no pan. The flat green background stays perfectly "
    "uniform and unchanged. She stays centered, head and shoulders, same framing, same clothes, "
    "same hair, same lighting. Photorealistic, natural motion, no stylisation."
)

key = os.environ["GEMINI_PAID_KEY"]
img = base64.b64encode(SRC.read_bytes()).decode()
body = {
    "instances": [{"prompt": PROMPT, "image": {"bytesBase64Encoded": img, "mimeType": "image/png"}}],
    "parameters": {"aspectRatio": "16:9", "resolution": "720p", "durationSeconds": 8,
                   "personGeneration": "allow_adult"},
}
req = pathlib.Path("/tmp/veo-req.json")
req.write_text(json.dumps(body))

r = subprocess.run(["curl", "-s", "-X", "POST", f"{API}/models/{MODEL}:predictLongRunning?key={key}",
                    "-H", "Content-Type: application/json", "-d", f"@{req}"],
                   capture_output=True, text=True)
req.unlink(missing_ok=True)
d = json.loads(r.stdout)
if "error" in d:
    sys.exit("refus: " + json.dumps(d["error"])[:400])
op = d.get("name")
print("job:", op, flush=True)

t0 = time.time()
while True:
    time.sleep(15)
    p = subprocess.run(["curl", "-s", f"{API}/{op}?key={key}"], capture_output=True, text=True)
    st = json.loads(p.stdout)
    if st.get("done"):
        if "error" in st:
            sys.exit("echec: " + json.dumps(st["error"])[:400])
        resp = st.get("response", {})
        vids = (resp.get("generateVideoResponse", {}).get("generatedSamples")
                or resp.get("generatedSamples") or resp.get("videos") or [])
        if not vids:
            sys.exit("pas de video: " + json.dumps(resp)[:500])
        v = vids[0]
        uri = (v.get("video") or {}).get("uri") or v.get("uri")
        if uri:
            subprocess.run(["curl", "-s", "-L", "-o", str(OUT), f"{uri}&key={key}" if "?" in uri else f"{uri}?key={key}"], check=True)
        else:
            data = (v.get("video") or {}).get("bytesBase64Encoded") or v.get("bytesBase64Encoded")
            OUT.write_bytes(base64.b64decode(data))
        print("saved:", OUT, OUT.stat().st_size // 1024, "Ko", flush=True)
        break
    print(f"{int(time.time()-t0):4d}s  en cours", flush=True)
