30 lines
2.0 KiB
Python
30 lines
2.0 KiB
Python
"""실제 영상의 시작·중간·끝 렌더를 모바일 크기로 나란히 보는 검사 보조물."""
|
|
import hashlib
|
|
import json
|
|
from pathlib import Path
|
|
from PIL import Image, ImageChops, ImageStat
|
|
|
|
ROOT=Path(__file__).resolve().parents[3]
|
|
BASE=ROOT/'projects/water-hydrogen-bond-surface-tension/stages/08-scenes/r3'
|
|
artifact=json.loads((BASE/'artifact.json').read_text(encoding='utf-8'))
|
|
results=[]
|
|
for sample in artifact['payload']['preview']['samples']:
|
|
if sample['media']['kind']!='video':
|
|
continue
|
|
folder=(ROOT/sample['media']['path']).parent
|
|
evidence=json.loads((folder/'evidence.json').read_text(encoding='utf-8'))
|
|
frames=evidence['logical_frames']
|
|
selection=[frames[0],frames[len(frames)//2],frames[-1]]
|
|
originals=[Image.open(folder/f'frame-{frame:08}.png').convert('RGB') for frame in selection]
|
|
differences=[ImageChops.difference(originals[0],image) for image in originals[1:]]
|
|
assert all(diff.getbbox() for diff in differences), '렌더 픽셀이 동일한 정지 클립'
|
|
sheet=Image.new('RGB',(1080,640))
|
|
for index,image in enumerate(originals):
|
|
sheet.paste(image.resize((360,640),Image.Resampling.LANCZOS),(index*360,0))
|
|
path=BASE/'generated-source'/f'mobile-{sample["cut_ids"][0]}.png'
|
|
sheet.save(path)
|
|
results.append(dict(cut_id=sample['cut_ids'][0],logical_frames=selection,pixel_sha256=[hashlib.sha256(image.tobytes()).hexdigest() for image in originals],mean_absolute_pixel_change=[sum(ImageStat.Stat(diff).mean)/3 for diff in differences],mobile_view_path=path.relative_to(ROOT).as_posix(),mobile_view_sha256=hashlib.sha256(path.read_bytes()).hexdigest(),visual_review='not_checked'))
|
|
assert len(results)==3, '세 대표 영상이 아직 없음'
|
|
(BASE/'motion-check.json').write_text(json.dumps(dict(result='GREEN',source_sha256=artifact['payload']['preview']['scene_file']['sha256'],views=results),ensure_ascii=False,indent=2)+'\n',encoding='utf-8')
|
|
print('MOTION_GREEN: 세 영상의 실제 시작/중간/끝 RGB 픽셀 변화')
|