
    Ejx2                       d Z ddlmZ ddlmZ ddlmZ  ed           G d d                      Z ed           G d	 d
                      Z ed           G d d                      Z	 ed           G d d                      Z
dddddEdZddddddFd ZdGd#ZdHd&ZdId*ZdJd,Zddd-dKd3ZdLd6ZdMd8ZdNd;ZdOd=ZdPd?ZdQdBZdRdDZdS )Sa  Static active-word caption segment logic.

Caption rule for TrueTraceShorts previews/finals:
- A subtitle phrase segment stays fixed on screen.
- At least three words are visible per default segment whenever possible.
- Only the active spoken word changes highlight.
- The highlight moves left-to-right until the next phrase segment replaces it.
- Caption layout must remain inside the mobile safe zone.
    )annotations)	dataclass)SequenceT)frozenc                  <    e Zd ZU ded<   ded<   ded<   dZded<   dS )	WordCuefloatstartendstrword sentenceN)__name__
__module____qualname____annotations__r        ^/home/agent/jarvis_runtime/autoshortsbot/AutoShortsBot/autoshorts/rendering/static_captions.pyr   r      s>         LLLJJJIIIHr   r   c                  ^    e Zd ZU ded<   ded<   ded<   ded<   dZd	ed
<   edd            ZdS )StaticCaptionSegmentr	   r
   r   ztuple[int, ...]word_indicesztuple[str, ...]wordsr   r   r   returnc                6    d                     | j                  S )N )joinr   )selfs    r   textzStaticCaptionSegment.text!   s    xx
###r   N)r   r   )r   r   r   r   r   propertyr    r   r   r   r   r      so         LLLJJJ!!!!H$ $ $ X$ $ $r   r   c                      e Zd ZU dZded<   dZded<   dZded<   dZded	<   d
Zded<   dZ	ded<   dZ
ded<   dZded<   dZded<   dZded<   dZded<   dZded<   edd            ZdS )CaptionLayoutConfigi8  intvideo_widthi  video_height<   horizontal_margin_pxi  bottom_margin_pxg)\(?r	   max_width_ratio   	max_linesD   font_size_px.   min_font_size_px   line_gap_px   word_gap_px
   highlight_pad_x_px   highlight_pad_y_pxr   c                ~    t          | j        | j        z            }| j        d| j        z  z
  }t	          ||          S )Nr+   )r$   r%   r*   r(   min)r   ratio_widthmargin_widths      r   safe_width_pxz!CaptionLayoutConfig.safe_width_px5   s?    $*T-AABB'!d.G*GG;---r   N)r   r$   )r   r   r   r%   r   r&   r(   r)   r*   r,   r.   r0   r2   r4   r6   r8   r!   r=   r   r   r   r#   r#   &   s        KL """""!O!!!!ILKK     . . . X. . .r   r#   c                  t    e Zd ZU ded<   ded<   ded<   ded<   ded<   ded<   ded	<   ded
<   ded<   ded<   dS )CaptionLayouttuple[tuple[str, ...], ...]linesr$   r.   left_pxright_pxtop_px	bottom_pxwidth_px	height_pxz%tuple[tuple[int, int, int, int], ...]
word_boxesz tuple[int, int, int, int] | Noneactive_word_boxN)r   r   r   r   r   r   r   r?   r?   <   sx         &&&&LLLMMMKKKNNNMMMNNN5555555555r   r?            	min_wordstarget_words	max_words	word_cuesSequence[WordCue]rN   r$   rO   rP   r    tuple[StaticCaptionSegment, ...]c               H    |dk     rt          d          ||k     rt          d          ||k     rt          d          g }d }g }t                     D ]F\  }}|j        pd}	|r|	|k    r|                    |           g }|	}|                    ||f           G|r|                    |           g }
|D ]}g }d}|t	          |          k     rt	          |          |z
  }t          ||          }||k     r&|r$|d                             ||d                     n||k     rQt	          |          |k    r>t          dt	          |          |z
            }|                    ||d                     n8|                    ||||z                       ||z  }|t	          |          k     |D ]}|st	          |          |k    rt	          |          |k    rI|d |         }|
                    t          |                     ||d          }t	          |          |k    Idt	          |          cxk     r|k     r1n n.|
r,|
	                                } fd|j
        D             }||z   }|
                    t          |                     t          |
          S )	Nr+   zmin_words must be >= 2z!target_words must be >= min_wordsz!max_words must be >= target_words__no_sentence__r   c                $    g | ]}||         fS r   r   .0idxrQ   s     r   
<listcomp>z1build_static_caption_segments.<locals>.<listcomp>   s"    !Y!Y!YC3	#"7!Y!Y!Yr   )
ValueError	enumerater   appendlenr:   extendmax_segment_from_chunkpopr   tuple)rQ   rN   rO   rP   groupedcurrent_sentencecurrentindexcuesentence_keysegmentsgroupchunksi	remainingsizer
   chunkheadprevious
prev_pairss   `                    r   build_static_caption_segmentsru   J   s    1}}1222i<===<<===/1G#')+G	** % %
s|8'8 	|'777NN7###G's|$$$$  w+-H 8 824#e**nnE

QI|Y//D9$$$r
!!%),,,iCJJ)$;$;As5zzI566eEFFm,,,MM%AH-...IA #e**nn  	8 	8E 5zzI%%%jj9,, ),DOO$7$=$=>>>!)**-E %jj9,, s5zz----I-----(-'||~~H!Y!Y!Y!Y8CX!Y!Y!YJ&.EOO/667777	8 ??r   N)layoutrN   rO   rP   rv   CaptionLayoutConfig | Nonec               Z    |pt                      }t           |||          }g }|D ]s} fd|j        D             }	g }
|	D ]r}|
|gz   }t          d |D                       }t	          |          |k    rt          ||          r|}
G|
r&|                    t          |
                     |g}
o|g}
s|
rt	          |
          |k     r|rt	          |d         j                  t	          |
          z   |k    r|d         } fd|j        D             |
z   }t          d |D                       }t          ||          rt          |          |d<   -|                    t          |
                     Q|                    t          |
                     ut          |          S )u  Build phrase segments that are pre-split to fit the caption safe zone.

    The function keeps the established 3–7 word phrase behavior, but refuses to
    create a segment that would need more than two lines or exceed the safe
    width at the minimum allowed font size. Very long tokens are handled by
    dynamic shrink in layout, and if a phrase is still too wide the segment is
    split earlier.
    rM   c                $    g | ]}||         fS r   r   rX   s     r   r[   z/build_safe_caption_segments.<locals>.<listcomp>   s"    GGG3#y~&GGGr   c              3  *   K   | ]\  }}|j         V  d S Nr   rY   _ri   s      r   	<genexpr>z.build_safe_caption_segments.<locals>.<genexpr>   s(      #E#ECCH#E#E#E#E#E#Er   rV   c                $    g | ]}||         fS r   r   rX   s     r   r[   z/build_safe_caption_segments.<locals>.<listcomp>   s"    SSS#in 5SSSr   c              3  *   K   | ]\  }}|j         V  d S r{   r|   r}   s      r   r   z.build_safe_caption_segments.<locals>.<genexpr>   s(      $I$I&!SSX$I$I$I$I$I$Ir   )	r#   ru   r   rd   r_   _fits_caption_layoutr^   rb   r   )rQ   rv   rN   rO   rP   cfgbase_segmentssafe_segmentssegmentpairsrg   pair	candidatecandidate_wordsprevmerged_pairsmerged_wordss   `                r   build_safe_caption_segmentsr      s     
)'))C1!	  M 13M  C CGGGG'2FGGG-/ 
	! 
	!D4&(I##E#E9#E#E#EEEO?##y005I/[^5_5_0# !$$%8%A%ABBB&& 	C Gy((! )b)/003w<<?9LL$R(SSSSARSSSV]]$$I$IL$I$I$III'c:: G(;L(I(IM"%%!(()<W)E)EFFFF$$%8%A%ABBBr   rq   Sequence[tuple[int, WordCue]]c           	         t          | d         d         j        | d         d         j        t          d | D                       t          d | D                       | d         d         j                  S )Nr      rV   c              3      K   | ]	\  }}|V  
d S r{   r   )rY   rh   r~   s      r   r   z&_segment_from_chunk.<locals>.<genexpr>   s&      77XUA5777777r   c              3  *   K   | ]\  }}|j         V  d S r{   r|   r}   s      r   r   z&_segment_from_chunk.<locals>.<genexpr>   s(      11CCH111111r   )r
   r   r   r   r   )r   r
   r   rd   r   )rq   s    r   rb   rb      sw    Ahqk"IaL777777711511111q!%   r   	timestampr	   c                    t          |           D ]#\  }}|j        cxk    r|j        k     rn |c S $fdt          |           D             }|r|d         ndS )Nc                0    g | ]\  }}|j         k    |S r   )r
   )rY   rh   ri   r   s      r   r[   z(active_word_index_at.<locals>.<listcomp>   s)    WWW*%	Y@V@V@V@V@Vr   rV   r   )r]   r
   r   )rQ   r   rh   ri   rs   s    `   r   active_word_index_atr      s    	**  
s9	++++CG+++++LLL ,WWWW	)(<(<WWWH#*8B<<*r   rk   Sequence[StaticCaptionSegment]active_word_indexc                L    | D ]}||j         v r|c S t          d| d          )Nzactive word index z is not present in any segment)r   r\   )rk   r   r   s      r   segment_for_active_wordr      sH       444NNN 5
[*;[[[
\
\\r   dict[str, object]c                    t          | |          }t          ||          }|j        |j        |j        || |         j        dS )N)segment_textsegment_wordsr   r   active_word)r   r   r    r   r   r   )rQ   rk   r   active_indexr   s        r   caption_state_atr      sM    '	9==L%h==G ,) .3  r   r   configr   Sequence[str]r   
str | Noner   c               |   |pt                      }| st          d          t          |j        |j        dz
  d          D ]c}t          | ||          }t          ||||          }t          |          |j        k    r%|d         |j	        k    rt          ||||          c S dt          | ||j                  }t          |          |j        k    r=|d |j        dz
           t          d ||j        dz
  d          D                       fz   }t          |||j        |          }t          |||j        |          S )Nzwords must not be emptyr   )r   widthc              3  $   K   | ]}|D ]}|V  d S r{   r   )rY   liner   s      r   r   z)layout_caption_segment.<locals>.<genexpr>   s1      3q3qTlp3q3qdhD3q3q3q3q3q3q3qr   )r#   r\   ranger.   r0   _wrap_words_measure_linesr_   r,   r=   _layout_from_metricsrd   )r   r   r   r   rp   rA   metricss          r   layout_caption_segmentr      s]    
)'))C 42333c&(<q(@"EE C CE3-- T{KKKu::&&77+;s?P+P+P'sD'BBBBB sC$899E
5zzCM!!)))*e3q3qU3=[\K\K^K^E_3q3q3q.q.q-ssUC)=;WWWGsC,@'JJJr   r   boolc                    t          | | r| d         nd |          }t          |j                  |j        k    o|j        |j        k    S )Nr   r   )r   r_   rA   r,   rF   r=   )r   r   rv   s      r   r   r      sJ    #E57RuQxxd[^___Fv|-V&/SEV2VVr   rp   c                    ddl m} dD ]+}	 |                    ||           c S # t          $ r Y (w xY w|                                S )Nr   )	ImageFont)z4/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttfz=/usr/share/fonts/truetype/liberation2/LiberationSans-Bold.ttf)rp   )PILr   truetypeOSErrorload_default)rp   r   paths      r   _fontr     s{      	%%d%66666 	 	 	H	!!###s   %
22r   r   c                    ddl m}m} |                    dd          }|                    |          }|                    d| t          |          d          }|d         |d         z
  S )Nr   )Image	ImageDrawRGB)r5   r5   )r   r   r+   )fontstroke_width)r   r   r   newDrawtextbboxr   )r   rp   r   r   imagedrawbboxs          r   _word_widthr     sp    $$$$$$$$IIeX&&E>>%  D==E$KKa=HHD7T!Wr   r   c                x    | sdS t          fd| D                       |j        t          |           dz
  z  z   S )Nr   c              3  8   K   | ]}t          |          V  d S r{   )r   )rY   r   rp   s     r   r   z_line_width.<locals>.<genexpr>  s-      884{4&&888888r   r   )sumr4   r_   )r   r   rp   s     `r   _line_widthr     sK     q88884888883?cRViiZ[m;\\\r   r@   c                    g g}| D ]X}|d         }||gz   }|r1t          |||          |j        k    r|                    |g           C|                    |           Yt          d |D                       S )NrV   c              3  8   K   | ]}|t          |          V  d S r{   rd   rY   r   s     r   r   z_wrap_words.<locals>.<genexpr>'  s-      77$7t777777r   )r   r=   r^   rd   )r   r   rp   rA   r   rg   r   s          r   r   r     s     TE ! !)tf$	 	!{9c4883;LLLLL$    NN4    77777777r   rA   Sequence[Sequence[str]]c          	        t          dz            }fd| D             }|rt          |          nd}t          |           |z  t          dt          |           dz
            j        z  z   }t          j        j        |z
  dz            }j        j        z
  |z
  }	g }
d }t          |           D ]\  }}t          |          }t          j        j        |z
  dz            }|	||j        z   z  z   }|D ]}t          |          }||||z   ||z   f}|
                    |           |r||k    rlt          j        |d         j        z
            |d         j        z
  t          j        j        z
  |d         j        z             |d         j        z   f}||j        z   z  }||||	t!          |
          |dS )Ngffffff?c                2    g | ]}t          |          S r   )r   )rY   r   r   rp   s     r   r[   z"_measure_lines.<locals>.<listcomp>2  s%    ===tk$T**===r   r   r   r+   rJ   )r   heightlefttoprH   rI   )r$   ra   r_   r2   r(   r%   r&   r)   r]   r   r   r^   r6   r8   r:   r4   rd   )rA   r   rp   r   line_heightwidthsr   r   r   r   rH   
active_box
line_indexr   
line_widthxyr   wwboxs    ``                 r   r   r   *  s    dTk""K=====u===F!(CKKKqEZZ+%As5zzA~(>(>(PPFs'#/E*Aa)GHHD

S1
1F
:C24JJ%e,, & &
D sD11
(3?Z+GA*MNN*co =>> 	& 	&DT4((BaR[1Cc"""!kT&9&90#a&3;Q2QRRFS33#*BBCFSMcDcddFS33	
 co%%AA	& J''%  r   r   c                .   t          |d                   }t          |d                   }t          |d                   }t          |d                   }t          t          d | D                       ||||z   |||z   |||d         |d         
  
        S )	Nr   r   r   r   c              3  4   K   | ]}t          |          V  d S r{   r   r   s     r   r   z'_layout_from_metrics.<locals>.<genexpr>^  s(      22DE$KK222222r   rH   rI   )
rA   r.   rB   rC   rD   rE   rF   rG   rH   rI   )r$   r?   rd   )rA   r   rp   r   r   r   r   r   s           r   r   r   S  s     wvD
gen

C !!E"##F22E22222,<( 12   r   )
rQ   rR   rN   r$   rO   r$   rP   r$   r   rS   )rQ   rR   rv   rw   rN   r$   rO   r$   rP   r$   r   rS   )rq   r   r   r   )rQ   rR   r   r	   r   r$   )rk   r   r   r$   r   r   )rQ   rR   rk   r   r   r	   r   r   )r   r   r   r   r   rw   r   r?   )r   r   r   r#   r   r   )rp   r$   )r   r   rp   r$   r   r$   )r   r   r   r#   rp   r$   r   r$   )r   r   r   r#   rp   r$   r   r@   )
rA   r   r   r#   rp   r$   r   r   r   r   )
rA   r   r   r#   rp   r$   r   r   r   r?   )__doc__
__future__r   dataclassesr   typingr   r   r   r#   r?   ru   r   rb   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>r      s    # " " " " " ! ! ! ! ! !       $        $	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ $. . . . . . . .* $
6 
6 
6 
6 
6 
6 
6 
6  9 9 9 9 9 9~ *.6  6  6  6  6  6 r   + + + +] ] ] ]	 	 	 	 #)-	K K K K K K0W W W W
$ $ $ $   ] ] ] ]	8 	8 	8 	8& & & &R     r   