File size: 3,910 Bytes
1081be0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
"""Capture a real wall-clock30s image-only stream, keeping all generation waits."""
import json,time,threading,subprocess
from pathlib import Path
import numpy as np
import torch
from PIL import Image
import imageio_ffmpeg
import sys
sys.path.insert(0,str(Path(__file__).resolve().parents[1]))
from fp8_runtime import load_pipeline
from acceleration import accelerate_pipeline
from prompts import VIDEO
import sys
ROOT=Path(__file__).resolve().parents[1];sys.path.insert(0,str(ROOT))
OUT=Path(__file__).parent/'demo';OUT.mkdir(parents=True,exist_ok=True)

@torch.inference_mode()
def main():
    pipe=accelerate_pipeline(load_pipeline('/home/user/models/qwen-image-2.1-b3179ad',ROOT/'release'/'transformer'))
    warm=pipe(prompt=VIDEO[0],width=1024,height=1024,num_inference_steps=40,generator=torch.Generator('cuda').manual_seed(50000)).images[0].convert('RGB')
    warm.save(OUT/'initial.png')
    ffmpeg=imageio_ffmpeg.get_ffmpeg_exe()
    cmd=[ffmpeg,'-y','-loglevel','error','-f','rawvideo','-pix_fmt','rgb24','-s','1024x1024','-r','30','-i','-',
         '-an','-c:v','libx264','-preset','veryfast','-crf','17','-pix_fmt','yuv420p','-movflags','+faststart',str(OUT/'realtime-30s.mp4')]
    encoder=subprocess.Popen(cmd,stdin=subprocess.PIPE)
    shared={'frame':np.asarray(warm).tobytes(),'id':'initial'};lock=threading.Lock();ready=threading.Event()
    frames=[];events=[];completed_images=[]
    start_holder={}
    def record():
        start=time.perf_counter();start_holder['start']=start;ready.set()
        for n in range(900):
            deadline=start+n/30
            remaining=deadline-time.perf_counter()
            if remaining>0:time.sleep(remaining)
            with lock:frame=shared['frame'];fid=shared['id']
            sampled=time.perf_counter()-start
            encoder.stdin.write(frame)
            frames.append({'frame':n,'nominal_seconds':n/30,'sampled_seconds':sampled,'image':fid})
        encoder.stdin.close()
    thread=threading.Thread(target=record);thread.start();ready.wait()
    start=start_holder['start']
    for i in range(1,10):
        if time.perf_counter()-start>=30:break
        prompt=VIDEO[i%len(VIDEO)]
        before=time.perf_counter()-start
        im=pipe(prompt=prompt,width=1024,height=1024,num_inference_steps=40,generator=torch.Generator('cuda').manual_seed(50000+i)).images[0].convert('RGB')
        torch.cuda.synchronize();complete=time.perf_counter()-start
        payload=np.asarray(im).tobytes()
        with lock:shared.update(frame=payload,id=f'image-{i}')
        published=time.perf_counter()-start
        completed_images.append((f'image-{i}',im))
        events.append({'id':f'image-{i}','prompt':prompt,'seed':50000+i,'request_start_seconds':before,
                       'completed_seconds':complete,'display_update_seconds':published,'seconds':complete-before,'appears_within_video':published<30})
        print(json.dumps(events[-1]),flush=True)
    thread.join();rc=encoder.wait();assert rc==0
    # Save diagnostic PNGs after capture so file compression does not delay requests.
    for fid,im in completed_images:im.save(OUT/f'{fid}.png')
    lags=[x['sampled_seconds']-x['nominal_seconds'] for x in frames]
    (OUT/'capture_receipt.json').write_text(json.dumps({'duration':30,'fps':30,'frames':900,'width':1024,'height':1024,'steps':40,
        'diagnostic_png_writes':'Deferred until capture ends; video display updates occur immediately on generation completion.',
        'initial_image':'One completed warmup image visible at time0; all subsequent image changes were captured live after actual generation completion. No time compression, overlays, text, transitions or audio.',
        'events':events,'max_capture_lag_seconds':max(lags),'frames_log':frames},indent=2))
    assert max(lags)<.25,('Capture lag exceeded250ms',max(lags))
    print('VIDEO_COMPLETE',max(lags),flush=True)

if __name__=='__main__':main()