
    O|%io             	          d Z ddlm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	 ddl
mZ ddlmZ ddlmZmZ 	 ddlmZ ddl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 ddlmZ ddlmZ ddlmZ ddl m!Z!m"Z"m#Z# ddl$Z$ddl%m&Z& ddl'Z'ddl(Z(ejR                  jU                  ejR                  jW                  e,            Z- eejR                  j]                  e-d            5 Z/e/ja                         jc                         Z2ddd       e2Z3dZ4 G d d edddg            Z5 G d d edg d            Z6 G d d edg d            Z7 edd      Z8e8D  cg c]  } | jr                   c} Z:ejR                  j]                  ejR                  jw                  d      d      Z<d Z=d!Z>d"Z?d#Z@d$ZAd%d&gZBejr                  d'k(  rd(Z@d(ZAg d)ZBd*ZCdZDd+ZEeEZFdZGd,ZHeHZId-ZJd.ZKd/ZLd.ZMd0ZNd/ZOd1ZPd1ZQd2ZReRZSeRZTd3ZU e5d4d4      ZVd5ZWd5ZXd,ZYd,ZZd6Z[d7Z\e8j                  Z^dZ_dZ` G d8 d9      Za G d: d;eb      Zc G d< d=eb      Zdeaj                  eaj                  fd>Zgd? Zhd@ ZidA ZjdBee6   fdCZkdDe6fdEZldF Zm	 	 	 	 	 d\dGZneaj                  dfdHZod]dIZpdJ ZqdK ZrdL ZsdM ZtdN ZudO ZvdP ZwdQ ZxdR ZydS ZzdT Z{dU Z|dV Z}dW Z~dX ZdY ZdZ Zed[k(  r e        yy# e$ r  eej(                  d	      ZY w xY w# 1 sw Y   xY wc c} w )^zCreate a video contact sheet.
    )print_functionN)ArgumentTypeError)ThreadPoolExecutor)deepcopy)ListIterable)DEVNULLwb)
namedtuple)Enum)glob)escape)Image	ImageDraw	ImageFont)TemplateVERSIONz
Nils Amietc                       e Zd Zd Zy)Gridc                 8    | j                   d| j                  S Nx)r   yselfs    K/home/uftp/.pyenv/versions/3.12.0/lib/python3.12/site-packages/vcsi/vcsi.py__str__zGrid.__str__0   s    &&$&&))    N)__name__
__module____qualname__r    r   r   r   r   /   s    *r   r   r   r   c                       e Zd Zy)FrameN)r   r    r!   r"   r   r   r$   r$   4   s    r   r$   filename
blurriness	timestamp	avg_colorc                       e Zd Zd Zd Zy)Colorc                 ~    t        |      j                  dd      j                         }t        |      dk(  r|S d|z   S )N0x    0)hexreplaceupperlen)r   	componenths      r   to_hexzColor.to_hex9   s:    	N""4,224FaKq,S1W,r   c                     dj                  | j                  | j                  | j                  | j                  fD cg c]  }| j                  |       c}      S c c}w )Nr.   )joinrgbar7   )r   r   s     r   r   zColor.__str__=   s@    ww0PQ1AQRRQs   AN)r   r    r!   r7   r   r"   r   r   r+   r+   8   s    -Sr   r+   )r:   r;   r<   r=   TimestampPositionz(north south east west ne nw se sw center~z.config/vcsi.confvcsi      z(/usr/share/fonts/TTF/DejaVuSans-Bold.ttfz#/usr/share/fonts/TTF/DejaVuSans.ttfz//usr/share/fonts/truetype/dejavu/DejaVuSans.ttfz /Library/Fonts/Arial Unicode.ttfntzC:/Windows/Fonts/msgothic.ttc)zC:/Windows/Fonts/simsun.ttcz!C:/Windows/Fonts/Everson Mono.ttfzC:/Windows/Fonts/calibri.ttfzC:/Windows/Fonts/arial.ttfi        topffffff000000000000aa   
            d   jpgc                       e Zd ZeZeZeZe	Z
eZeZeZeZeZeZeZeZeZeZeZ e!Z"e#Z$e%Z&e'Z(e)Z*e+Z,e-Z.e/Z0e1Z2e3Z4e5Z6e7Z8e9Z:e;Z<e=Z>e?Z@eAZBeCZDeEZFeGeHfd       ZIy)Configc                 l   t        j                  t              }|j                  |       | j                  j                         D ]A  }|j                  d      rt        | ||j                  t        |t        | |                   C |j                  t        dd       }|rt        |      | _        y y )N)default_section__)fallbackfallback_fonts)configparserConfigParserDEFAULT_CONFIG_SECTIONread__dict__keys
startswithsetattrgetgetattrcomma_separated_string_typerW   )clsr&   configconfig_entryrW   s        r   load_configurationzConfig.load_configuration   s    **;QRHLL--/ 	L&&t,Cvzz& l3 (2 ( 		  $:<LW[\!<^!LC r   N)Jr   r    r!   DEFAULT_METADATA_FONT_SIZEmetadata_font_sizeDEFAULT_METADATA_FONTmetadata_fontDEFAULT_TIMESTAMP_FONT_SIZEtimestamp_font_sizeDEFAULT_TIMESTAMP_FONTtimestamp_fontFALLBACK_FONTSrW   DEFAULT_CONTACT_SHEET_WIDTHcontact_sheet_widthDEFAULT_DELAY_PERCENTdelay_percentDEFAULT_START_DELAY_PERCENTstart_delay_percentDEFAULT_END_DELAY_PERCENTend_delay_percentDEFAULT_GRID_SPACINGgrid_spacingDEFAULT_GRID_HORIZONTAL_SPACINGgrid_horizontal_spacingDEFAULT_GRID_VERTICAL_SPACINGgrid_vertical_spacingDEFAULT_METADATA_POSITIONmetadata_positionDEFAULT_METADATA_FONT_COLORmetadata_font_colorDEFAULT_BACKGROUND_COLORbackground_colorDEFAULT_TIMESTAMP_FONT_COLORtimestamp_font_color"DEFAULT_TIMESTAMP_BACKGROUND_COLORtimestamp_background_colorDEFAULT_TIMESTAMP_BORDER_COLORtimestamp_border_colorDEFAULT_TIMESTAMP_BORDER_SIZEtimestamp_border_sizeDEFAULT_ACCURATE_DELAY_SECONDSaccurate_delay_secondsDEFAULT_METADATA_MARGINmetadata_margin"DEFAULT_METADATA_HORIZONTAL_MARGINmetadata_horizontal_margin DEFAULT_METADATA_VERTICAL_MARGINmetadata_vertical_marginDEFAULT_CAPTURE_ALPHAcapture_alphaDEFAULT_GRID_SIZE	grid_size$DEFAULT_TIMESTAMP_HORIZONTAL_PADDINGtimestamp_horizontal_padding"DEFAULT_TIMESTAMP_VERTICAL_PADDINGtimestamp_vertical_padding#DEFAULT_TIMESTAMP_HORIZONTAL_MARGINtimestamp_horizontal_margin!DEFAULT_TIMESTAMP_VERTICAL_MARGINtimestamp_vertical_marginDEFAULT_IMAGE_QUALITYqualityDEFAULT_IMAGE_FORMATformatDEFAULT_TIMESTAMP_POSITIONtimestamp_positionDEFAULT_FRAME_TYPE
frame_typeDEFAULT_INTERVALintervalclassmethodDEFAULT_CONFIG_FILErf   r"   r   r   rR   rR   y   s    3)M5+N#N5)M51'L=915/7!C;9;-O!C?)M!I#G !C"E A#G!F3#JH)< M Mr   rR   c                       e Zd ZdZddZd ZddZd Zd Zd Z	d Z
ed	        Ze	 	 dd
       Zed        Zej                   fdZd Zd Zed        Zy)	MediaInfoz+Collect information about a video file
    c                    | j                  |       | j                          | j                          | j                          | j	                          | j                          |rt        | j                         t        | j                  d| j                         t        | j                  d| j                         t        | j                         t        | j                         y y r   )probe_mediafind_video_streamfind_audio_streamcompute_display_resolutioncompute_formatparse_attributesprintr&   sample_widthsample_heightdisplay_widthdisplay_heightdurationsize)r   pathverboses      r   __init__zMediaInfo.__init__   s      '')$-- T..0B0BCDT//1D1DEF$-- $)) r   c           	          dddddddd|g	}	 t        j                  |      }t        j                  |j	                  d	            | _        y# t        $ r d
}t        |       Y yw xY w)z'Probe video file using ffprobe
        ffprobe-vquietz-print_formatjsonz-show_formatz-show_streamsz--zutf-8zfCould not find 'ffprobe' executable. Please make sure ffmpeg/ffprobe is installed and is in your PATH.N)
subprocesscheck_outputr   loadsdecodeffprobe_dictFileNotFoundError
error_exit)r   r   ffprobe_commandoutputerrors        r   r   zMediaInfo.probe_media   so     'V
	,,_=F $

6==+A BD  	|Eu	s   >A A%$A%c                 Z    dD ]  }t        |      dk  r
d|||fz  c S |dz  }! d|d|fz  S )z>Converts a number of bytes to a human readable format
        )r.   KiMiGiTiPiEiZig      @z
%3.1f %s%sz	%.1f %s%sYi)abs)r   numsuffixunits       r   human_readable_sizezMediaInfo.human_readable_size   sO     C 	D3x& #sD&&9996MC	 c4000r   c                 ^    | j                   d   D ]  }	 |d   dk(  r	|| _         y y#  Y xY w)z6Find the first stream which is a video stream
        streams
codec_typevideoN)r   video_streamr   streams     r   r   zMediaInfo.find_video_stream   J     ''	2 	F,'72(.D% 3	
   (,c                 ^    | j                   d   D ]  }	 |d   dk(  r	|| _         y y#  Y xY w)z7Find the first stream which is an audio stream
        r   r   audioN)r   audio_streamr   s     r   r   zMediaInfo.find_audio_stream   r   r   c                    t        | j                  d         | _        t        | j                  d         | _        	 t        | j                  d   d         }|dv r#| j                  | j                  c| _        | _        d}	 | j                  d   }|dk(  r#| j                  | _        | j                  | _        ng|j                  d	      }t        |d
         }t        |d         }t        | j                  |z  |z        | _        t        | j                        | _        | j
                  d
k(  r| j                  | _        | j                  d
k(  r| j                  | _        yy# t        $ r d}Y w xY w# t        $ r Y w xY w)zComputes the display resolution.
        Some videos have a sample resolution that differs from the display resolution
        (non-square pixels), thus the proper display resolution has to be computed.
        widthheighttagsrotateN)Z   i  1:1sample_aspect_ratio:r   rJ   )intr   r   r   KeyErrorr   r   split)r   rotationr   sample_splitswshs         r   r   z$MediaInfo.compute_display_resolution   s   
   1 1' :; !2!28!<=	4,,V4X>?H y 484F4FHYHY1Dt1#	"&"3"34I"J %'!%!2!2D"&"4"4D.44S9L\!_%B\!_%B!$T%6%6%;b%@!AD"%d&8&8"9D"!%!2!2D!#"&"4"4D $7  	H	  		s#   E! E3 !E0/E03	E?>E?c                    | j                   d   }	 t        | j                  d         | _        t        j                  | j                        | _        t        j                  j                  |d         | _        t        |d         | _        | j                  | j                        | _        y# t        t
        f$ r t        |d         | _        Y w xY w)z5Compute duration, size and retrieve filename
        r   r   r&   r   N)r   floatr   duration_secondsr   AttributeErrorr   pretty_durationr   osr   basenamer&   r   
size_bytesr   r   )r   format_dicts     r   r   zMediaInfo.compute_format!  s     ''1	C$)$*;*;J*G$HD!
 "11$2G2GH((Z)@Ak&12,,T__=	 .) 	C$)+j*A$BD!	Cs   B- -"CCc                    | j                  d      }d}t        |      dk(  rt        |d         }|d   }n| }|j                  d      }t        |      dkD  rd|  d}t        |      t        |      dk  rd}t        |d         }t        |d         }n*t        |d         }t        |d         }t        |d         }|d	z  |z   |d
z  z   |dz  z   }	|	S )z5Converts pretty printed timestamp to seconds
        .r   r/   rJ   r   rN   z
Timestamp z ill formattedg     @@<     )r   r4   r   r   )
r   millis_splitmillisleft
left_splitehoursminutessecondsresults
             r   pretty_to_secondszMediaInfo.pretty_to_seconds4  s    
 ',,S1|!a)F?D"DZZ_
z?Q_-^<A#A&&z?QE*Q-(G*Q-(G
1&E*Q-(G*Q-(G6/W,w|;edlJr   c           
      T   t        t        j                  | dz              }| d|z  z
  }t        j                  |dz        }|d|z  z
  }d}|dkD  r|t        |      dz  }|t        t        |            j	                  d      dt        t        t        j                  |                  j	                  d      z  }|s|rc|rdnd}|rd	nd}t        j                  |t        j                  |      z
  |z        }	|d
t        t        |	            j	                  |      z  z  }|S )z9Converts seconds to a human readable time format
        r  r  r.   r   r   r/     rO   rN   z.%s)r   mathfloorstrzfill)
r  show_centisshow_millisr
  remaining_secondsr  r   coeffdigitscentiss
             r   r   zMediaInfo.pretty_durationS  s    DJJw~./#dUl2**.34-W<19U--Hs3w<066q93s4::N_C`?a;b;h;hij;kll+'DSE%Q1FZZ!2TZZ@Q5R!RV[ [\FS[!1!7!7!?@@Hr   c                    t        t        j                  | dz              }| d|z  z
  }t        j                  |dz        }|d|z  z
  }t        j                  |      } t        j                  |t        j                  |      z
  dz        }t        j                  |t        j                  |      z
  dz        }||| ||dS )Nr  r  r  rO   )r
  r  r  r  r  )r   r  r  )r  r
  r  r  r  r  s         r   parse_durationzMediaInfo.parse_durationo  s    DJJw~./#dUl2**.34-W<**./.<M1NNRVVW.<M1NNRUUV 
 	
r   c                     |t        | j                        z  }t        t        j                  | j
                  |z              }||fS )zkComputes the height based on a given width and fixed aspect ratio.
        Returns (width, height)
        )r   r   r   r  r  r   )r   r   ratiodesired_heights       r   desired_sizezMediaInfo.desired_size  sB     d0011TZZ(;(;e(CDE~&&r   c                    	 | j                   d   | _        	 | j                   d   | _        	 t	        | j                   d         | _        	 | j                   d   | _        	 | j                   d   | _        	 | j                   d   | _        | j                  j                  d      }t        |      d	k(  r#t	        |d
         t	        |d         z  | _        nt	        | j                        | _        t        | j                  d      | _        	 | j                  d   | _        	 | j                  d   | _        	 t	        | j                  d         | _        	 t	        | j                  d         | _        y# t        $ r d| _        Y mw xY w# t        $ r d| _        Y ow xY w# t        $ r d| _        Y hw xY w# t        $ r d| _        Y jw xY w# t        $ r d| _        Y lw xY w# t        $ r
 d| _        Y t        $ r
 d| _        Y w xY w# t        t        f$ r d| _        Y w xY w# t        t        f$ r d| _        Y w xY w# t        t        f$ r d| _        Y w xY w# t        t        f$ r
 d| _        Y yw xY w)z(Parse multiple media attributes
        
codec_nameNcodec_long_namebit_rater   display_aspect_ratioavg_frame_rate/r/   r   rJ   rN   sample_rate)r   video_codecr   video_codec_longr   video_bit_rater   r%  
frame_rater   r4   roundZeroDivisionErrorr   audio_codecr   audio_codec_longaudio_sample_rateaudio_bit_rate)r   splitss     r   r   zMediaInfo.parse_attributes  sw   	$#00>D	)$($5$56G$HD!	'"%d&7&7
&C"DD	,'+'8'89N'OD$	-(,(9(9:P(QD%	#"//0@ADO__**3/F6{a"%fQi.3vay>"A"%doo"6#DOOQ7DO	$#00>D	)$($5$56G$HD!	*%():):=)I%JD"	'"%d&7&7
&C"DDo  	$#D	$
  	)$(D!	)
  	'"&D	'
  	,'+D$	,
  	-(,D%	-  	#"DO  	#"DO	# .) 	$#D	$
 .) 	)$(D!	)
 .) 	*%)D"	*
 .) 	'"&D	's   E0 F F 
F5 G 4BG# 
H
 H' 4I I! 0FFFFF21F25G	G	G G #H5HH
H$#H$'I III!I:9I:c                 P     t         fdt        j                         D              S )zXReturns the template attributes and values ready for use in the metadata header
        c              3   F   K   | ]  }|d    t        |d          f  yw)nameN)ra   ).0r   r   s     r   	<genexpr>z0MediaInfo.template_attributes.<locals>.<genexpr>  s%     haQvYai 89hs   !)dictr   list_template_attributesr   s   `r   template_attributeszMediaInfo.template_attributes  s     h9CeCeCghhhr   c                     g } | j                  dddd       | j                  dddd       | j                  dd	d
d       | j                  dddd       | j                  dddd       | j                  dddd       | j                  dddd       | j                  dddd       | j                  dddd       | j                  dddd       | j                  ddd d       | j                  d!d"d#d       | j                  d$d%d&d       | j                  d'd(d)d       | j                  d*d+d,d       | j                  d-d.d/d       | j                  d0d1d2d       | j                  d3d4d5d       | S )6zaReturns a list a of all supported template attributes with their description and example
        r   zFile size (pretty format)z	128.3 MiB)r6  descriptionexampler   zFile size (bytes)
4662788373r&   z	File namez	video.mkvr   zDuration (pretty format)z03:07r   zSample width (pixels)1920r   zSample height (pixels)1080r   zDisplay width (pixels)r   zDisplay height (pixels)r)  zVideo codech264r*  zVideo codec (long name)z)H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10r+  zVideo bitrate4000r%  zDisplay aspect ratioz16:9r   zSample aspect ratior   r/  zAudio codecaacr0  zAudio codec (long name)zAAC (Advanced Audio Coding)r1  zAudio sample rate (Hz)44100r2  zAudio bit rate (bits/s)192000r,  zFrame rate (frames/s)z23.974)append)tables    r   r:  z"MediaInfo.list_template_attributes  s    f5P]hijl;N[ghijQ\]^j9S`ghin=Taghio>Vcijko>Vcijk.?XeklmmMV\]^0AZ!LN 	O.[abc4E[hnop3DYfklmmMV[\]0AZ!>@ 	A1BZgnop.?Xemnol;R_ghir   N)F)B)FF)r   r    r!   __doc__r   r   r   r   r   r   r   staticmethodr  r   r  rR   rq   r   r   r;  r:  r"   r   r   r   r      s    (1		'5R>&  <   6 
 
& "(!;!; '?'Bi
  r   r   c                   h    e Zd ZdZdej
                  ej                  fdZd
dZd Z	d Z
ddZd Zy	)MediaCapturezCapture frames of a video
    Fc                 <    || _         || _        || _        || _        y N)r   accurateskip_delay_secondsr   )r   r   rP  rQ  r   s        r   r   zMediaCapture.__init__  s    	 "4$r   c                    t         j                  | j                  d      }dd|d| j                  ddd|d	|g	}| j                  dd| j                  z   dz   g}| j                  dk(  rddg}| j                  |z  }|d|gz  }| j
                  rt         j                  |      }|| j                  z
  }	|	dk  r3dd| j                  d|ddd|d	|g	}| j                  |z  }|d|gz  }nKt         j                  |	d      }
dd|
d| j                  d|ddd|d	|g}| j                  |z  }|d|gz  }	 t        j                  |t        t        t               y
# t        $ r d}t        |       Y y
w xY w)zOCapture a frame at given time with given width and height using ffmpeg
        Tr  ffmpegz-ssz-iz-vframes1-sr   Nz-vfzselect='eq(frame_type\,z)'keyz
select=keyz-yr   )stdinstderrstdoutzeCould not find 'ffmpeg' executable. Please make sure ffmpeg/ffprobe is installed and is in your PATH.)r   r   rQ  r   r   rP  r  r   callr	   r   r   )r   timer   r   out_path
skip_delayffmpeg_commandselect_argstime_secondsskip_time_seconds	skip_timer   s               r   make_capturezMediaCapture.make_capture  s    ..t/F/FTX.Y
 4$))UF+
 ??&1DOOCdJK ??e#|K ??&k)N
 	

 ==$66t<L ,t/F/F F 1$$))4UF3" ??."k1N# 
 &556GUY5Z	9$)):UF3" ??."k1N# 
	OON''RYZ  	{Eu	s   ;%E! !E:9E:c                     t        j                  |      }|j                  d      }|j                         }d}d}|D ]  \  }}||z  }|||z  z  } ||z  }|S )z/Computes the average color of an image
        Pr   )r   openconvert	getcolors)r   
image_pathiptotal_countr)   countcolors           r   compute_avg_colorzMediaCapture.compute_avg_colorD  ss     JJz"IIcNKKM 	 	'LE55 K&I	' 	[ 	r   c                     t        j                  |      }|j                  d      }t        j                  |      }t        t        j                  j                  |            }| j                  |      }|dk7  rd|z  S y)zLComputes the blurriness of an image. Small value means less blurry.
        Lr   rJ   )	r   rg  rh  numpyasarrayr   fftrfft2avg9x)r   rj  rk  r=   r<   max_freqs         r   compute_blurrinesszMediaCapture.compute_blurrinessV  se     JJz"IIcNMM!		"#::a=q=x<r   c                     |j                         }t        |d      }t        t        j                  |t        |      z              }|d| }t        j                  |      S )z_Computes the median of the top n% highest values.
        By default, takes the top 5%
        T)reverseN)flattensortedr   r  r  r4   rs  median)r   matrix
percentagexssrtlengthmatrix_subsets          r   rw  zMediaCapture.avg9xe  sR     ^^R&TZZ
SX 567GV||M**r   c                 >    d}|D ]  }t        |      }||kD  s|} |S )z0Returns the maximum value in the matrix
        r   )max)r   r  mrowmxs        r   rx  zMediaCapture.max_freqp  s4      	CSBAv	
 r   N)zout.png)皙?)r   r    r!   rJ  rR   r   r   r   rd  rp  ry  rw  rx  r"   r   r   rM  rM    s=     ',@]@]"--%JX$	+	r   rM  c                     || j                   dz
  |z  z
  | j                   z  }t        t        j                  |            }|j	                  |      S )zmComputes the size of the images placed on a mxn grid with given fixed width.
    Returns (width, height)
    rJ   )r   )r   r   r  r  r   )grid
media_infor   horizontal_margindesired_widths        r   grid_desired_sizer  |  sL     dffqj,===GM

=12M"""77r   c                     t        j                  | j                  |j                  z  dz        }t        j                  | j                  |j                  z  dz        }||z   }|S )z=Computes the total seconds to skip (beginning + ending).
    rO   )r  r  r   ru   rw   )r  argsstart_delay_secondsend_delay_secondsdelays        r   total_delay_secondsr    s`     **Z%@%@4C[C[%[^a%ab

:#>#>AWAW#WZ]#]^"33ELr   c              #     K   t        | |      }| j                  |z
  |j                  dz   z  }|j                  #t	        |j                  j                               }t        j                  | j                  |j                  z  dz        }||z   }t        |j                        D ]"  }|t        j                  |d      f ||z  }$ yw)a  Generates `num_samples` uniformly distributed timestamps over time.
    Timestamps will be selected in the range specified by start_delay_percent and end_delay percent.
    For example, `end_delay_percent` can be used to avoid making captures during the ending credits.
    rJ   NrO   TrS  )r  r   num_samplesr   r   total_secondsr  r  ru   ranger   r   )r  r  r  capture_intervalr  r\  rk  s          r   timestamp_generatorr    s     
  
D1E"33e;@P@PST@TU}} t}}::<=**Z%@%@4C[C[%[^a%ab!11D4##$ !Y..t.FGG  !s   C
Cc           
         t        |j                  | |j                  |j                        }|j                  t        | |      }n.|j                  D cg c]  }t        j                  |      |f }}fd}g }g }|j                  rt               5 }	t        |      D ]`  \  }
}dj                  |
dz   |j                        }t        |d       d}|	j                  |||d	   |d   ||      }|j                  |       b t                t        |      D ]G  \  }
}d
j                  |
dz   |j                        }t        |d       |j!                         }||gz  }I t                ddd       nct        |      D ]K  \  }
}d
j                  |
dz   |j                        }t        |d       d} |||d	   |d   ||      }||gz  }M t                t#        |d       }|j$                  dkD  rct'        dt)        t+        j,                  t/        |      |j$                  z                    }t1        ||      }|D cg c]  }t3        |       }}n|}t5        ||j6                        }||fS c c}w # 1 sw Y   xY wc c}w )z{Make `num_samples` captures and select `num_selected` captures out of these
    based on blurriness and color variety.
    r   r  Nc                    t        j                  |      \  }}
j                  | d   |||       d}d}|j                  s"
j	                  |      }
j                  |      }t        j                  |       t        ||| d   |      }	|	S )N)r   rJ   r   r%   )	tempfilemkstemprd  fastry  rp  r   closer$   )ts_tupler   r   r   r  fdr&   r'   r)   frmmedia_captures             r   
do_capturez*select_sharpest_images.<locals>.do_capture  s    ''v6H""8A;vxH
	yy&99(CJ%77AI
!qk	
 
r   zStarting task... {}/{}rJ   )endz.jpgr   zSampling... {}/{}z.bmpc                     | j                   S rO  r(   r   s    r   <lambda>z(select_sharpest_images.<locals>.<lambda>  s
    akk r   rW  )r  r  	vcs_widthr{   manual_timestampsr  r   r  r  r   	enumerater   r  r   submitrG  r  r}  
num_groupsr  r   r  r  r4   chunksbestselect_color_varietynum_selected)r  r  r  r   
timestampsr   r  blursfuturesexecutorrk  timestamp_tuplestatusr   futureframetime_sorted
group_sizegroupsselected_itemss    `                  r   select_sharpest_imagesr    s    %		nn66	8L %(T:
CGCYCYZay2215q9Z
Z* EGyy! 	X&/
&; '"?188Q@P@PQf$'!_lSToWcdeWfhnptuv&' G&w/ 	6,33AE4;K;KLf$' 	 G!	 	& #,J"7 	A(//At7G7GHF&d#FQaRXZ^_E E	 	$9:K C

3{+;doo+M NOP
Z0 9?&?1tAw&?&?$).$:K:KLN;&&Q [8	 	L '@s   I5CI:J:Jframesc           	         t        | d       }|d   j                  }|d   j                  }||z
  }t        |dz        }t        | d d      }g }g }	|ri|j                         }
|s||
gz  }nMt	        |D cg c]$  }t        |
j                  |j                  z
        & c}      }||k  r	|	|
|fgz  }	n||
gz  }|ri|t        |      z
  }|dkD  r't        |	d	       }||d
| D cg c]  }|d   	 c}z  }|S c c}w c c}w )zDSelect captures so that they are not too similar to each other.
    c                     | j                   S rO  )r)   r  s    r   r  z&select_color_variety.<locals>.<lambda>  s
    AKK r   r  r   r  c                     | j                   S rO  r'   r  s    r   r  z&select_color_variety.<locals>.<lambda>
  s
    Q\\ r   T)rW  r{  c                      | d   j                   S )Nr   r  r  s    r   r  z&select_color_variety.<locals>.<lambda>  s    1 r   N)r}  r)   r   popminr   r4   )r  r  avg_color_sorted	min_color	max_color
color_spanmin_color_distanceblurriness_sortedr  unselected_itemsr  r   color_distancemissing_items_countremaining_itemss                  r   r  r    s9    f*?@ #--I $..IY&JZ$./v+A4PN
!%%'ug%N n!]#eoo&C"D!]^N 22 !e^%<$== 5')  '^)<<Q !17PQ9M:M)NOA1Q4OO "^ Ps   7)C:'C?capturesc                 $    t        | d       d   S )z%Returns the least blurry capture
    c                     | j                   S rO  r  r  s    r   r  zbest.<locals>.<lambda>'  s
    !,, r   r  r   )r}  )r  s    r   r  r  $  s     ( 67::r   c              #   V   K   t        dt        |       |      D ]  }| |||z      yw)z- Yield successive n-sized chunks from l.
    r   N)r  r4   )lnrk  s      r   r  r  *  s4      1c!fa  !a%js   ')c                     |}||j                   z  }|D ](  }| j                  |j                  |f|||       ||z  }* ||j                   z  }|S )zDraw metadata header
    )fontfill)r   textr   )	drawr  header_line_heightheader_linesheader_fontheader_font_colorstart_heightr6   lines	            r   draw_metadatar  1  sj     	A	&	&&A  		422A6;Uf	g	  	&	&&AHr   c                     || j                   }|d|z  z
  }d}t        t        |      dz         D ]2  }|d| }t        |      dk(  rdn|j                  |      }	|}|	|kD  s1 |S  |S )zEFind the number of characters that fit in width with given font.
    Nr/   r   rJ   )r&   r  r4   	getlength)
r  rj   header_marginr   r  	max_width
max_lengthrk  
text_chunk
text_widths
             r   max_line_lengthr  G  s     |""M))IJ3t9q=! "1X
j/Q.QM4K4KJ4W

	! r   c                 P   d}|d}n$t        |      5 }|j                         }ddd       | j                         }t        |      j	                  |      }|j                  d      }|D 	cg c]!  }	t        |	      dkD  s|	j                         # }}	g }
|D ]{  }|}t        |      dkD  st        | ||||      }t        j                  ||      }|
j                  |d          |t        |d         d j                         }t        |      dkD  rh} |
S # 1 sw Y   xY wc c}	w )zMPrepare the metadata header text and return a list containing each line.
    r.   Nz~{{filename}}
        File size: {{size}}
        Duration: {{duration}}
        Dimensions: {{sample_width}}x{{sample_height}}
r   )r   r  )rg  r[   r;  r   renderr   r4   stripr  textwrapwraprG  )r  r  r  r   template_pathtemplatefparamstemplate_linesr   r  r  remaining_charsmax_metadata_line_lengthwrapss                  r   prepare_metadata_text_linesr  `  s8    H:
 -  	 AvvxH	  ++-F!((0H^^D)N)7FA3q6A:aggiFNFL F/"Q&'6$(&$ MM/3KLEa)-c%(mn=CCEO /"Q&F -	  	  Gs   D+D#?D#D c                 
   | j                   }d}|t        j                  t        j                  t        j                  fv r| j
                  }nd|t        j                  t        j                  t        j                  fv r|d   dz  |d   dz  z
  |z
  }n|d   |d   z
  | j
                  z
  d|z  z
  }d}	|t        j                  t        j                  t        j                  fv r| j                  }	nd|t        j                  t        j                  t        j                  fv r|d   dz  |d   dz  z
  |z
  }	n|d   |d   z
  | j                  z
  d|z  z
  }	||z   ||	z   f}
|
d   |d   z   d|z  z   |
d   |d   z   d|z  z   f}|
|fS )zvCompute the (x,y) position of the upper left and bottom right points of the rectangle surrounding timestamp text.
    r   r/   rJ   )r   r>   westnwr   r   northcentersouthner   east)r  wr6   	text_sizer   rectangle_hpaddingrectangle_vpaddingpositionx_offsety_offset
upper_leftbottom_rights               r   compute_timestamp_positionr    s    &&HH%**,=,@,@BSBVBVWW33	'--/@/G/GIZI`I`a	a Oa'IaL1,<=@RR?Yq\1D4T4TTWX[mWmmH%((*;*A*ACTCWCWXX11	',,.?.F.FHYH^H^_	_ Oa'IaL1,<=@RR?Yq\1D4R4RRUVYkUkk 	
H	HJ 	1	!$q+='==1	!$q+='==L
 |##r   c                    | j                   rt        d       |gt        z   }||k(  rv|D ]R  }| j                   rt        d|       t        j                  j                  |      s;	 t        j                  ||      c S  t        d       t        j                         S 	 t        j                  ||      S # t        $ r Y w xY w# t        $ r t        dj                  |             Y yw xY w)z>Loads given font and defaults to fallback fonts if that fails.zLoading font...zTrying to load font:zFalling back to default font.zCannot load font: {}N)
is_verboser   ro   r   r   existsr   truetypeOSErrorload_defaultr   r   )r  	font_path	font_sizedefault_font_pathfontsr  s         r   	load_fontr    s     K.(E%% 	D,d3ww~~d#$--dI>>	 	-.%%''	A%%i;;    	A-44Y?@	As$   %B4C 4	C ?C #C)(C)c                   12345 t        j                  | j                  j                        }j                  j                  |d   j                  z   z  j                  z
  }j                  j
                  |d   j                  z   z  j                  z
  }t        j                  j                  t        j                        3t        j                  j                  t        j                        }t        | 3j                  |j                        5d}t!        j                  |z        4dj"                  z  t%        5      4z  z   }j&                  dk(  rd}|}	||z   }
d}t)        j*                  d	|	|
fj,                        }t)        j*                  d	|	|
f|      }t)        j*                  d	|	|
f|      }t)        j*                  d	|	|
f|      }t)        j*                  d	|	|
f|      }t/        j0                  |      1t/        j0                  |      }t/        j0                  |      }d212345fd
}j&                  dk(  r |       2d}t3        |d       }t5        |      D ]  \  }}t)        j6                  |j8                        }|j;                  j<                         |j?                  ||2f       j@                  rtB        jE                  |jF                  d      }tB        jE                  | jH                  d      }tB        jK                  |jF                        }tB        jK                  | jH                        }|||dz   tM        |d         jO                  d      tM        |d         jO                  d      tM        |d         jO                  d      tM        |d         jO                  d      tM        |d         jO                  d      tM        |d         jO                  d      tM        |d         jO                  d      tM        |d         jO                  d      tM        |d         jO                  d      tM        |d         jO                  d      d} jP                  jR                  di |}|jU                  |      }|\  }} }!}"tW        |!|z
        }#tW        | |"z
        }$|#|$f}%jX                  }&jZ                  }'t]        |2|%||&|'      \  }(})j^                  s |ja                  |(|)gjb                         njd                  }*g d}+g },tg        d|*dz         D ]#  }-|,|+D .cg c]  }.|.d   |-z  |.d   |-z  f c}.z  },% |,D ]<  }/|ji                  |(d   |&z   |/d   z   |(d   |'z   |/d   z   f||jj                  d       > |ji                  |(d   |&z   |(d   |'z   f||jl                  d       ||d   j                  z   z  }|dz   j                  j                  z  dk(  r2|d   j                  z   z  2|dz   j                  j                  z  dk(  sd} j&                  dk(  r2j                  z  2 |       2t)        jn                  ||      }0t)        jn                  |0|      }0t)        jn                  |0|      }0t)        jn                  |0|      }0|0S c c}.w )zCreates a video contact sheet with the media information in a header
    and the selected frames arranged on a mxn grid with optional timestamps
    r  r   rJ   )r  g333333?r/   hidden)rL   rL   rL   r   RGBAc            	      <    t          j                        S )z+Draw metadata with fixed arguments
        )r  r  r  r  r  )r  r   )r  draw_header_text_layerr6   r  r  r  s   r   draw_metadata_helperz3compose_contact_sheet.<locals>.draw_metadata_helper  s-     "1%#"66 	r   rF   c                     | j                   S rO  r  r  s    r   r  z'compose_contact_sheet.<locals>.<lambda>  s
    !++ r   r  T)r  r
  r  r  r  r  rN   )TIMEDURATIONTHUMBNAIL_NUMBERHMScr  dHdMdSdcdm)r  ))rJ   r   )r  r   )r   rJ   )r   r  )rJ   rJ   )rJ   r  )r  rJ   )r  r  lt)r  r  anchorbottomr"   )8r  r  r  r{   r   r   r}   r  rj   rh   rR   rn   rl   r  r   metadata_template_pathr   r   r4   r   r   newr   r   Drawr}  r  rg  r&   putalphar   pasteshow_timestampr   r   r(   r   r  r  r  timestamp_formatr   getbboxr   r   r   r  timestamp_border_mode	rectangler   r   r  r  r   r   alpha_composite)6r  r  r  r   r   r   rn   line_spacing_coefficientheader_heightfinal_image_widthfinal_image_heighttransparentimageimage_capture_layerimage_header_text_layerimage_timestamp_layerimage_timestamp_text_layerdraw_timestamp_layerdraw_timestamp_text_layerr$  r
  rk  r  r  timestamp_timetimestamp_durationparsed_timeparsed_durationtimestamp_argstimestamp_text	text_bboxr  rF   rightr4  r  text_heightr  r  r  r  r  offset_factoroffsetsfinal_offsetsoffset_counterr   offset	out_imager#  r6   r  r  r  s6     `                                              @@@@@r   compose_contact_sheetr[    s    %		nn66	8L
 IIKK<?T-I-IIJTMiMiiEYY[[LOd.H.HHIDLfLffFD$"4"4d6M6MvOcOcdKtT%8%8$:R:RTZTiTijN.''113L  #T447OOP,,,s</@CU/UUM)-/$KIIf02DEtG\G\]E))F->@R,SU`a#ii1BDV0WYde!IIf/@BT.UWbc!&64EGY3Z\g!h&^^,CD$>>*?@ )/I J	A
 
 & " 	
AF 56Ff% `5JJu~~&	

4%%&!!!aV, &66uTX6YN!*!:!::;V;Vdh!:!i#225??CK'66z7R7RSO&.$%EW-.44Q7Y/066q9Y/066q9X./55a8X./55a8/'2399!</)45;;A>/)45;;A>/(34::1=/(34::1=N :T2299KNKN&..~>I)2&T3vUT\*JcFl+K#[1I "&!B!B!%!@!@'A$1iYeBTVh(j$J --$...88 / 
 !% : :	 !#&+A}q/@&A gN!^e%fYZqtn'<ad^>S&T%ffMg , F-22&qM,>>J&qM,>>J '+!88# 3 	 &**qM$66qM$66 #.. + 	 	
\!_t;;;; ETYY[[ A%a4#=#===A ETYY[[ A%AA`F )	T''' " %%e-@AI%%i1HII%%i1FGI%%i1KLIc &gs   [
c                     |j                  d      }	 |j                  |d| j                         y# t        $ r Y yw xY w)z$Save the image to `output_path`
    RGBT)optimizer   F)rh  saveimage_qualityr   )r  rE  r  output_paths       r   
save_imagerb  o  sD     MM% E

;t7I7I
J s   2 	>>c                    |j                   r#t        dj                  t        |                    | D ]R  }	 |j                   r$t        dj                  |j                               t        j                  |j                         T y# t        $ rE}|j                   r/t        dj                  |j                               t        |       Y d}~d}~ww xY w)zDelete temporary captures
    zDeleting {} temporary frames...zDeleting {} ...z[Error] Failed to delete {}N)r  r   r   r4   r&   r   unlink	Exception)r  r  r  r	  s       r   cleanuprf  z  s     /66s6{CD 	'..u~~>?IIenn%	
  	3::5>>JKa	s   AB	C;CCc                  8   t         j                         } t        j                         }|j	                  g d       | D cg c]  }|d   |d   |d   g }}|j                  |d       |j                  g d       t        |j                                yc c}w )	zFDisplay all the available template attributes in a tabular format
    )trh  rh  r6  r=  r>  F)header)zAttribute nameDescriptionExampleN)	r   r:  	texttable	Texttableset_cols_dtypeadd_rowsri  r   r  )rH  tabr   rowss       r   print_template_attributesrr    s     ..0E



C'AFGAQvY-(!I,7GDGLLeL$JJ;<	#((* Hs    Bc                    	 | j                  d      }t        |      dk(  sJ t        |d         }|dk\  sJ t        |d         }|dk\  sJ t        ||      S # t        t
        t        f$ r d}t        j                  |      w xY w)zType parser for argparse. Argument of type "mxn" will be converted to Grid(m, n).
    An exception will be thrown if the argument is not of the required form
    r   r/   r   rJ   z[Grid must be of the form mxn, where m is the number of columns and n is the number of rows.)	r   r4   r   r   
IndexError
ValueErrorAssertionErrorargparser   )stringr   r  r  r   s        r   mxn_typery    s    
0S!E
a aMQaMQAqz
N3 0m((//0s   AA ,Bc                 |    g d}| j                         }||v r|S dt        |      z  }t        j                  |      )zType parser for argparse. Argument of type string must be one of ["top", "bottom", "hidden"].
    An exception will be thrown if the argument is not one of these.
    )rF   r4  r   z*Metadata header position must be one of %s)lowerr  rw  r   )rx  valid_metadata_positionslowercase_positionr   s       r   metadata_position_typer~    sF      ;55!!<D\@_`((//r   c                     	 t        t        j                  |             }t        |      dk(  r|dz  }t	        | }|S #  d}t        j                  |      xY w)zType parser for argparse. Argument must be an hexadecimal number representing a color.
    For example 'AABBCC' (RGB) or 'AABBCCFF' (RGBA). An exception will be raised if the argument
    is not of that form.
    rN   )rL   z9Color must be an hexadecimal number, for example 'AABBCC')tuple	bytearrayfromhexr4   r+   rw  r   )rx  
componentsr,  r   s       r   hex_color_typer    s^    
09,,V45
z?a& J:0K((//s	   := Ac                    	 | j                  d      }|D cg c]  }|s|j                          }}|D ]  }t        j                  |        |S c c}w # t        $ r'}t        |       d}t        j                  |      d}~ww xY w)zType parser for argparse. Argument must be a comma-separated list of frame timestamps.
    For example 1:11:11.111,2:22:22.222
    ,zLManual frame timestamps must be comma-separated and of the form h:mm:ss.mmmmN)r   r  r   r  re  r   rw  r   )rx  r  r   rh  r	  r   s         r   r  r    s    0\\#&
)39Aqaggi9
9  	+A''*	+  :  0a^((//0s,   A AAA A 	B"BBc                     	 t        t        |       S # t        $ r" d| dt        }t	        j
                  |      w xY w)zEType parser for argparse. Argument must be a valid timestamp positionzInvalid timestamp position: z. Valid positions are: )ra   r>   r   VALID_TIMESTAMP_POSITIONSrw  r   )rx  r   s     r   timestamp_position_typer    s@    0(&11 0MSUno((//0s    +=c                     t         j                   j                  }t        j                         }|j	                  | |      d   |z
  }||k(  r&dj                  |       }t        j                  |      |S )a  Type parser for argparse. Argument must be a valid interval format.
    Supports any format supported by `parsedatetime`, including:
        * "30sec" (every 30 seconds)
        * "5 minutes" (every 5 minutes)
        * "1h" (every hour)
        * "2 hours 1 min and 30 seconds"
    )
sourceTimer   zInvalid interval format: {})datetimer  parsedatetimeCalendarparseDTr   rw  r   )rx  r  calr   r   s        r   interval_typer    sl     	A

 
 
"C{{6a{03a7H1}-44V<((//Or   c                     | j                  d      }|D cg c]  }|j                          }}|D cg c]  }t        |      dkD  s| }}|S c c}w c c}w )zMType parser for argparse. Argument must be a comma-separated list of strings.r  r   )r   r  r4   )rx  r3  r   s      r   rb   rb     sS    \\#F!'(Aaggi(F(.A3q6A:a.F.M ).s   AAAc                      t        d|        y)zPrint an error message.z[ERROR] N)r   messages    r   r   r     s    	'
#$r   c                 D    t        |        t        j                  d       y)zPrint an error message and exitr  N)r   sysexitr  s    r   r   r     s    	'NHHRLr   c            	         t        j                  d      } | j                  dddd       | j                         \  }}	 |j                  rUt
        j                  j                  |j                        r t        j                  |j                         nHt        d       n<t
        j                  j                  t              rt        j                  t               t        j                  d	t         j                  
      }|j                  dd       |j                  dddd       |j                  dddt               |j                  dddt         t        j"                         |j                  dddt         t        j$                         |j                  dddt         t        j&                         |j                  dd d!t         t        j(                         |j                  d"d#d$t         t        j*                         |j                  d%d&d't         t        j,                         |j                  d(d)d*d+t         t        j.                         |j                  d,d-d.d/t0        t        j2                         |j                  d0d1d2d3t         d       |j                  d4d5d6d7d89       |j                  d:d;d<t         t        j4                         |j                  d=d>d?t        j6                  @       |j                  dAdBdCt         t        j8                         |j                  dDdEdFt        j:                  @       |j                  dGdHdIt<        t        j>                         |j                  dJdKdLt@        tA        t        jB                               |j                  dMdNdOt@        tA        t        jD                               |j                  dPdQdRt@        tA        t        jF                               |j                  dSdTdUt@        tA        t        jH                               |j                  dVdWdXt@        tA        t        jJ                               |j                  dYdZd[d@       |j                  d\d]d^d_tL        d       |j                  d`dad6dbdc9       |j                  ddded6dfdg9       |j                  dhdit         t        jN                  djdkl       |j                  dmt         t        jP                  dndol       |j                  dpt         t        jR                  dqdrl       |j                  dst         t        jT                  dtdul       |j                  dvt         t        jV                  dwdxl       |j                  dyt         t        jX                  dzd{l       |j                  d|t         t        jZ                  d}d~l       |j                  dt         t        j\                  ddl       |j                  dt         t        j^                  ddl       |j                  ddt`        t        jb                  ddl       |j                  ddtd        t        jf                  dth        ddl       |j                  ddd6dd9       |j                  dd6dd9       |j                  dt         t        jj                  ddl       |j                  dt         t        jl                  ddl       |j                  dddjc                  tn                     |j                  dd6d       |j                  dt`        tp        ddl       |j                  dtr        t        jt                  ddl       |j                  dd6dd9       |j                  dd6dd9       |j                  dtv        g ddl       |j                  dd6dd9       |j                  ddddd       |j                  dddd6d       |j                  dddd¬       |jy                         }|jz                  rt}                t        j                  dë       dĄ }|j                  r`|j                  D ]P  }t        j                  |      D ]6  \  }}	}
|
D ]+  }t
        j                  j                  ||      } |||       - 8 R y|j                  D ]  }t
        j                  j                  |      rdt        j                  |      D ]K  }t
        j                  j                  ||      }t
        j                  j                  |      rC |||       M t        t        |            }t        |      dk(  r|g}|D ]  } |||         y# t        j                  $ r }t        |j                         Y d}~d}~ww xY w)zProgram entry point
    F)add_helpz-cz--config
configfileN)destdefaultzCould find config filezCreate a video contact sheet)r=  formatter_class	filenames+)nargsz-oz--outputzsave to output filera  )helpr  z!Config file to load defaults from)r  r  z--start-delay-percentz:do not capture frames in the first n percent of total timeru   )r  r  typer  z--end-delay-percentz9do not capture frames in the last n percent of total timerw   z--delay-percentzCdo not capture frames in the first and last n percent of total timers   z--grid-spacingzBnumber of pixels spacing captures both vertically and horizontallyry   z--grid-horizontal-spacingz.number of pixels spacing captures horizontallyr{   z--grid-vertical-spacingz,number of pixels spacing captures verticallyr}   z-wz--widthz$width of the generated contact sheetr  z-gz--gridzdisplay frames on a mxn grid (for example 4x5). The special value zero (as in 2x0 or 0x5 or 0x0) is only allowed when combined with --interval or with --manual. Zero means that the component should be automatically deduced based on other arguments passed.r  rV  z--num-samplesznumber of samplesr  z-tz--show-timestamp
store_truez display timestamp for each framer:  )actionr  r  z--metadata-font-sizez"size of the font used for metadatarh   z--metadata-fontzTTF font used for metadatarj   )r  r  r  z--timestamp-font-sizez$size of the font used for timestampsrl   z--timestamp-fontzTTF font used for timestampsrn   z--metadata-positionzKPosition of the metadata header. Must be one of ['top', 'bottom', 'hidden']r   z--background-colorz:Color of the background in hexadecimal, for example AABBCCr   z--metadata-font-colorz=Color of the metadata font in hexadecimal, for example AABBCCr   z--timestamp-font-colorz>Color of the timestamp font in hexadecimal, for example AABBCCr   z--timestamp-background-colorzNColor of the timestamp background rectangle in hexadecimal, for example AABBCCr   z--timestamp-border-colorz@Color of the timestamp border in hexadecimal, for example AABBCCr   z
--templatezPath to metadata template filer5  z-mz--manualzTComma-separated list of frame timestamps to use, for example 1:11:11.111,2:22:22.222r  r   z	--verbosezdisplay verbose messagesr  z-az
--accuratezMake accurate captures. This capture mode is way slower than the default one
        but it helps when capturing frames from HEVC videos.is_accuratez-Az--accurate-delay-secondszFast skip to N seconds before capture time, then do accurate capture
        (decodes N seconds of video before each capture). This is used with accurate capture mode only.r   )r  r  r  r  z--metadata-marginz*Margin (in pixels) in the metadata header.r   z--metadata-horizontal-marginz5Horizontal margin (in pixels) in the metadata header.r   z--metadata-vertical-marginz3Vertical margin (in pixels) in the metadata header.r   z--timestamp-horizontal-paddingz.Horizontal padding (in pixels) for timestamps.r   z--timestamp-vertical-paddingz,Vertical padding (in pixels) for timestamps.r   z--timestamp-horizontal-marginz-Horizontal margin (in pixels) for timestamps.r   z--timestamp-vertical-marginz+Vertical margin (in pixels) for timestamps.r   z	--qualityzPOutput image quality. Must be an integer in the range 0-100. 100 = best quality.r`  z-fz--formatzWOutput image format. Can be any format supported by pillow. For example 'png' or 'jpg'.image_formatz-Tz--timestamp-positionz#Timestamp position. Must be one of r  r   z-rz--recursivez:Process every file in the specified directory recursively.	recursivez--timestamp-border-modezCDraw timestamp text with a border instead of the default rectangle.r=  z--timestamp-border-sizezPSize of the timestamp border in pixels (used only with --timestamp-border-mode).r   z--capture-alphaz_Alpha channel value for the captures (transparency in range [0, 255]). Defaults to 255 (opaque)r   z	--versionversionz%(prog)s version {version})r  )r  r  z--list-template-attributesr:  )r  r  z--frame-typezFrame type passed to ffmpeg 'select=eq(pict_type,FRAME_TYPE)' filter. Should be one of ('I', 'B', 'P') or the special type 'key' which will use the 'select=key' filter instead.r   z
--intervalzCapture frames at specified interval. Interval format is any string supported by `parsedatetime`. For example '5m', '3 minutes 5 seconds', '1 hour 15 min and 20 sec' etc.r   z--ignore-errorsz^Ignore any error encountered while processing files recursively and continue to the next file.ignore_errorsz--no-overwritez{Do not overwrite output file if it already exists, simply ignore this file and continue processing other unprocessed files.no_overwritez--exclude-extensionsz8Do not process files that end with the given extensions.exclude_extensionsz--fastzwFast mode. Just make a contact sheet as fast as possible, regardless of output image quality. May mess up the terminal.r  z-Oz--thumbnail-outputzSave thumbnail files to the specified output directory. If set, the thumbnail files will not be deleted after successful creation of the contact sheet.thumbnail_output_path)r  r  r  z-Sz--actual-sizezqMake thumbnails of actual size. In other words, thumbnails will have the actual 1:1 size of the video resolution.actual_size)r  r  r  z--timestamp-formata  Use specified timestamp format. Replaced values include: {TIME}, {DURATION}, {THUMBNAIL_NUMBER}, {H} (hours), {M} (minutes), {S} (seconds), {c} (centiseconds), {m} (milliseconds), {dH}, {dM}, {dS}, {dc} and {dm} (same as previous values but for the total duration). Example format: '{TIME} / {DURATION}'. Another example: '{THUMBNAIL_NUMBER}'. Yet another example: '{H}:{M}:{S}.{m} / {dH}:{dM}:{dS}.{dm}'.z{TIME}r;  r   c                     	 t        | |       y # t        $ r: |j                  s t        dj	                  |       t
        j                         Y y w xY w)Nz*[WARN]: failed to process {} ... skipping.)file)process_filere  r  r   r   r  rY  )filepathr  s     r   process_file_or_ignorez$main.<locals>.process_file_or_ignoreS  sL    	f4( 	f%%BII(SZ]ZdZde		fs    A AA)Jrw  ArgumentParseradd_argumentparse_known_argsr  r   r   r  rR   rf   r   r   rX   MissingSectionHeaderErrorr  ArgumentDefaultsHelpFormatterr   ru   rw   rs   ry   r{   r}   rq   ry  r   rh   rj   rl   rn   r~  r   r  r   r   r   r   r   r  r   r   r   r   r   r   r   r   r   r  r   r  r   r  r   r   __version__r   r  r   rb   
parse_argsr:  rr  r  r  r  r  walkr9   isdirlistdirr   r   r4   )preargparserpreargs_r	  parserr  r  r   rootsubdirsfilesr  r  abs_filepathfiles_to_processr&   s                   r   mainr    sr
    **E:LdJ\4P..0JGQ ww~~g001))'*<*<=34 ww~~12))*=> $$1O5=5[5[]F
3/
j"   j0#  
 I"**  , H ((  * R$$  & Q##  % #=&..  0 !;$,,  . i3**  , h O    " o     /	  
 1!))  + )$$	  &
 3"**  , +%%	  '
 Z #((  * Iv667  9 L"v99:  <  M#v::;  = &])v@@A  C "O%v<<=  ? -%	  
 jc    k'	  
 l@   (--k%  ' &&9    &11D)  + $//B'  ) (33=+  - &11;)  + '22<*  , %00:(  * _   jf   $$))9RT!  # mI	  
 !R$	  &
 !,,_$  & $$n   ,33K3H  J $'  ) " @    z   m	  
  K	   (G!    G	  
 " g$	   o A	    e	   D$$!#f ~~NN 	;D(* ;$gu ;A!ww||D!4H*8T:;;	; NN 	;Dww}}T" "

4 0 CH#%77<<h#?L77==6.|TBC $(t#5 '(A-(,v$ 0 ;H*8T:;	;S
 11 199s    Bf g&ggc                 P   |j                   rt        dj                  |              t        |      }t        j
                  j                  |       sC|j                  rt        dj                  |              ydj                  |       }t        |       | j                         j                  d      d   }||j                  v rt        dj                  |             y|j                  }|s| dz   |j                  z   }nlt        j
                  j                  |      rMt        j
                  j                  |t        j
                  j!                  |       dz   |j                  z         }|j"                  r:t        j
                  j                  |      rt        dj                  |             yt        d	j                  |              |j$                  |j&                  t        d
       |j(                  t*        k7  r|j,                  rt        d       |j.                  "|j.                  |_        |j.                  |_        d|_        t7        | |j                         }t9        | |j:                  |j<                  |j>                        }|j@                  tB        k(  s"|j@                  |_"        |j@                  |_#        |j$                  K|j&                  ?|jH                  jJ                  dk(  s|jH                  jL                  dk(  rd}t        |       |j$                  rtO        ||      }|jP                  |z
  }	tS        jT                  |	|j$                  jW                         z        |_,        |jX                  |_-        |jX                  |_        |j&                  *t]        |j&                        }
|
|_-        |
|_,        |
|_        |j$                  |j&                  tS        j^                  tS        j`                  |jX                              }|jH                  tb        k(  rte        ||      |_$        n-|jH                  jJ                  dk(  r+|jH                  jL                  dk(  rte        ||      |_$        n|jH                  jJ                  dk(  r\tS        j^                  |jX                  |jH                  jL                  z        }te        ||jH                  jL                        |_$        nt|jH                  jL                  dk(  r[tS        j^                  |jX                  |jH                  jJ                  z        }te        |jH                  jJ                  |      |_$        |jH                  jJ                  |jH                  jL                  z  |_-        |jX                  |jZ                  |_,        |j4                  |jZ                  |_        |j$                  |j&                  |jZ                  |j4                  kD  r|jZ                  |_        |jZ                  |jX                  kD  r|jZ                  |_,        |jX                  |jZ                  k  s|jX                  |j4                  k  r"|jZ                  |_,        |jZ                  |_        |jf                  "|jf                  |_4        |jf                  |_5        |j,                  r?|jH                  jJ                  }|jl                  }||z  |dz
  |jh                  z  z   |_        to        |||      \  }}t        d       tq        |||      }ts        ||||      }|jt                  }|t	        jv                  |d       t        dj                  |             ty        t{        |d             D ]  \  }}t        |j|                         |j|                  j                         j                  d      d   }dj                  t        j
                  j!                  |       t        |      j                  d      |      }t        j
                  j                  ||      }t        j                  |j|                  |        t        d       t        ||       |st        d|j                  d       yy)z>Generate a video contact sheet for the file at given path
    zConsidering {}...z!File does not exist, skipping: {}NzFile does not exist: {}r  r  z'[WARN] Excluded extension {}. Skipping.z1[INFO] contact-sheet already exists, skipping: {}zProcessing {}...z4Cannot use --interval and --manual at the same time.z6Cannot use --width and --actual-size at the same time.rE   )r   )rP  rQ  r   r   zIRow or column of size zero is only supported with --interval or --manual.rJ   zComposing contact sheet...T)exist_okzCopying thumbnails to {} ...c                     | j                   S rO  r  )x_frames    r   r  zprocess_file.<locals>.<lambda>  s    gN_N_ r   r  z{filename}.{number}.{extension}rM   )r&   number	extensionzCleaning up temporary files...zUnsupported image format: )Dr  r   r   r   r   r   r  r  r   r{  r   r  ra  r  r  r9   r   r  r   r  r  rp   r  rs   ru   rw   r  r   rM  r  r   r   r   r   r   r   r  r   r   r  r   r  r  r  r  r  r4   ceilsqrtr   r   ry   r{   r}   r   r  r[  rb  r  makedirsr  r}  r&   r  r  shutilcopyfilerf  )r   r  error_messagefile_extensionra  r  r  r   total_delayselected_durationmframes_sizesquare_sider   r   r   selected_framestemp_framesrE  is_save_successfulr  rk  r  thumbnail_file_extensionthumbnail_filenamethumbnail_destinations                            r   r  r  r  s    !((./D>D77>>$5<<TBC5<<TBM}%ZZ\'',R0N0007>>~NO""KSj4#4#44	{	#ggll;0@0@0F0LtO`O`0`a77>>+&ELL[YZ	

#
#D
)*}} T%;%;%GIJ~~449I9IKL%#'#5#5 !%!3!3DO!J !!!66??	M #::*.*>*>'(,(<(<%}}!7!7!?TYY[[TUEUY]YbYbYdYdhiYi[5}} )*d;&77+E::&7$--:U:U:W&WX ,,** )4112('&}} D$:$:$Fii		$*:*: ;<99))[+6DIYY[[A$))++"2[+6DIYY[[A		$**TYY[[89AQ		,DIYY[[A		$**TYY[[89ATYY[[!,DI		diikk1D,,++ }}!7!7!?t."//DOt///#00D d///43C3Cdoo3U#00D"//DO$'+'8'8$%)%6%6"IIKK((Ua!et/K/K%KK#9*mUY#Z O[	
&'!*otDE#D%[I !66(
)D9,334IJK!&>_"`a 	CHAu%..!',~~';';'='C'CC'H'L$!B!I!ISUSZSZScScdhSiQTUVQWQ]Q]^_Q`Tl "J "n %'GGLL1FHZ$[!OOENN,AB	C 

*+Kd6G6GIJ r   __main__)NNNNNrO  )rJ  
__future__r   r  r   r  r   r  rw  r   concurrent.futuresr   copyr   typingr   r   r	   ImportErrorrg  devnullrX   r   r  r  r  collectionsr   enumr   r   r   PILr   r   r   rs  jinja2r   rl  r  r   abspathdirname__file__herer9   r  readliner  r   r  
__author__r   r$   r+   r>   r6  r  
expanduserr   rZ   rg   rk   ri   rm   ro   rp   rr   rt   rv   rx   rz   r|   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   ser   r   r   rR   objectr   rM  rq   r{   r  r  r  r  r  r  r  r  r  r  r  r  r[  rb  rf  rr  ry  r~  r  r  r  r  rb   r   r   r  r  r   r  s   0r   <module>r     s   &  	   
 & 1  !%"       "    + +    	wwrwwx01	"'',,tY
'( #Ajjl  "G#
*:fsCj) *
	Jw TU 	SJw 45 S ,.XY ->?QVV? ggll277#5#5c#:<OP      C > CEgh 77d?;<N #   7  "#  ? ! & # ' %/ "!)  ! !"  %< "#:   AJ '( $%& "&' #$% !  .11   6M 6Mrx xv	L6 Ld (( 88	8!$Y'x %  F;5 ;  4 ((2 F$DA0od 
0"00 0&0$%
h;VVKr zF o7  %2::t$G%*# #2 @s#   K  K!K.KK!K+