#!/usr/bin/env python3
from pathlib import Path
import json,subprocess,time,urllib.error,urllib.request
P=Path(__file__).resolve().parents[1];ROOT=Path('/data/video-pipeline').resolve();BASE='http://192.168.1.104:8021'
def safe(x):
 p=Path(x).resolve();p.relative_to(ROOT);return str(p)
def probe(f):return json.loads(subprocess.check_output(['ffprobe','-v','error','-show_streams','-show_format','-of','json',str(f)]))
def post(payload,name):
 data=json.dumps(payload).encode();req=urllib.request.Request(BASE+'/stickman-render-gpu',data=data,headers={'Content-Type':'application/json'},method='POST')
 for a in range(12):
  try:
   with urllib.request.urlopen(req,timeout=3600) as r:d=json.load(r)
   if d.get('status')=='error' or d.get('detail'):raise RuntimeError(d)
   (P/f'logs/render_{name}_response.json').write_text(json.dumps(d,ensure_ascii=False,indent=2)+'\n');return d
  except urllib.error.HTTPError as e:
   if e.code==409:time.sleep(min(60,5*(a+1)));continue
   raise
 raise RuntimeError('gpu lock retries exhausted')
m=json.load(open(P/'asr/timeline.json'));jobs=[('intro',[{'image_path':safe(P/'images/intro_poster.render.png'),'duration':float(subprocess.check_output(['ffprobe','-v','error','-show_entries','format=duration','-of','default=nk=1:nw=1',P/'audio/intro.wav']))}],P/'audio/intro.wav',P/'video/intro.mp4'),('outro',[{'image_path':safe(P/'images/outro_poster.render.png'),'duration':float(subprocess.check_output(['ffprobe','-v','error','-show_entries','format=duration','-of','default=nk=1:nw=1',P/'audio/outro.wav']))}],P/'audio/outro.wav',P/'video/outro.mp4'),('main',[{'image_path':safe(P/f'images/scenes/scene_{s["id"]:03d}.render.png'),'duration':s['duration']} for s in m['scenes']],P/'audio/full_narration.wav',P/'video/output/main.mp4')]
# Intro audio must include physical 2-second silence.
jobs[0]=(jobs[0][0],jobs[0][1],P/'audio/intro.wav',jobs[0][3])
for name,scenes,audio,out in jobs:
 h=json.load(urllib.request.urlopen(BASE+'/health',timeout=30));assert h.get('status')=='ok' and h.get('nvenc_available') is True and h.get('gpu',{}).get('available') is True and h.get('encoder')=='h264_nvenc' and '/stickman-render-gpu' in h.get('endpoints',[]),h
 payload={'job_id':f'029-{name}','scenes':scenes,'audio_path':safe(audio),'output_path':safe(out),'width':1920,'height':1080,'fps':30,'crf':20,'transition':'cut','timeline_start_sec':0,'timeline_end_sec':sum(x['duration'] for x in scenes),'burn_subtitles':False,'motion':False}
 d=post(payload,name);assert d.get('service')=='dedicated-gpu-story-render' and d.get('encoder')=='h264_nvenc',d
 q=probe(out);v=next(x for x in q['streams'] if x['codec_type']=='video');assert (v['width'],v['height'],v['codec_name'],v['r_frame_rate'])==(1920,1080,'h264','30/1');assert any(x['codec_type']=='audio' for x in q['streams']) and out.stat().st_size>10000;print(name,'PASS')
print('GPU_RENDER_GATE PASS')
