
    Sjs                     b   d Z ddlZddlZddlZddlZddlZddlmZ  ee	      j                  Zej                  j                  d ee             ddlZeZdZdZedz  dz  dz  Zedz  dz  d	z  Zed
z  ZdZdZdZ ej4                   eedz  dz              Zed   D  ci c]  } | d   | d   f|  c} Z ej<                   ej>                  g dddgg dg dg dg dd            Z dddddddZ!ddd d!d"d#dZ"d$ Z#d% Z$d& Z%d' Z&d(dd)d*d+d,dd-iZ'd. Z(d/ Z)d0 Z*d1 Z+d2 Z,g d3Z-d4 Z.d5j_                  g d6      Z0d7 Z1d8 Z2e3d9k(  r ejh                         Z5e5jm                  d:d)g d;<       e5jm                  d=d>?       e5jo                         Z8e8jr                  ju                  d@      D cg c]  }|s|	 c}Z;e8jx                  dAk(  r	 e%e;       ye8jx                  dBk(  r	 e&e;       ye8jx                  dCk(  r e(        ye8jx                  dDk(  r	 e1e;       y e2        yyc c} w c c}w )Eu  s34 전체 샷 스틸 런 (2026-07-12, 실험 전용·커밋 금지).

v24i 체인: v24 i2 콘티(실사영화 스토리보드+REALIZE 원칙) 6장
 → 그리드 크롭(백색 패널 제외, 28패널, panels24i/)
 → LLM이 샷별 '시각적 관련 앞쪽 샷' 판정(기존 판정 재사용, prev 참조)
 → nb2 스틸 순차 생성 (참조=콘티 패널[참조일 뿐, 그대로 실사화 금지
   강조]+prev 스틸+VE 엔티티: 캐릭터 composite+소품 reference_face —
   맵·배경 참조 없음, REALIZE 원칙 주입, stills24i/)
 → stills_run24i.html 새 갤러리.
이전 런(nb2 콘티 기반 panels24/stills24/stills_run24.html)은 보존.

사용: backend/.venv/bin/python s34_stillrun.py --only <judge|crop|gen|html>
     [--groups ...]
    N)Pathconti24i2outconti	panels24i	stills24szstills_run24s.htmls34_conti_v2s34_stillrun_v1z$8ad94c03-5b33-4d51-83d0-a6e4106e9c02pipeline_doczshot_loc_data.jsonshotssceneshot)S1sh1S1sh4S3sh3S15sh2S15sh6)S10sh6S10sh7S11sh4S11sh5S13sh4S13sh6)S12sh11S12sh21S14sh5S18sh11S25sh1S25sh5)S8sh3S8sh5S19sh5S19sh6S20sh1S20sh3)S16sh3S21sh7S21sh10S21sh12S22sh1forestbusstoprooftop_extrooftop_intmartpolice)   r3   )r3      )   r3   z5a dense Korean mountain forest with thick undergrowthz\a small seaside bus stop with a bench facing the sea at night on a quiet Korean coastal roada  the exterior of an old Korean multi-family villa: narrow alley and small yard at ground level, an added exterior steel staircase climbing the wall, and a rooftop with a small rooftop room (steel front door, one lit window), a water tank, a clothesline and a low parapetzthe interior of a small Korean rooftop home: living room with a small window, kitchenette and dining table; a bedroom with a bed against one wall and a curtained window; a tiny tiled bathroom with a mirrorza mid-size Korean supermarket: shelved sales floor inside; the entrance area outside with a bicycle rack and one wall-mounted CCTV camera above; a small back security office with CCTV monitorsza modest Korean provincial police station: a detectives' office with desks, monitors and a doorway; and the street right in front of the buildingc                 \    | dd  j                  d      \  }}t        |      t        |      fS )Nr4   sh)splitint)tagsishis      P/Users/manta/Documents/Projects/TheRoad-I1/scratchpad/forest_exp/s34_stillrun.py_keyr>   O   s-    !"gmmD!GBGSX    c                 x    t         t        |          d   xs d}d|v sd|v ryd|v sd|v ryd	|v ry
d|v ryd|v ryy)Nheading z/ Nu   밤nightu   해질u   해 질zdusk, just after sunsetu   동틀dawnu	   소나기zheavy rain shower, daytimeu   실내zinterior ambient lightdaytimeSHOTr>   )r:   hs     r=   _time_ofrI   T   s[    T#Y	"(bAzUaZ1}	Q(1}a+1}'r?   c                 >   t         dz  t         dz  j                         rt        j                  t              ni }|j                  di       }dj                  g d      }ddddd	d
id	d
dgid	d
idg dddidgd}t        j                         D ]  \  }}| r|| vrt        |D ch c]  }t        |      d    c}      }dj                  d |D              }	dj                  d |D              }
t        j                  d| |d|	 d|
 |      }|d   D ci c]  }|d   |d   |d   d c}||<   t        d| d||   j                         D ci c]  \  }}||d    c}}        t        j                  t        |       y c c}w c c}w c c}}w )Nplansz.jsonprev
)u\   당신은 콘티 연속성 판정가다. 같은 장소 그룹의 샷 목록(순서대로)과uW   씬 원문을 보고, 각 샷마다 '시각적으로 관련된 앞쪽 샷'이 있는지uY   판정하라. 시각적 관련 = 같은 공간·연속된 액션·같은 인물 구도가uZ   이어져 앞 샷의 생성 이미지를 참조로 붙이면 일관성에 도움이 되는uP   경우. 다른 시간대·다른 서브 공간·연결 단서가 없으면 null.uT   앞쪽 샷은 반드시 목록에서 자기보다 앞에 있는 샷이어야 한다.uJ   각 샷마다 prev(태그 또는 null)와 reason_ko(한 구절)를 반환.objectitemsarraytypestringnull)r   rL   	reason_korQ   
propertiesrequiredrQ   rO   r   

c              3      K   | ]<  }d | dt         d   t        |         d    dt         d   t        |         d   z    > yw)u   [씬 z] scenesrA   rM   textN)DATAstr).0r;   s     r=   	<genexpr>zstage_judge.<locals>.<genexpr>z   sU      !C8A" B4r$x.R1)<=R@8nSW%f-.8As   AAc              3   P   K   | ]  }| d t         t        |         d       yw): descNrF   )r_   ts     r=   r`   zstage_judge.<locals>.<genexpr>}   s-      ;59qcDaM&)*+Ts   $&s34run_prev_u   씬 원문:
u   

샷 목록(순서):
r   rT   )rL   reasonz[judge] :)BASEPLAN_RUNexistsF	load_plan
setdefaultjoinGROUPSrO   sortedr>   llmprint	save_plan)groups_filterplanprev_mapSYSSCHEMAgkeytagsrd   	scene_ids
scenes_txt	shots_txtresitkvs                  r=   stage_judger   c   s   %)G^
%6H%H$P$P$R1;;x XZDvr*H
))  C w"X&h/0 (+3- 6	798 /9 IF lln
dT651DGAJ56	[[ !C8A!C C
 II ;59; ;	eel4&)3#J</HT
 $'w<1#/R V*r&z13K'B B#/1 	a (0(<(<(>?(>1q!F)|(>?	A %" KK$ 61 @s   *F
FFc                    t        j                  t              }|j                  di       }t        j                  t              d   }dj                  g d      }dddddd	idd
idd	idg dddidgd}t        j                         D ]  \  }}| r|| vrg }|D ]u  }	|j                  |i       j                  |	i       }
t        |
t              rd|
i}
|j                  |	 dt        t        |	         d    d|
j                  dd      z          w t        j                  d| |ddj                  |      z   |      }|d   D ci c]  }|d   |d   |d   d c}||<   t        d| d||   j                         D ci c]  \  }}||d    c}}        t        j                   t        |       yc c}w c c}}w )uX   LLM 판정: 샷별로 콘티(구도) 참조가 필요한지 — 쉬운 구도는 제거.
conti_needmovementrM   )uU   당신은 촬영 현장의 콘티 운용 판정가다. 각 샷의 텍스트와 동선uO   분석을 보고, 이미지 생성 시 스토리보드(콘티) 패널을 구도u5   참조로 첨부할 필요가 있는지 판정하라.uO   콘티 필요(true) = 구도를 글만으로 오해하기 쉬운 경우: 여러uT   인물의 동선·위치 관계가 얽힘, 특수한 카메라 각도/깊이 관계,uT   연속 액션의 방향 유지가 중요, 프레임 내 배치가 스토리텔링에u
   결정적.uP   콘티 불필요(false) = 글만으로 충분히 명확한 쉬운 구도: 단일uV   인물 클로즈업/상반신, 단순 인서트(손·사물), 정적인 단순 배치,u   표준적인 대화 구도 등.uH   각 샷마다 need_conti(bool)와 reason_ko(한 구절)를 반환하라.rN   rO   rP   rQ   rR   boolean)r   
need_contirT   rU   rX   rb   rc   u   
  동선: u   (없음)s34run24s_contineed_u   샷 목록:
r   r   rT   needrf   z[conti_need] rg   r   N)rk   rl   ri   rm   
PLAN_CONTIrn   ro   rO   get
isinstancer^   appendrG   r>   rq   rr   rs   )rt   ru   need_mapmv_allrw   rx   ry   rz   linesrd   mr~   r   r   r   s                  r=   stage_conti_needr      s   ;;x D|R0H[[$Z0F
))  C w"X&!9- (+3- <	=9> /? IF lln
dT6A

4$((B/A!S!OLLA3bd1gv!6 7|D55Z89 :	  ee*4&13#dii&66@ %(L2$0b V*r,/?13K'B B$02 	dV1%(0(<(<(>?(>1q!F)|(>?	A %" KK$2 @s   	F;G r-   T)r   r   )r4   r   )r   r4   )gridequalcellsc                     ddl m}  t        j                  dd       t        j                         D ]  \  }}| j                  t        dz  dz  t         d| dt         dz        j                  d	      }|j                  d
      j                  d       }|j                         }|rsd}t        d|d   |z
        t        d|d   |z
        t        |j                  d   |d   |z         t        |j                  d   |d   |z         f}|j!                  |      }|j                  \  }}t"        j%                  |      }	|	r|	d   nt&        |   \  }
}dd l}|j+                  |j                  d
            }|dk  }d }|	rZ|	j%                  d      rIt-        |
dz
        D cg c]  }||dz   z  |
z   }}t-        |dz
        D cg c]  }||dz   z  |z   }}nH|
dkD  r ||j/                  d      |
dz
  |      ng }|dkD  r ||j/                  d      |dz
  |      ng }dg|z   |gz   }dg|z   |gz   }t1        |      D ]k  \  }}|	r|	d   |   \  }}n
||
z  ||
z  }}||   dz   ||   dz   ||dz      dz
  ||dz      dz
  f}|j!                  |      j3                  t        | dz         m t5        d| dt7        |       d| d| |	rdndz           y c c}w c c}w )Nr   )ImageTparentsexist_okr   r   _.pngRGBLc                     | dk  rdS dS )N      r    )r   s    r=   <lambda>zstage_crop.<locals>.<lambda>   s    S#2Ga2Gr?      r4   r3   r5   r   x   c                    t        |       D cg c]  \  }}|dkD  s| }}}g }|D ]9  }|r#||d   d   z
  dk  r|d   j                  |       (|j                  |g       ; |D cg c]B  }|dz  t        |      t        |      z  cxk  r|dz  k  rn nt        |      t        |      z  D }}t        |      |k(  r|S t	        |      D 	cg c]  }	||	dz   z  |dz   z   c}	S c c}}w c c}w c c}	w )Ng?   g?gffffff?r4   )	enumerater   sumlenrange)
profilen_expecttotalir   candgroupsgcentersr   s
             r=   _lineszstage_crop.<locals>._lines   s   "+G"4A"4$!QDA"4DAFa&*R.0A52J%%a(MM1#&	 
 28 IA$,Q#a&G54<G 1vQ'G I7|x'"8_., QUO15,. . BI.s   C&C&(AC,C1r   )axisr   z[crop] rb   u	   패널 v=z h=z (override)rB   )PILr   OUTPmkdirro   rO   openrh   	CONTI_VER	CONTI_ENGconvertpointgetbboxmaxminsizecropSHEET_OVERRIDESr   GRIDnumpyasarrayr   meanr   saverr   r   )r   ry   rz   sheetmaskbboxpadWHovcolsrowsnparrdarkr   r   v_linesh_linesxsysr   r:   crboxs                             r=   
stage_cropr      s   JJtdJ+lln
d

5L7"1TF!I;d3455<WU^ 	 }}S!''(GH||~C47S=)3q$q'C-+@

1tAw}5

1tAw}57D JJt$Ezz1  &#%RZ4:
d 	jjs+,Sy	.  "&&/49$(ODOqqAE{d*OGD49$(ODOqqAE{d*OGD@DqfTYYAY.q!<bG@DqfTYYAY.q!<bGS7]aS S7]aS oFAs'{3'14xd1a519beaiAEQ1q5	AFCJJsO  3%t!45 & 	vRD	{)G9CyI"$". 	/m %P EDs   #KK!c                 b    t        j                  dddddddd| g	dddd	d
d      j                  S )Npsqlz-h	localhostz-Utheroadz-dz-tAcTtheroad_dev_2026z./usr/bin:/bin:/opt/homebrew/bin:/usr/local/bin)
PGPASSWORDPATH)capture_outputr\   checkenv)
subprocessrunstdout)sqls    r=   _psqlr      sH    >>	{D)T9		$d-7gh	j kqjp	qr?   c                      dt          d} i }t        |       j                         j                  d      D ]-  }|s|j                  d      \  }}}|t	        d      |z  f||<   / |S )u9   5회차 VE 캐릭터 → composite 경로 (DB read-only).SELECT DISTINCT ON (ec.short_id) ec.short_id, ec.name, ia.file_path FROM image_asset ia JOIN entity_canon ec ON ec.id::text=ia.entity_id::text WHERE ia.project_id='zt' AND ec.entity_type='character' AND ia.pipeline_role='reference_composite' ORDER BY ec.short_id, ia.created_at DESCrM   |*/Users/manta/Documents/Projects/TheRoad-I1P5r   stripr8   r   r   r   linesidnamepaths         r=   
_char_refsr     |    # $&$ '66C 	Ac
  "((.**S/T4IJTQR#	 /
 Hr?   c                      dt          d} i }t        |       j                         j                  d      D ]-  }|s|j                  d      \  }}}|t	        d      |z  f||<   / |S )u;   5회차 VE 소품 → reference_face 경로 (DB read-only).r   zj' AND ec.entity_type='prop' AND ia.pipeline_role='reference_face' ORDER BY ec.short_id, ia.created_at DESCrM   r   r   r   r   s         r=   
_prop_refsr     r   r?   c            
         dt          d} i }t        |       j                         j                  d      D ]z  }|s|j                  dd      \  }}}	 t	        j
                  |      D cg c]'  }t        |j                  dd            dd	 d
v r|d   ) }}||t        |      t        |      f<   | |S c c}w # t        $ r g }Y /w xY w)uB   샷별 VE — 배경(L) 제외 전 엔티티(C/P) short_id 목록.zYSELECT scene_index, shot_index, visible_entities_json FROM scene_still WHERE project_id='z' AND is_selectedrM   r   r3   short_idrB   Nr4   )CP)
r   r   r   r8   jsonloadsr^   r   	Exceptionr9   )r   r   r   r;   r<   veeidss           r=   _ve_idsr  '  s    --/D0ACC
Ac
  "((.jja(C	*.**R. D.Q!%%
B/0!4
B Z=.C D "%3r7CH
 / HD 	C	s$   B9),B4B94B99CC))u   피투성이가 된u$   힘없이 무너져 미동이 없는)u	   핏자국u   어두운 얼룩)u
   피 묻은u	   얼룩진)u   피로 그린 듯한u   짙은 붉은)zblood-soakeddark-stained)bloodiedr	  )bloodstainedstained)bloodyr	  )bloodzdark stains)lifelesszutterly motionless, collapsed)corpsezmotionless figurec                 F    t         D ]  \  }}| j                  ||      }  | S )N)_SOFTENreplace)rd   abs      r=   _softenr  D  s$    1IIaO Hr?   rM   )zBREALIZE FIGURATIVE LANGUAGE AS A LIVE-ACTION SHOT: the Korean shotzAtext may describe characters metaphorically, figuratively or withz@exaggeration. Photograph what a real movie camera would actuallyuB   record on a physical set — exaggerated or figurative impressionsz<become realistic staging choices (lighting, distance, angle,z'wardrobe), not literal fantasy imagery.z=EVERY CHARACTER IS A HUMAN BEING: unless the story explicitlyz>features non-human or virtual beings (as in science fiction oru<   fantasy), every character — however indirectly, vaguely oruB   figuratively the text describes them — IS a real human. When thez@text gives no direct visual description of a person, IMAGINE onez<and still show them as a concrete, fully-formed human being:u=   always render the human form to the maximum extent — build,uD   posture, face, hands, clothing — never reduce a person to a shape,z(blob, solid silhouette or abstract mass.c                 &
   t        j                  t              }|d   }|j                  di       }|j	                  di       }t        j                  t
              d   }t               }t               }t               }i }	|j                         D ]1  \  \  }
}}|	j	                  |
t                     j                  |       3 t        j                  dd       t        j                         D ]  \  }}| r|| vr|D ]  }t        | dz  }|j                         rt!        d| d	       0t"        t%        |         }|j                  |i       j                  |i       }t'        |t(              r|d
d}|j                  |i       j                  |i       }|j                  d      }|j                  |i       j                  |ddd      }g }|d   r|j+                  dt,        | dz  f       d }|r9t        | dz  j                         r|}|j+                  dt        | dz  f       |j                  t%        |      g       }|s/t/        |	j                  t%        |      d   t                           }g g }}|D ]  }||v rB||   \  }}|j                         s |j+                  |       |j+                  d| d|f       I||v sN||   \  }}|j                         sg|j+                  |       |j+                  d| d|f        dt1        |      z   dz   dt3        |d          dt4        |    dg}|d   r"|j+                  dj7                  g d             |j+                  t8               |j                  d      r |j+                  dt3        |d         z          |j                  d       r |j+                  d!t3        |d          z          |r'|j+                  d"d#j7                  |      z   d$z          n|j+                  d%       |j+                  d&       d'j7                  |      }t        j:                  d(| d)||d*|+       |d   |d,   |||D  cg c]X  \  } }| t)        |      j=                  t)        t>                    rt)        |jA                  t>                    n
t)        |      d-Z c}} d.||<   t        jB                  t        |       t!        d| d/|d    d0| d1| d2| d3       
  y c c}} w )4NrL   r   gen_metar   Tr   _nb2.pngz[gen] z skip(exists)rB   )r   figuresu   판정 없음r   r   uy  STORYBOARD PANEL — a REFERENCE ONLY, never the target: use it loosely for camera framing, figure placement and depth order. Do NOT photorealize this drawing as-is — the SHOT TEXT and the other references are authoritative; re-stage the moment naturally as a real photograph. Never copy the sketch's line style, paper texture, borders, simplified geometry or drawing errors.r   u   PREVIOUS SHOT STILL — a visually related earlier shot of this same place: the location's look, materials, fixed features, lighting mood and each person's clothing are LOCKED to this photo; never copy its camera framing.r   u   CHARACTER REFERENCE — zN: the exact person appearing in this shot; match face, hair and build exactly.u   PROP REFERENCE — zU: the exact object appearing in this shot; match its look, material and wear exactly.u   Create ONE FINAL photorealistic live-action film still of the moment below — contemporary South Korea, 2026; all people are Korean unless stated. TIME OF DAY (lock): .z#SHOT TEXT (authoritative, Korean): rc   zLOCATION (lock): u^   . The shot takes place here — pick the sub-area of this location that the shot text implies.rM   )
z1THE STORYBOARD PANEL IS ONLY A REFERENCE: it is az-rough pre-production sketch, not the image toz-reproduce. Take from it only the shot's roughu4   composition — framing, where figures sit, near/farz5order. Everything else (real-world detail, materials,z4light, anatomy, environment richness) must come fromz.the shot text and the photographic references,z5re-staged as if actually filmed on a real set. If thez,sketch conflicts with the shot text or looksz2simplified/wrong, FOLLOW THE TEXT, not the sketch.zMOVEMENT (follow exactly): r  u+   FIGURES — size & depth (follow exactly): zPEOPLE: the SHOT TEXT alone decides whether any person is visible in this shot. IF a person appears, they must be one of the referenced people (z, uu   ) matched exactly to their reference photo — never anyone else, and never add a person the shot text does not show.z5No people appear unless the shot text itself says so.z6No text, captions, watermarks or annotations anywhere.rY   
s34run24s__nb2z16:9)aspect_ratioout_pathrf   )labelr   )
conti_usedconti_reason	prev_usedpromptrefsu    완료 (conti=z, prev=z, chars=z, props=))"rk   rl   ri   r   rm   r   r   r   r  rO   setupdateOUTSr   ro   rj   rr   rG   r>   r   r^   r   r   rp   rI   r  PLACErn   REALIZE_STILLimg_nb2
startswithrh   relative_tors   )!rt   ru   rv   r   metar   charspropsr  scene_unionr;   r<   r  ry   rz   r:   r   sr   pjprev_tagndr%  r#  ve_ids
char_names
prop_namescidr   ppartsprompt_fulllabs!                                    r=   	stage_genr?  ]  s*   ;;x DF|Hxxb)H??:r*D[[$Z0FLELE	BK((*	S3r35)005 %JJtdJ+lln
dT6CC5))Czz|se=12T#YA

4$((b1A!S!!"r2dB'++C4Bvvf~HdB'++C$<K2M NBD&z> cU$<'	) 	* ITxj$99AAC$	' )-(8/D(DF G VVDIr*FS	!ce DE%'
J%<#CjGD!xxz"))$/6tf =7 789%; < E\#CjGD!xxz"))$/1$ 8: :;<%> ? $I 3-  #&& 6gai6H5IJ#E$K= 1! !	E &zTYY (   LL'uuZ :&q}56 7uuYJ&q|45 6> ii
+,&	&'  ) *LL & ' ++e,KII
3%t,k4#)C9 !j"X,&+
 (,	- (,VS!	 $'&)!f&7&7D	&B $'q}}T':#;(+A1 (,	-DI KK$'F3%r&zl ;$+Xj\ :&<q* +a  %X-s   (ATc                     dd l t        j                  t              } | j	                  di       }| j	                  di       }| j	                  di       }t
        dz  dz  dz  j                  dd	       d
 d fd}g }ddddddd}t        j                         D ]  \  }}d}	|D ]  }
|j	                  |i       j	                  |
i       }|j	                  |i       j	                  |
i       }|j	                  |
i       }d|
 d}|j	                  d|j	                  d            }|rdnd}d}|j	                  dg       D ]+  } ||d         }|d| d| d  |d                 d!z  }- |sd"}dj                  fd#|j	                  dg       D              }|	d$|
 d%| d& |j	                  d'd             d( t        |j	                  d      xs d)             |j	                  d      rd* |j	                  d'd             d+ndz   d, t        t        |
         d-          d.| d| d/t        |j	                  dg              d0| d1| d2 |j	                  d3d4             d5z   z  }	 |j                  d6 ||          d7| d8|	 d9        t        j!                  d:dj                  |       d;       t#        d<t                y )=Nr   rL   r   r  r   r   refs24sTr   c                 4    t        j                  | xs d      S )NrB   )_htmlescape)rd   s    r=   esczstage_html.<locals>.esc  s    ||AG$$r?   c                 |   | j                  d      ry| j                  d      ry| j                  d      r9d| j                  dd      d   j                  d	d      d
   j                         z   S | j                  d      r9d| j                  dd      d   j                  d	d      d
   j                         z   S | d d S )N
STORYBOARDu$   콘티 패널 (구도 참조 전용)PREVIOUSu'   PREV 스틸 (장소 룩·의상 잠금)	CHARACTERu
   캐릭터 u   —r4   rg   r   PROPu   소품    )r-  r8   r   )r   s    r=   	_ref_kindzstage_html.<locals>._ref_kind  s    L)9J'<K(%++eQ"7":"@"@a"H"K"Q"Q"SSSF#u{{5!4Q7==c1EaHNNPPPSbzr?   c                     | j                  d      s| S t        |       }|j                  z  }|j                         sj	                  ||       d|j                   S )N/zout/conti/refs24s/)r-  r   r   rj   copy)path_ssrcdstREFDshutils      r=   _ref_relzstage_html.<locals>._ref_rel  sT      %M6lSXXozz|KKS!#CHH:..r?   u   숲속u   해안가 버스정류장u   옥탑 단지 외부u   옥탑방 내부u   대형마트u	   경찰서r,   rB   zout/conti/stills24s/r  r!  r   u#   <span class=on>콘티 사용</span>u$   <span class=off>콘티 제거</span>r%  r   z<figure class=ref><a href='z' target=_blank><img src='z' loading=lazy></a><figcaption>r   z</figcaption></figure>u/   <span class=note>참조 이미지 없음</span>c           
   3   x   K   | ]1  }d   |d                d |d          d |d          d 3 yw)z<li><b>r   u   </b> — <span class=note>z</span> <code>r   z</code></li>Nr   )r_   r   rL  rE  s     r=   r`   zstage_html.<locals>.<genexpr>  s]      "- ,A #i'
345 6$$''
O#4 5QvY(6 ,s   7:z<div class=shot><h3> u%   <span class=note> — 콘티 판정: rf   u
    · prev: u   없음z (r&  z5</span></h3><div class=note style='margin:2px 0 8px'>rc   z&</div><div class=row><figure><a href='uq   ' loading=lazy></a><figcaption>nb2 스틸</figcaption></figure><div class=refs><div class=note>참조 이미지 (u   장):</div><div class=refrow>uU   </div></div></div><details><summary>참조 상세 + 프롬프트 전문</summary><ul>z
</ul><pre>r$  u   (기록 없음)z</pre></details></div>z<section><h2>z <span class=k>(z)</span></h2>z
</section>uP
  <!DOCTYPE html>
<html lang=ko><head><meta charset=utf-8>
<meta name=viewport content="width=device-width, initial-scale=1">
<title>s34 v24s 스틸 런 — LLM 콘티 선별+참조·프롬프트 전문 기록</title>
<style>
body { margin:0; padding:24px; background:#0f1216; color:#e6e6e6;
       font:14px/1.6 -apple-system,'Apple SD Gothic Neo',sans-serif; }
h1 { font-size:20px; } h2 { font-size:17px; margin:34px 0 8px;
     border-bottom:1px solid #333; padding-bottom:5px; }
.k { color:#8a939e; font-size:13px; font-weight:400; }
.row { display:flex; gap:14px; align-items:flex-start; margin:14px 0;
        flex-wrap:wrap; }
figure { margin:0; } figcaption { color:#c9d2dc; font-size:12.5px;
          max-width:640px; }
img { max-width:640px; width:100%; border-radius:8px;
      border:1px solid #2a2f36; }
img.sm { max-width:300px; }
.note { color:#8a939e; }
.box { background:#161b22; border:1px solid #2a2f36; border-radius:8px;
       padding:12px 16px; margin:12px 0; }
.shot { border-top:1px dashed #2a2f36; padding:12px 0; }
h3 { font-size:15px; margin:6px 0; }
.on { background:#1e3a2a; color:#7ee2a8; border-radius:5px;
      padding:1px 8px; font-size:12px; margin-left:6px; }
.off { background:#3a2a1e; color:#e2b57e; border-radius:5px;
       padding:1px 8px; font-size:12px; margin-left:6px; }
.refs { max-width:640px; }
.refrow { display:flex; gap:8px; flex-wrap:wrap; }
figure.ref img { max-width:150px; }
figure.ref figcaption { font-size:11px; max-width:150px; }
code { background:#161b22; padding:0 4px; border-radius:4px;
       font-size:11px; }
details { margin:6px 0; } summary { color:#9ecbff; cursor:pointer; }
pre { background:#161b22; border:1px solid #2a2f36; padding:10px;
      white-space:pre-wrap; font-size:12px; }
</style></head><body>
<h1>s34 v24s 스틸 런 — 28샷 (LLM 콘티 선별: 쉬운 구도는 콘티 참조
제거 → nb2 스틸)</h1>
<div class=box><b>콘티 선별</b>: 샷별로 LLM(GPT-5.6 Sol)이 "구도를
글만으로 오해하기 쉬운가"를 판정 — 다인물 동선·특수 앵글·깊이 관계는
<span class=on>콘티 사용</span>, 단일 인물 클로즈업·단순 인서트·정적
배치는 <span class=off>콘티 제거</span>. 나머지 참조는 동일: prev 스틸
(시각 관련 앞쪽 샷, 장소 룩·의상 잠금) + VE 전 엔티티(캐릭터 composite
+ 소품 reference_face, 배경 L 제외) + REALIZE 원칙 + 씬 헤딩 시간 잠금.
각 샷 카드에 <b>사용된 참조 이미지 전부와 프롬프트 전문</b>을 기록.
비교: <a href='stills_run24i.html'>v24i(전샷 콘티)</a> ·
<a href='stills_run24.html'>v24(nb2 콘티)</a>.</div>
z
</body></html>z[html] )rT  rk   rl   ri   r   rh   r   ro   rO   rn   r^   rG   r>   r   r   PAGE
write_textrr   )ru   rv   r   r/  rU  secsNAMEry   rz   figsr:   r4  r6  mt	still_relr!  badge	ref_itemsr   relref_detailsrS  rL  rE  rT  s                        @@@@r=   
stage_htmlrc    sZ   ;;x Dxx#Hxxb)H88J#D%<'!I-DJJtdJ+%	/ D+F1BT"k;D lln
dCdB'++C4BdB'++C4B#r"B.se8<IbffVn=J>H:@ IVVFB'qy)1# 7!!$%D9QwZ0122HJK	 ( M	'' "- +	"- -K
 &se1UG7BFF8R<P8Q7RSRVVF^%?x!@ABD 9;vRBFF8R012!4BP<tDIv./0 133<+ >,,5; 7 +,- .%%.K 0"m $BFF8->?@A B#$	$%D- P 	mCT
O#4 5v]4&
< 	=U %X 	OO /^  _0 0b 
GD6
r?   __main__z--only)judger   r   genhtml)rW   choicesz--groupsrB   )default,re  r   r   rf  )=__doc__argparserg  rC  r  r   syspathlibr   __file__parentHEREr   insertr^   
forest_librk   rh   r   r   r   r)  rX  r   ri   r   loadr   r]   rG   r  dumpsro   r   r*  r>   rI   r   r   r   r   r   r   r   r  r  r  rn   r+  r?  rc  __name__ArgumentParserapadd_argument
parse_argsr  r   r8   gfonly)r3  r   s   00r=   <module>r}     s       
 H~ 3t9  		e|g+ e|g+""
+tyyd^+.BBCD,0M:Mq7QvY"M:	JDJJ)(#ORFB   
 VFvA F7"L)0%	0
$ N* b v&68; <:/zq""&, 		  &C+LAH z	 	 	 	"BOOHtJ  LOOJO+
AXX^^C(	.(A!(	.BvvB	
<		
6		
5"! A ;L 
/s   !H'0H,8H,