
    W|hb                         S r SSKrSSKJr  SSKJr  SSKJr  SSK	J
r
Jr  SSKrSSKr\
(       a  SSKJr  SSKJrJrJrJrJrJr   " S	 S
5      rg)zImplements the central object of MoviePy, the Clip, and all the methods that
are common to the two subclasses of Clip, VideoClip and AudioClip.
    N)reduce)Real)add)TYPE_CHECKINGList)Effect)apply_to_audioapply_to_maskconvert_parameter_to_secondsoutplacerequires_durationuse_clip_fps_by_defaultc                   P   \ rS rSrSrSrS rS r\" S/5      S 5       r	S)S	 jr
S*S
 jrS\S   4S jr\\\" S/5      \S+S j5       5       5       5       r\\\" S/5      \S 5       5       5       5       r\\\" S/5      \S+S j5       5       5       5       r\S 5       rS,S jr\S 5       r\S 5       r\" SS/5      \\S-S j5       5       5       r\" SS/5      S 5       rS.S\S\4S jjrS.S\4S jjr\\S/S j5       5       r\" S/5      S 5       r S  r!S! r"S" r#S# r$S$ r%S% r&S& r'S' r(S(r)g)0Clip   a  Base class of all clips (VideoClips and AudioClips).

Attributes
----------

start : float
  When the clip is included in a composition, time of the
  composition at which the clip starts playing (in seconds).

end : float
  When the clip is included in a composition, time of the
  composition at which the clip stops playing (in seconds).

duration : float
  Duration of the clip (in seconds). Some clips are infinite, in
  this case their duration will be ``None``.
	TEMP_MPY_c                 X    SU l         S U l        S U l        SU l        S U l        S U l        g )Nr   F)startenddurationmemoize
memoized_tmemoized_frameselfs    F/home/james-whalen/.local/lib/python3.13/site-packages/moviepy/Clip.py__init__Clip.__init__5   s-    
"    c                 .    [         R                  " U 5      $ )zGAllows the usage of ``.copy()`` in clips as chained methods invocation.)_copycopyr   s    r   r"   	Clip.copy>   s    zz$r   tc                     U R                   (       a:  XR                  :X  a  U R                  $ U R                  U5      nXl        X l        U$ U R                  U5      $ )zGets a numpy array representing the RGB picture of the clip,
or (mono or stereo) value for a sound clip, at time ``t``.

Parameters
----------

t : float or tuple or str
  Moment of the clip whose frame will be returned.
)r   r   r   frame_function)r   r$   frames      r   	get_frameClip.get_frameB   sR     <<OO#***++A."#&+#&&q))r   Nc                   ^ ^ Uc  / nT R                  UU 4S j5      nU(       d  SUl        SUl        [        U[        5      (       a  U/nU H0  n[        XES5      nUc  M  UR                  TUS9n[        XEU5        M2     U$ )an  General processing of a clip.

Returns a new Clip whose frames are a transformation
(through function ``func``) of the frames of the current clip.

Parameters
----------

func : function
  A function with signature (gf,t -> frame) where ``gf`` will
  represent the current clip's ``get_frame`` method,
  i.e. ``gf`` is a function (t->image). Parameter `t` is a time
  in seconds, `frame` is a picture (=Numpy array) which will be
  returned by the transformed clip (see examples below).

apply_to : {"mask", "audio", ["mask", "audio"]}, optional
  Can be either ``'mask'``, or ``'audio'``, or
  ``['mask','audio']``.
  Specifies if the filter should also be applied to the
  audio or the mask of the clip, if any.

keep_duration : bool, optional
  Set to True if the transformation does not change the
  ``duration`` of the clip.

Examples
--------

In the following ``new_clip`` a 100 pixels-high clip whose video
content scrolls from the top to the bottom of the frames of
``clip`` at 50 pixels per second.

>>> filter = lambda get_frame,t : get_frame(t)[int(t):int(t)+50, :]
>>> new_clip = clip.transform(filter, apply_to='mask')

Nc                 *   > T" TR                   U 5      $ N)r(   )r$   funcr   s    r   <lambda> Clip.transform.<locals>.<lambda>   s    d4>>ST>Ur   keep_duration)with_updated_frame_functionr   r   
isinstancestrgetattr	transformsetattr)r   r-   apply_tor1   new_clip	attributeattribute_valuenew_attribute_values   ``      r   r6   Clip.transformY   s    J H 334UV $HHLh$$ zH!I%h4@O*&5&?&? '@ '# -@A " r   c                 8   ^ Uc  / nU R                  U4S jUUS9$ )aT  
Returns a Clip instance playing the content of the current clip
but with a modified timeline, time ``t`` being replaced by the return
of `time_func(t)`.

Parameters
----------

time_func : function
  A function ``t -> new_t``.

apply_to : {"mask", "audio", ["mask", "audio"]}, optional
  Can be either 'mask', or 'audio', or ['mask','audio'].
  Specifies if the filter ``transform`` should also be applied to the
  audio or the mask of the clip, if any.

keep_duration : bool, optional
  ``False`` (default) if the transformation modifies the
  ``duration`` of the clip.

Examples
--------

.. code:: python

    # plays the clip (and its mask and sound) twice faster
    new_clip = clip.time_transform(lambda t: 2*t, apply_to=['mask', 'audio'])

    # plays the clip starting at t=3, and backwards:
    new_clip = clip.time_transform(lambda t: 3-t)

c                     > U " T" U5      5      $ r,    )r(   r$   	time_funcs     r   r.   %Clip.time_transform.<locals>.<lambda>   s    9Q<!8r   r0   )r6   )r   rA   r8   r1   s    `  r   time_transformClip.time_transform   s0    B H~~8'  
 	
r   effectsr   c                 z    U R                  5       nU H$  nUR                  5       nUR                  U5      nM&     U$ )zReturn a copy of the current clip with the effects applied

>>> new_clip = clip.with_effects([vfx.Resize(0.2, method="bilinear")])

You can also pass multiple effect as a list

>>> clip.with_effects([afx.VolumeX(0.5), vfx.Resize(0.3), vfx.Mirrorx()])
)r"   apply)r   rE   r9   effecteffect_copys        r   with_effectsClip.with_effects   s=     99;F !++-K"((2H	  r   c                     Xl         U R                  b  U(       a  XR                  -   U l        gU R                  b  U R                  U R                   -
  U l        gg)aR  Returns a copy of the clip, with the ``start`` attribute set
to ``t``, which can be expressed in seconds (15.35), in (min, sec),
in (hour, min, sec), or as a string: '01:03:05.35'.

These changes are also applied to the ``audio`` and ``mask``
clips of the current clip, if they exist.

note::
  The start and end attribute of a clip define when a clip will start
  playing when used in a composite video clip, not the start time of
  the clip itself.

  i.e: with_start(10) mean the clip will still start at his first frame,
  but if used in a composite video clip it will only start to show at
  10 seconds.

Parameters
----------

t : float or tuple or str
  New ``start`` attribute value for the clip.

change_end : bool optional
  Indicates if the ``end`` attribute value must be changed accordingly,
  if possible. If ``change_end=True`` and the clip has a ``duration``
  attribute, the ``end`` attribute of the clip will be updated to
  ``start + duration``. If ``change_end=False`` and the clip has a
  ``end`` attribute, the ``duration`` attribute of the clip will be
  updated to ``end - start``.
N)r   r   r   )r   r$   
change_ends      r   
with_startClip.with_start   sG    F 
MM%:==(DHXX! HHtzz1DM "r   c                     Xl         U R                   c  gU R                  c,  U R                  b  [        SXR                  -
  5      U l        ggU R                   U R                  -
  U l        g)a  Returns a copy of the clip, with the ``end`` attribute set to ``t``,
which can be expressed in seconds (15.35), in (min, sec), in
(hour, min, sec), or as a string: '01:03:05.35'. Also sets the duration
of the mask and audio, if any, of the returned clip.

note::
  The start and end attribute of a clip define when a clip will start
  playing when used in a composite video clip, not the start time of
  the clip itself.

  i.e: with_start(10) mean the clip will still start at his first frame,
  but if used in a composite video clip it will only start to show at
  10 seconds.

Parameters
----------

t : float or tuple or str
  New ``end`` attribute value for the clip.
Nr   )r   r   r   max)r   r$   s     r   with_endClip.with_end   sZ    2 88::}}( A$56
 ) !HHtzz1DMr   r   c                     Xl         U(       a  Uc  SOU R                  U-   U l        gU R                   c  [        S5      eU R                  U-
  U l        g)a  Returns a copy of the clip, with the  ``duration`` attribute set to
``t``, which can be expressed in seconds (15.35), in (min, sec), in
(hour, min, sec), or as a string: '01:03:05.35'. Also sets the duration
of the mask and audio, if any, of the returned clip.

If ``change_end is False``, the start attribute of the clip will be
modified in function of the duration and the preset end of the clip.

Parameters
----------

duration : float
  New duration attribute value for the clip.

change_end : bool, optional
  If ``True``, the ``end`` attribute value of the clip will be adjusted
  accordingly to the new duration using ``clip.start + duration``.
Nz2Cannot change clip start when new duration is None)r   r   r   
ValueError)r   r   rM   s      r   with_durationClip.with_duration  sI    . ! ( 0t

X8MDH}}$ !UVVH,DJr   c                     Xl         g)zSets a ``frame_function`` attribute for the clip. Useful for setting
arbitrary/complicated videoclips.

Parameters
----------

frame_function : function
  New frame creator function for the clip.
N)r&   )r   r&   s     r   r2    Clip.with_updated_frame_function<  s
     -r   c                     U(       a+  SSK Jn  U R                  U" XR                  -  5      /5      nOU R	                  5       nXl        U$ )a  Returns a copy of the clip with a new default fps for functions like
write_videofile, iterframe, etc.

Parameters
----------

fps : int
  New ``fps`` attribute value for the clip.

change_duration : bool, optional
  If ``change_duration=True``, then the video speed will change to
  match the new fps (conserving all frames 1:1). For example, if the
  fps is halved in this mode, the duration will be doubled.
r   MultiplySpeed)moviepy.video.fx.MultiplySpeedr\   rJ   fpsr"   )r   r^   change_durationr\   newclips        r   with_fpsClip.with_fpsI  s=     D''sXX~)F(GHGiikGr   c                     Xl         g)zSays whether the clip is a mask or not.

Parameters
----------

is_mask : bool
  New ``is_mask`` attribute value for the clip.
N)is_mask)r   rd   s     r   with_is_maskClip.with_is_maskb  	     r   c                     Xl         g)zSets whether the clip should keep the last frame read in memory.

Parameters
----------

memoize : bool
  Indicates if the clip should keep the last frame read in memory.
N)r   )r   r   s     r   with_memoizeClip.with_memoizen  rg   r   
start_timeend_timec                 b  ^ TS:  a  U R                   T-   mU R                   b1  TU R                   :  a!  [        ST-  S-   SU R                   -  -   5      eU R                  U4S j/ S9nUc  U R                   b  U R                   nO>Ub;  US:  a5  U R                   c  [        S[        TU45      -  5      eU R                   U-   nUbh  U R                   b3  X R                   -
  S:  a!  [        S	U-  S
-   SU R                   -  -   5      eUT-
  Ul         UR                  UR                   -   Ul        U$ )aZ  Returns a clip playing the content of the current clip between times
``start_time`` and ``end_time``, which can be expressed in seconds
(15.35), in (min, sec), in (hour, min, sec), or as a string:
'01:03:05.35'.

The ``mask`` and ``audio`` of the resulting subclip will be subclips of
``mask`` and ``audio`` the original clip, if they exist.

It's equivalent to slice the clip as a sequence, like
``clip[t_start:t_end]``.

Parameters
----------

start_time : float or tuple or str, optional
  Moment that will be chosen as the beginning of the produced clip. If
  is negative, it is reset to ``clip.duration + start_time``.

end_time : float or tuple or str, optional
  Moment that will be chosen as the end of the produced clip. If not
  provided, it is assumed to be the duration of the clip (potentially
  infinite). If is negative, it is reset to ``clip.duration + end_time``.
  For instance:

  >>> # cut the last two seconds of the clip:
  >>> new_clip = clip.subclipped(0, -2)

  If ``end_time`` is provided or if the clip has a duration attribute,
  the duration of the returned clip is set automatically.
r   zstart_time (%.02f) z"should be smaller than the clip's zduration (%.02f).c                    > U T-   $ r,   r@   )r$   rk   s    r   r.   !Clip.subclipped.<locals>.<lambda>  s	    Zr   r8   zZSubclip with negative times (here %s) can only be extracted from clips with a ``duration``g:0yE>zend_time (%.02f) z)should be smaller or equal to the clip's )r   rU   rC   r4   r   r   r   rk   rl   r9   s    `  r   
subclippedClip.subclippedz  sT   D > 3JMM%J$--,G%
267%56  &&'?"&M4==#<}}H"A}}$ P J12	4   ==83)==0H:0U '(2AB)DMM9:  !): 5H#>>H,=,==HLr   c                    ^^ U R                  UU4S jSS/S9nU R                  b!  UR                  U R                  TT-
  -
  5      $ U$ )a  
Returns a clip playing the content of the current clip but
skips the extract between ``start_time`` and ``end_time``, which can be
expressed in seconds (15.35), in (min, sec), in (hour, min, sec),
or as a string: '01:03:05.35'.

If the original clip has a ``duration`` attribute set,
the duration of the returned clip  is automatically computed as
`` duration - (end_time - start_time)``.

The resulting clip's ``audio`` and ``mask`` will also be cutout
if they exist.

Parameters
----------

start_time : float or tuple or str
  Moment from which frames will be ignored in the resulting output.

end_time : float or tuple or str
  Moment until which frames will be ignored in the resulting output.
c                    > X T:  TT-
  -  -   $ r,   r@   )r$   rl   rk   s    r   r.   +Clip.with_section_cut_out.<locals>.<lambda>  s    a
?x*/DEEr   audiomaskrp   )rC   r   rV   rq   s    `` r   with_section_cut_outClip.with_section_cut_out  sU    0 &&Ev& ' 

 ==$))$--8j;P*QRROr   factorfinal_durationc                 :    SSK Jn  U R                  U" XS9/5      $ )zReturns a clip playing the current clip but at a speed multiplied
by ``factor``. For info on the parameters, please see ``vfx.MultiplySpeed``.
r   r[   )r{   r|   )r]   r\   rJ   )r   r{   r|   r\   s       r   with_speed_scaledClip.with_speed_scaled  s&     	A  &HI
 	
r   c                 <    SSK Jn  U R                  U" XUS9/5      $ )zReturns a new clip with audio volume multiplied by the value `factor`.
For info on the parameters, please see ``afx.MultiplyVolume``
r   )MultiplyVolume)r{   rk   rl   )moviepy.audio.fx.MultiplyVolumer   rJ   )r   r{   rk   rl   r   s        r   with_volume_scaledClip.with_volume_scaled  s(     	C  68TU
 	
r   c           	   #   P  #    [         R                  " U5      nUR                  [        R                  " S[        U R                  U-  5      5      S9 HN  nXQ-  nU R                  U5      nUb!  UR                  U:w  a  UR                  U5      nU(       a  Xg4v   MJ  Uv   MP     g7f)ao  Iterates over all the frames of the clip.

Returns each frame of the clip as a HxWxN Numpy array,
where N=1 for mask clips and N=3 for RGB clips.

This function is not really meant for video editing. It provides an
easy way to do frame-by-frame treatment of a video, for fields like
science, computer vision...

Parameters
----------

fps : int, optional
  Frames per second for clip iteration. Is optional if the clip already
  has a ``fps`` attribute.

with_times : bool, optional
  Ff ``True`` yield tuples of ``(t, frame)`` where ``t`` is the current
  time for the frame, otherwise only a ``frame`` object.

logger : str, optional
  Either ``"bar"`` for progress bar or ``None`` or any Proglog logger.

dtype : type, optional
  Type to cast Numpy array frames. Use ``dtype="uint8"`` when using the
  pictures to write video, images..

Examples
--------


.. code:: python

    # prints the maximum of red that is contained
    # on the first line of each frame of the clip.
    from moviepy import VideoFileClip
    myclip = VideoFileClip('myvideo.mp4')
    print([frame[0,:,0].max()
          for frame in myclip.iter_frames()])
r   )frame_indexN)
proglogdefault_bar_loggeriter_barnparangeintr   r(   dtypeastype)r   r^   
with_timesloggerr   r   r$   r'   s           r   iter_framesClip.iter_frames  s     V ++F3!??		!S)<%=> + 
K
 !ANN1%E!u(<U+h
s   B$B&c                    [        U[        R                  5      (       a}  UR                  5       UR	                  5       p2U R
                  b  X R
                  :  a  gX0R                  :  a  gSXR                  :  -  nU R
                  b  XAU R
                  :*  -  nU$ XR                  :  =(       a#    U R
                  SL =(       d    XR
                  :  $ )ab  If ``t`` is a time, returns true if t is between the start and the end
of the clip. ``t`` can be expressed in seconds (15.35), in (min, sec), in
(hour, min, sec), or as a string: '01:03:05.35'. If ``t`` is a numpy
array, returns False if none of the ``t`` is in the clip, else returns a
vector [b_1, b_2, b_3...] where b_i is true if tti is in the clip.
NF   )r3   r   ndarrayminrQ   r   r   )r   r$   tmintmaxresults        r   
is_playingClip.is_playing9  s     a$$!%%'$$488+;jj  !zz/*Fxx#txx-'M OO488t+;*NXXOr   c                     g)z&Release any resources that are in use.Nr@   r   s    r   close
Clip.closeT  s     	r   c                 F   [        U[        5      (       d  [        $ U R                  U R                  -  nUR                  UR                  -  nX#:w  a  g[        U R                  5       UR                  5       5       H"  u  pE[        R                  " XE5      (       a  M"    g   g)NFT)	r3   r   NotImplementedr   r^   zipr   r   array_equal)r   otherself_lengthother_lengthframe1frame2s         r   __eq__Clip.__eq__`  s    %&&!! mmdhh.~~		1& "$"2"2"4e6G6G6IJNF>>&11 K r   c                     U $ )zP
Support the Context Manager protocol,
to ensure that resources are cleaned up.
r@   r   s    r   	__enter__Clip.__enter__q  s	    
 r   c                 $    U R                  5         g r,   )r   )r   exc_type	exc_value	tracebacks       r   __exit__Clip.__exit__x  s    

r   c                 R  ^ ^^ SS/n[        U[        5      (       a  T R                  UR                  =(       d    SUR                  =(       d    T R
                  5      mUR                  (       aw  [        UR                  5      mTS:w  a6  TR                  U4S jUSS9mTR                  STR
                  -  T-  5      mUR                  S:  a  TR                  UU 4S	 jSUS
9mT$ [        U[        5      (       a  [        [        U 4S jU 5       5      $ T R                  U5      $ )a  
Support extended slice and index operations over
a clip object.

Simple slicing is implemented via `subclip`.
So, ``clip[t_start:t_end]`` is equivalent to
``clip.subclipped(t_start, t_end)``. If ``t_start`` is not
given, default to ``0``, if ``t_end`` is not given,
default to ``self.duration``.

The slice object optionally support a third argument as
a ``speed`` coefficient (that could be negative),
``clip[t_start:t_end:speed]``.

For example ``clip[::-1]`` returns a reversed (a time_mirror fx)
the video and ``clip[:5:2]`` returns the segment from 0 to 5s
accelerated to 2x (ie. resulted duration would be 2.5s)

In addition, a tuple of slices is supported, resulting in the concatenation
of each segment. For example ``clip[(:1, 2:)]`` return a clip
with the segment from 1 to 2s removed.

If ``key`` is not a slice or tuple, we assume it's a time
value (expressed in any format supported by `cvsec`)
and return the frame at that time, passing the key
to ``get_frame``.
rx   rw   r   r   c                    > TU -  $ r,   r@   )r$   r{   s    r   r.   "Clip.__getitem__.<locals>.<lambda>  s	    &1*r   T)r8   r1   g      ?c                 B   > TR                   U -
  STR                  -  -
  $ )Nr   )r   r^   )r$   clipr   s    r   r.   r     s    $--!"3a$((l"Br   )r1   r8   c              3   .   >#    U  H
  nTU   v   M     g 7fr,   r@   ).0kr   s     r   	<genexpr>#Clip.__getitem__.<locals>.<genexpr>  s     5AQs   )r3   slicerr   r   stopr   stepabsrC   rV   tupler   r   r(   )r   keyr8   r   r{   s   `  @@r   __getitem__Clip.__getitem__{  s    8 G$c5!! ??399>3883Lt}}MDxxSXXQ;..,xt / D  --cDMM.AF.JKD88a<..B&*!) / D
 KU###5566>>#&&r   c                     g r,   r@   r   s    r   __del__Clip.__del__  s    
 	r   c                     [         $ r,   )r   )r   r   s     r   __add__Clip.__add__  s    r   c                 t    [        U[        5      (       d  [        $ SSKJn  U R                  U" U5      /5      $ )Nr   )Loop)r3   r   r   moviepy.video.fx.Loopr   rJ   )r   nr   s      r   __mul__Clip.__mul__  s/    !T""!!.  $q'++r   )r   r   r&   rd   r   r   r   r   )NT)NF)T)F)r   N)NN)NFNN)*__name__
__module____qualname____firstlineno____doc___TEMP_FILES_PREFIXr   r"   r   r(   r6   rC   r   rJ   r
   r	   r   rN   rR   rV   r2   ra   re   ri   rr   ry   floatr~   r   r   r   r   r   r   r   r   r   r   r   r   r   __static_attributes__r@   r   r   r   r      s   , %#  "3%(* )*,:x(
TDN $ !3%(#2  )  #2J !3%(2  )  2< !:,/-  0  -8 
- 
-2 	 	 	 	 "<"<=I   >IV "<"<= >B
 
e 

 
 7  7r "3%(P )P4
"7'r,r   r   )r   r"   r!   	functoolsr   numbersr   operatorr   typingr   r   numpyr   r   moviepy.Effectr   moviepy.decoratorsr	   r
   r   r   r   r   r   r@   r   r   <module>r      s?        &   % j
, j
,r   