§
    F*ÊjÈ-  ã                   ó  — d Z ddlZddlZddlZddlmZ ddlmZmZm	Z	m
Z
 ddlZddlZej        dk    rC	 ej                             d¬¦  «         ej                             d¬¦  «         n# e$ r Y nw xY w ee¦  «                             ¦   «         j        j        Zedz  d	z  Zd
edeeef         fd„Zdedefd„Z G d„ d¦  «        Z	 	 	 d,de
eef         dede	e
eef                  deeef         dee	ej                 e	e         f         f
d„Z	 d-de
eef         dede	e         fd„Z e!dk    rØddl"Z" e"j#        d¬¦  «        Z$e$ %                    ddd¬¦  «         e$ %                    d edd!¬"¦  «         e$ %                    d#dd$¬%¦  «         e$ &                    ¦   «         Z' ee'j(        e'j)        e'j*        ¬&¦  «        \  Z+Z,e,r7 e-d'e,› �¦  «          e-d(e+j.        d)         › d*e+j.        d         › �¦  «         dS  e-d+¦  «         dS dS ).u*  
=============================================================================
THáº¬P NGÅ¨ NIÃŠN (THE FIFTEEN SPRINGS) - ZERO-WASTE CONTACT SHEET TILING ENGINE
=============================================================================
Module: contact_sheet_engine.py
Author: Nguyá»…n SÄ© SÆ¡n / AI Cinema Autonomous Engineering
Reference: FlowKit Architectural Specification (Section 1)

Engine ghÃ©p khung hÃ¬nh liÃªn hoÃ n khÃ´ng khoáº£ng cháº¿t (Zero-Waste Contact Sheet):
- TÃ­nh toÃ¡n Æ°á»›c sá»‘ chÃ­nh xÃ¡c (Exact Divisor Math) cho cols_eff vÃ  rows_eff
  Ä‘áº£m báº£o cols_eff * rows_eff == n_frames.
- Triá»‡t tiÃªu 100% cÃ¡c Ã´ Ä‘en rÃ¡c (unfilled black cells), ngÄƒn cháº·n hoÃ n toÃ n
  hiá»‡n tÆ°á»£ng Vision LLM (Gemini 3.8 / Flash / Claude) bá»‹ áº£o giÃ¡c "black frame defect".
- Ä�Ã³ng dáº¥u timestamp badge trá»±c quan [T=X.Xs | Frame N] Ä‘á»™ tÆ°Æ¡ng pháº£n cao.
- Há»— trá»£ xuáº¥t máº£ng NumPy, lÆ°u file JPEG cháº¥t lÆ°á»£ng cao vÃ  trÃ­ch xuáº¥t raw JPEG bytes.
=============================================================================
é    N)ÚPath)ÚTupleÚListÚOptionalÚUnionÚwin32zutf-8)ÚencodingÚ	04_AssetsÚcritic_queueÚn_framesÚreturnc                 ó¶  — | dk    rdS | dk    rdS | dk    rdS g }t          dt          t          j        | ¦  «        ¦  «        dz   ¦  «        D ]'}| |z  dk    r| |z  }|                     ||f¦  «         Œ(|s| dfS d}|d         }t          d	¦  «        }|D ]B\  }}t          |¦  «        t          |¦  «        z  }t          ||z
  ¦  «        }||k     r|}||f}ŒC|S )
uÛ  
    TÃ­nh toÃ¡n lÆ°á»›i (cols_eff, rows_eff) sao cho cols_eff * rows_eff == n_frames
    vá»›i tiÃªu chÃ­:
    1. Zero black cells (khÃ´ng Ã´ rÃ¡c).
    2. Tá»‰ lá»‡ khung hÃ¬nh cá»§a lÆ°á»›i gáº§n vá»›i tá»‰ lá»‡ chuáº©n 16:9 nháº¥t cÃ³ thá»ƒ (cols >= rows).
    
    Náº¿u n_frames lÃ  sá»‘ nguyÃªn tá»‘ hoáº·c khÃ´ng cÃ³ Æ°á»›c sá»‘ Ä‘áº¹p, tá»± Ä‘á»™ng Ä‘iá»�u chá»‰nh n_frames
    vá»� sá»‘ chia tá»‘i Æ°u gáº§n nháº¥t (vÃ­ dá»¥: 5 -> 6 hoáº·c 4; 7 -> 6 hoáº·c 8).
    é   )r   r   é   )r   r   é   )r   r   r   gÇqÇqü?Úinf)ÚrangeÚintÚmathÚisqrtÚappendÚfloatÚabs)	r   Ú
candidatesÚrÚcÚtarget_ratioÚ	best_pairÚmin_diffÚratioÚdiffs	            úDC:\Projects\KieuStory\05_Production_Pipeline\contact_sheet_engine.pyÚcompute_zero_waste_gridr#   )   s  € ð �1‚}€}ØˆvØ�1‚}€}ØˆvØ�1‚}€}Øˆvð )+€JÝ�1•c�$œ* XÑ.Ô.Ñ/Ô/°!Ñ3Ñ4Ô4ð &ð &ˆØ�a‰<˜1ÒÐØ˜A‘ˆAØ×Ò˜q !˜fÑ%Ô%Ð%øàð à˜!ˆ}Ðð €LØ˜1”€IÝ�U‰|Œ|€Hàð ð ‰ˆˆ1Ý�a‘”�5 ™8œ8Ñ#ˆÝ�5˜<Ñ'Ñ(Ô(ˆØ�(Š?ˆ?ØˆHØ˜A˜ˆIøàÐó    Úrequested_framesc                 óp   ‡ — ‰ dk    rt          d‰ ¦  «        S ‰ dv r‰ S g d¢}t          |ˆ fd„¬¦  «        }|S )uÇ   
    Chuáº©n hÃ³a sá»‘ lÆ°á»£ng frame kiá»ƒm duyá»‡t vá»� cÃ¡c giÃ¡ trá»‹ cÃ³ Æ°á»›c sá»‘ tá»‘i Æ°u
    cho mÃ n hÃ¬nh 16:9 (4, 6, 8, 9, 10, 12, 16) Ä‘á»ƒ triá»‡t tiÃªu hoÃ n toÃ n Ã´ Ä‘en rÃ¡c.
    r   r   )é   é   é   é	   é
   é   é   c                 ó(   •— t          | ‰z
  ¦  «        S )N)r   )Úgr%   s    €r"   ú<lambda>z'normalize_frame_count.<locals>.<lambda>`   s   ø€ ­s°1Ð7GÑ3GÑ/HÔ/H€ r$   )Úkey)ÚmaxÚmin)r%   Úgolden_countsÚclosests   `  r"   Únormalize_frame_countr6   T   sa   ø€ ð
 ˜1ÒÐÝ�1Ð&Ñ'Ô'Ð'ØÐ3Ð3Ð3ØÐð -Ð,Ð,€MÝ�-Ð%HÐ%HÐ%HÐ%HÐIÑIÔI€GØ€Nr$   c                   óz  — e Zd ZdZe	 ddeeef         dede	e
eeej        f                  fd„¦   «         Ze	 	 	 	 	 ddeeef         dedeeeef                  de
eef         dedede
eej                 ee         f         fd„¦   «         Ze	 	 ddeeef         dede
eef         dee         fd„¦   «         ZdS )ÚZeroWasteContactSheetuf   
    Ä�á»™ng cÆ¡ táº¡o Contact Sheet khÃ´ng Ã´ Ä‘en rÃ¡c cho quy trÃ¬nh kiá»ƒm duyá»‡t AI Cinema.
    r(   Ú
video_pathÚ
num_framesr   c                 ó–  ‡‡— t          | ¦  «        }|                     ¦   «         r|                     ¦   «         j        dk    rg S t	          j        t          |¦  «        ¦  «        }|                     ¦   «         sg S t          | 	                    t          j
        ¦  «        ¦  «        Š| 	                    t          j        ¦  «        pd}‰dk    r|                     ¦   «          g S t          |¦  «        Š‰dk    r‰dk    rdg‰z  ng }n?‰‰k    rˆˆfd„t          ‰¦  «        D ¦   «         }nˆˆfd„t          ‰¦  «        D ¦   «         }g }|D ]h}|                     t          j        |¦  «         |                     ¦   «         \  }}	|r-|	�+t%          ||z  d¦  «        }
|                     |
||	f¦  «         Œi|                     ¦   «          |S )uÁ   
        TrÃ­ch xuáº¥t num_frames khung hÃ¬nh phÃ¢n bá»‘ Ä‘á»�u trÃªn toÃ n bá»™ thá»�i lÆ°á»£ng video.
        Tráº£ vá»� danh sÃ¡ch cÃ¡c tuple: (timestamp_sec, frame_idx, frame_bgr).
        r   g      8@r   c                 óF   •— g | ]}t          |‰d z
  z  ‰d z
  z  ¦  «        ‘ŒS ©r   ©r   ©Ú.0ÚiÚ
eff_framesÚtotal_framess     €€r"   ú
<listcomp>z@ZeroWasteContactSheet.extract_uniform_frames.<locals>.<listcomp>…   ó4   ø€ ÐaÐaÐaÈ!•s˜1 ¨qÑ 0Ñ1°ZÀ!±^ÑDÑEÔEÐaÐaÐar$   c                 óF   •— g | ]}t          |‰d z
  z  ‰d z
  z  ¦  «        ‘ŒS r=   r>   r?   s     €€r"   rD   z@ZeroWasteContactSheet.extract_uniform_frames.<locals>.<listcomp>ˆ   rE   r$   Nr   )r   ÚexistsÚstatÚst_sizeÚcv2ÚVideoCaptureÚstrÚisOpenedr   ÚgetÚCAP_PROP_FRAME_COUNTÚCAP_PROP_FPSÚreleaser6   r   ÚsetÚCAP_PROP_POS_FRAMESÚreadÚroundr   )r9   r:   Úv_pathÚcapÚfpsÚindicesÚ	extractedÚidxÚretÚframeÚt_secrB   rC   s              @@r"   Úextract_uniform_framesz,ZeroWasteContactSheet.extract_uniform_framesi   sÔ  øø€ õ �jÑ!Ô!ˆØ�}Š}‰Œð 	 &§+¢+¡-¤-Ô"7¸1Ò"<Ð"<ØˆIåÔ�s 6™{œ{Ñ+Ô+ˆØ�|Š|‰~Œ~ð 	ØˆIå˜3Ÿ7š7¥3Ô#;Ñ<Ô<Ñ=Ô=ˆØ�gŠg•cÔ&Ñ'Ô'Ð/¨4ˆØ˜1ÒÐØ�KŠK‰MŒMˆMØˆIå*¨:Ñ6Ô6ˆ
Ø˜1ÒÐØ*6¸!Ò*;Ð*;�q�c˜JÑ&Ð&ÀˆGˆGØ˜ZÒ'Ð'àaÐaÐaÐaÐaÍuÐU_ÑO`ÔO`ÐaÑaÔaˆGˆGð bÐaÐaÐaÐaÍuÐU_ÑO`ÔO`ÐaÑaÔaˆGà9;ˆ	Øð 	6ð 	6ˆCØ�GŠG•CÔ+¨SÑ1Ô1Ð1ØŸš™œ‰JˆC�Øð 6�uÐ(Ý˜c C™i¨Ñ+Ô+�Ø× Ò  %¨¨eÐ!4Ñ5Ô5Ð5øà�Š‰ŒˆØÐr$   N©i€  i8  TFÚoutput_pathÚtarget_sizeÚadd_timestamp_labelsÚpreserve_aspect_ratioc                 óœ  — |                       ||¬¦  «        }|sdS t          |¦  «        }t          |¦  «        \  }	}
|\  }}|r£|d         d         �•|d         d         }t          |j        d         ¦  «        t          |j        d         ¦  «        z  }||	z  }t          t          ||z  ¦  «        ¦  «        }||
z  |k    r$||
z  }t          t          ||z  ¦  «        ¦  «        }n
||	z  }||
z  }t          j        ||
z  ||	z  dft          j	        ¬¦  «        }t          |¦  «        D ]§\  }\  }}}||	z  }||	z  }t          j        |||ft          j        ¬	¦  «        }|rPd
|d›d|› �}t          j        |dddd¦  «         t          j        ||dt          j        dddt          j        ¦  «         ||z  }||z   }||z  }||z   }||||…||…f<   Œ¨d}|rht%          |¦  «        }|j                             dd¬¦  «         t          j        t-          |¦  «        |t          t          j        ¦  «        dg¦  «         n�t%          |¦  «        j                             dd¦  «        }t4          |› d�z  }|j                             dd¬¦  «         t          j        t-          |¦  «        |t          t          j        ¦  «        dg¦  «         ||fS )u�  
        Táº¡o contact sheet dáº¡ng lÆ°á»›i zero-waste:
        - target_size: (width, height) tá»•ng thá»ƒ cá»§a contact sheet.
        - add_timestamp_labels: gáº¯n nhÃ£n thá»�i gian vÃ  sá»‘ thá»© tá»± frame.
        - preserve_aspect_ratio: duy trÃ¬ tá»‰ lá»‡ gá»‘c cá»§a frame trÃ¡nh mÃ©o máº·t/dá»‹ dáº¡ng khi xáº¿p lÆ°á»›i.
        - Tráº£ vá»� (contact_sheet_bgr, output_file_path).
        )r:   )NNr   r   Nr   r   )Údtype)ÚinterpolationzT=z.1fzs | #)r)   r)   )éª   é$   )é   rj   rj   éÿÿÿÿ)é   é   gš™™™™™á?)r   éð   éÿ   T)ÚparentsÚexist_oké\   Ú_10sÚ z_contact_sheet.jpg)r_   Úlenr#   r   Úshaper   rU   ÚnpÚzerosÚuint8Ú	enumeraterJ   ÚresizeÚ
INTER_AREAÚ	rectangleÚputTextÚFONT_HERSHEY_SIMPLEXÚLINE_AAr   ÚparentÚmkdirÚimwriterL   ÚIMWRITE_JPEG_QUALITYÚstemÚreplaceÚCRITIC_QUEUE_DIR) Úclsr9   r:   ra   rb   rc   rd   rZ   Úactual_nÚcolsÚrowsÚtot_wÚtot_hÚfirst_frameÚarÚcell_wÚcell_hÚsheetrA   r^   Ú	frame_idxr]   r   r   Úcell_imgÚlabelÚy_startÚy_endÚx_startÚx_endÚout_pathÚ	shot_stems                                    r"   Úcreate_contact_sheetz*ZeroWasteContactSheet.create_contact_sheet•   s  € ð" ×.Ò.¨zÀjÐ.ÑQÔQˆ	Øð 	Ø�:å�y‘>”>ˆÝ,¨XÑ6Ô6‰
ˆˆdð #‰ˆˆuØ ð 
	# Y¨q¤\°!¤_Ð%@Ø# Aœ, qœ/ˆKÝ�{Ô(¨Ô+Ñ,Ô,­u°[Ô5FÀqÔ5IÑ/JÔ/JÑJˆBØ˜d‘]ˆFÝ�˜v¨™{Ñ+Ô+Ñ,Ô,ˆFØ˜‰}˜uÒ$Ð$Ø $™�Ý�U 6¨B¡;Ñ/Ô/Ñ0Ô0�øà˜d‘]ˆFØ˜d‘]ˆFõ ”˜& 4™-¨°$©¸Ð:Å"Ä(ÐKÑKÔKˆå,5°iÑ,@Ô,@ð 	;ð 	;Ñ(ˆAÑ(��y %Ø�T‘	ˆAØ�D‘ˆAõ ”z %¨&°&Ð)9ÍÌÐXÑXÔXˆHð $ð Ø8˜UÐ8Ð8Ð8¨YÐ8Ð8�å”˜h¨°	¸<ÈÑLÔLÐLÝ”ØØØÝÔ,ØØ!ØÝ”Kñ	ô 	ð 	ð ˜&‘jˆGØ˜fÑ$ˆEØ˜&‘jˆGØ˜fÑ$ˆEà2:ˆE�'˜%�- ¨ Ð.Ñ/Ð/à#'ˆØð 		SÝ˜KÑ(Ô(ˆHØŒO×!Ò!¨$¸Ð!Ñ>Ô>Ð>ÝŒK�˜H™œ u­sµ3Ô3KÑ/LÔ/LÈbÐ.QÑRÔRÐRÐRõ ˜ZÑ(Ô(Ô-×5Ò5°f¸bÑAÔAˆIÝ'¨YÐ*JÐ*JÐ*JÑJˆHØŒO×!Ò!¨$¸Ð!Ñ>Ô>Ð>ÝŒK�˜H™œ u­sµ3Ô3KÑ/LÔ/LÈbÐ.QÑRÔRÐRà�hˆÐr$   c                 óØ   — |                       ||d|d¬¦  «        \  }}|€dS t          j        d|t          t          j        ¦  «        dg¦  «        \  }}|r|                     ¦   «         S dS )uÄ   
        TrÃ­ch xuáº¥t trá»±c tiáº¿p contact sheet dÆ°á»›i dáº¡ng JPEG bytes Ä‘á»ƒ náº¡p vÃ o
        ná»™i dung Multimodal Vision LLM (Google Antigravity SDK hoáº·c Google GenAI Client).
        NT)r:   ra   rb   rc   z.jpgéX   )rœ   rJ   Úimencoder   r„   Útobytes)rˆ   r9   r:   rb   r’   Ú_ÚsuccessÚbufs           r"   Úextract_contact_sheet_bytesz1ZeroWasteContactSheet.extract_contact_sheet_bytesê   s€   € ð ×+Ò+ØØ!ØØ#Ø!%ð ,ñ 
ô 
‰ˆˆqð ˆ=Ø�4å”| F¨EµC½Ô8PÑ4QÔ4QÐSUÐ3VÑWÔW‰ˆ�Øð 	!Ø—;’;‘=”=Ð Øˆtr$   ©r(   )r(   Nr`   TF)r(   r`   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ústaticmethodr   rL   r   r   r   r   r   rw   Úndarrayr_   Úclassmethodr   Úboolrœ   Úbytesr¤   © r$   r"   r8   r8   d   s¢  € € € € € ðð ð ð ð)ð )Ø˜#˜t˜)Ô$ð)àð)ð 
ˆe�E˜3 ¤
Ð*Ô+Ô	,ð)ð )ð )ñ „\ð)ðV ð Ø26Ø'3Ø%)Ø&+ðRð Rà˜#˜t˜)Ô$ðRð ðRð ˜e C¨ IÔ.Ô/ð	Rð
 ˜3 ˜8”_ðRð #ðRð  $ðRð 
ˆx˜œ
Ô# X¨d¤^Ð3Ô	4ðRð Rð Rñ „[ðRðh ð Ø'3ð	ð à˜#˜t˜)Ô$ðð ðð ˜3 ˜8”_ð	ð
 
�%Œðð ð ñ „[ðð ð r$   r8   r(   r`   r9   r:   ra   rb   c                 ó@   — t                                | |||d¬¦  «        S )u9   HÃ m tiá»‡n Ã­ch táº¡o contact sheet khÃ´ng Ã´ Ä‘en rÃ¡c.T)r9   r:   ra   rb   rc   )r8   rœ   )r9   r:   ra   rb   s       r"   Ú!generate_zero_waste_contact_sheetr±   	  s0   € õ !×5Ò5ØØØØØ!ð 6ñ ô ð r$   c                 ó:   — t                                | |¬¦  «        S )u>   HÃ m tiá»‡n Ã­ch trÃ­ch xuáº¥t JPEG bytes cá»§a contact sheet.©r9   r:   )r8   r¤   r³   s     r"   r¤   r¤     s'   € õ
 !×<Ò<ØØð =ñ ô ð r$   Ú__main__z&Zero-Waste Contact Sheet Tiling Engine)Údescriptionz--videoTu&   Ä�Æ°á»�ng dáº«n file video Ä‘áº§u vÃ o)ÚrequiredÚhelpz--framesu5   Sá»‘ khung hÃ¬nh cáº§n láº¥y máº«u (máº·c Ä‘á»‹nh: 6))ÚtypeÚdefaultr·   z--outputu+   Ä�Æ°á»�ng dáº«n file áº£nh Ä‘áº§u ra (.jpg))r¹   r·   )r:   ra   u-   [âœ“] Ä�Ã£ táº¡o Contact Sheet thÃ nh cÃ´ng: u       KÃ­ch thÆ°á»›c: r   Úxu>   [!] KhÃ´ng thá»ƒ táº¡o Contact Sheet tá»« video chá»‰ Ä‘á»‹nh.)r(   Nr`   r¥   )/r©   ÚosÚsysr   Úpathlibr   Útypingr   r   r   r   rJ   Únumpyrw   ÚplatformÚstdoutÚreconfigureÚstderrÚ	ExceptionÚ__file__Úresolver�   ÚBASE_DIRr‡   r   r#   r6   r8   rL   r«   r±   r®   r¤   r¦   ÚargparseÚArgumentParserÚparserÚadd_argumentÚ
parse_argsÚargsÚvideoÚframesÚoutputÚsÚpÚprintrv   r¯   r$   r"   ú<module>rÔ      s„  ððð ð$ 
€	€	€	Ø 
€
€
€
Ø €€€Ø Ð Ð Ð Ð Ð Ø /Ð /Ð /Ð /Ð /Ð /Ð /Ð /Ð /Ð /Ð /Ð /Ø 
€
€
€
Ø Ð Ð Ð ð „<�7ÒÐðØŒ
×Ò¨ÐÑ0Ô0Ð0ØŒ
×Ò¨ÐÑ0Ô0Ð0Ð0øØð ð ð Øˆðøøøð ˆ4�‰>Œ>×!Ò!Ñ#Ô#Ô*Ô1€Ø˜kÑ)¨NÑ:Ð ð( cð (¨e°C¸°H¬oð (ð (ð (ð (ðV¨Cð °Cð ð ð ð ð ^ð ^ð ^ð ^ð ^ñ ^ô ^ð ^ðN Ø.2Ø#/ð	ð Ø�c˜4�iÔ ðàðð ˜%  T 	Ô*Ô+ðð �s˜C�x”ð	ð
 ˆ8�B”JÔ ¨$¤Ð/Ô0ðð ð ð ð$ ðð Ø�c˜4�iÔ ðàðð ˆe„_ðð ð ð ð ˆzÒÐØ€O€O€OØ$ˆXÔ$Ð1YÐZÑZÔZ€FØ
×Ò˜	¨DÐ7_ÐÑ`Ô`Ð`Ø
×Ò˜
¨°aÐ>uÐÑvÔvÐvØ
×Ò˜
¨DÐ7dÐÑeÔeÐeØ×ÒÑÔ€Dà,Ð,¨T¬ZÀDÄKÐ]aÔ]hÐiÑiÔi�D€A€qØð PØˆÐA¸aÐAÐAÑBÔBÐBØˆÐ> Q¤W¨Q¤ZÐ>Ð>°!´'¸!´*Ð>Ð>Ñ?Ô?Ð?Ð?Ð?àˆÐNÑOÔOÐOÐOÐOð Ðs   µ6A, Á,A4Á3A4