
    g&                         d Z ddlZddlZddlZddlZddlZddlm	Z	 ddl
mZmZmZ  G d d      ZddZ G d d	      Z	 	 	 	 dd
Zy)zGImplements all the functions to read a video or a picture using ffmpeg.    N)FFMPEG_BINARY)convert_to_secondscross_platform_popen_paramsffmpeg_escape_filenamec                   h    e Zd ZdZ	 	 	 	 	 	 	 	 ddZddZddZd Zd Ze	d        Z
d	 Zdd
Zd Zy)FFMPEG_VideoReaderz/Class for video byte-level reading with ffmpeg.Nc
                    || _         d | _        t        |||	||      }
|
j                  dd      | _        |
j                  dd      | _        t        |
j                  dd            | _        | j                  dv r#| j
                  d	   | j
                  d   g| _        |rqd |v rfd	}t        |      D ]  \  }}|s	|| j
                  |   z  } t        | j
                  d   |z        t        | j
                  d	   |z        f| _        n|| _        || _
        |
j                  d
d      | _        |
j                  dd      | _        |
j                  dd      | _        |
j                  dd      | _        |
| _        || _        |d   dk(  rdnd| _        |$| j
                  \  }}| j"                  |z  |z  dz   }|| _        | j'                          y )N)check_duration
fps_sourcedecode_fileprint_infos	video_fps      ?
video_size)   r   video_rotationr   )Z   i  r   video_duration        durationvideo_n_framesvideo_bitratea      d   )filenameprocffmpeg_parse_infosgetfpssizeabsrotation	enumerateintresize_algor   ffmpeg_durationn_framesbitrateinfospixel_formatdepthbufsize
initialize)selfr   r   r   r/   r-   r
   target_resolutionr(   r   r,   ratioidxtargetwhs                   g/var/www/it7/html/youtubeDownloader/venv/lib/python3.12/site-packages/moviepy/video/io/ffmpeg_reader.py__init__zFFMPEG_VideoReader.__init__   s    !	")!##
 99[#.IIlF3	 EII&6:;==I%1tyy|4DI((#,->#? 8KC &3 78 !1!56DIIaL5<P8QR	-	&		"2C8$yyS9		"2A6yy!4
(&r*c1Qq
 ?99DAqjj1nq(3.G    c                 B   | j                  d       |dk7  r1t        d|      }dd||z
  z  dt        | j                        dd|z  g}ndt        | j                        g}| j                  dk(  r4| j
                  j                  d	      }|d
k(  rddg|z   }n|dk(  rddg|z   }t        | j
                         t        g|z   ddddddt        | j                        z  d| j                  d| j                  dddgz   }t        dj                  |             t        | j                  t         j"                  t         j"                  t         j$                  d      }t!        j&                  |fi || _        | j+                  |      | _        | j/                         | _        y)z
        Opens the file, creates the pipe.

        Sets self.pos to the appropriate value (1 if start_time == 0 because
        it pre-reads the first frame).
        F)delete_lastreadr   r   z-ssz%.06f-ir   video_codec_namevp9z-c:vz
libvpx-vp9vp8libvpxz	-loglevelerror-f
image2pipez-vfzscale=%d:%dz
-sws_flagsz-pix_fmtz-vcodecrawvideo- r/   stdoutstderrstdinN)closeminr   r   r.   r,   r!   printr   tupler#   r(   r-   joinr   r/   spPIPEDEVNULLPopenr   get_frame_numberpos
read_frame	last_read)r1   
start_timeoffseti_arg
codec_namecmdpopen_paramss          r8   r0   zFFMPEG_VideoReader.initializeS   s    	

5
)?J'F:./&t}}5& E 1$--@AE ::?(:;JU".6u$*U2djj O dii 00  !! 	( 	chhsm2<<''''	
 HHS1L1	
 ((4*r:   c                     | j                   \  }}t        |      D ]7  }| j                  j                  j	                  | j
                  |z  |z         9 | xj                  |z  c_        y)zReads and throws away n framesN)r#   ranger   rI   readr.   rV   )r1   nr6   r7   is        r8   skip_frameszFFMPEG_VideoReader.skip_frames   sV    yy1q 	6AII!!$**q.1"45	6 	Ar:   c           
         | j                   \  }}| j                  |z  |z  }| j                  j                  j	                  |      }t        |      |k7  rt        j                  d| j                  |t        |      | j                  | j                  d| j                  z  | j                  z  | j                  fz  t               t        | d      st        d| j                   d      | j                   }n_t        t"        d      rt#        j$                  |d      }nt#        j&                  |d      }||t        |      ||z  z  f|_        || _        | xj                  d	z  c_	        |S )
z
        Reads the next frame from the file.
        Note that upon (re)initialization, the first frame will already have been read
        and stored in ``self.last_read``.
        zIn file %s, %d bytes wanted but %d bytes read at frame index %d (out of a total %d frames), at time %.02f/%.02f sec. Using the last valid frame instead.r   rX   z<MoviePy error: failed to read the first frame of video file z. That might mean that the file is corrupted. That may also mean that you are using a deprecated version of FFMPEG. On Ubuntu/Debian for instance the version in the repos is deprecated. Please update to a recent version from the website.
frombufferuint8)dtyper   )r#   r.   r   rI   ra   lenwarningswarnr   rV   r*   r"   r   UserWarninghasattrIOErrorrX   nprf   
fromstringshape)r1   r6   r7   nbytessresults         r8   rW   zFFMPEG_VideoReader.read_frame   sE    yy1a!#II!!&)q6VMM;
 MMFHHMM$((NTXX-MM " 4-&&*mm_ 5NN	 	 ^^F r<(q8q8q#a&QU"34FL#DN 	Ar:   c                    | j                  |      dz   }| j                  s(t        d       | j                  |       | j                  S || j
                  k(  r| j                  S || j
                  k  s|| j
                  dz   kD  r| j                  |       | j                  S | j                  || j
                  z
  dz
         | j                         }|S )a5  Read a file video frame at time t.

        Note for coders: getting an arbitrary frame in the video with
        ffmpeg can be painfully slow if some decoding has to be done.
        This function tries to avoid fetching arbitrary frames
        whenever possible, by moving between adjacent frames.
        r   zProc not detectedr   )rU   r   rN   r0   rX   rV   rd   rW   )r1   trV   rt   s       r8   	get_framezFFMPEG_VideoReader.get_frame   s     ##A&* yy%&OOA>>!$((?>>!DHHn#3"6OOA>>! S488^a/0__&FMr:   c                     | j                   S )zGAlias of `self.last_read` for backwards compatibility with MoviePy 1.x.)rX   r1   s    r8   lastreadzFFMPEG_VideoReader.lastread   s     ~~r:   c                 8    t        | j                  |z  dz         S )z6Helper method to return the frame number at time ``t``gh㈵>)r'   r"   )r1   rv   s     r8   rU   z#FFMPEG_VideoReader.get_frame_number  s     488a<')**r:   c                 z   | j                   r| j                   j                         || j                   j                          | j                   j                  j	                          | j                   j
                  j	                          | j                   j                          d| _         |rt        | d      r| `yyy)z<Closes the reader terminating the process, if is still open.NrX   )	r   poll	terminaterI   rL   rJ   waitrm   rX   )r1   r<   s     r8   rL   zFFMPEG_VideoReader.close	  s    99yy~~'		##%		  &&(		  &&(		 DIwt[9  :?r:   c                 $    | j                          y N)rL   ry   s    r8   __del__zFFMPEG_VideoReader.__del__  s    

r:   )TFNrgb24TNbicubicr"   )r   )r   )T)__name__
__module____qualname____doc__r9   r0   rd   rW   rw   propertyrz   rU   rL   r    r:   r8   r   r      s_    9
 <|H+T6p<  +
r:   r   c                 L    |s|rdnd}t        | |d      }|j                  }~|S )a  Read an image file (PNG, BMP, JPEG...).

    Wraps FFMPEG_Videoreader to read just one image.
    Returns an ImageClip.

    This function is not meant to be used directly in MoviePy.
    Use ImageClip instead to make clips out of image files.

    Parameters
    ----------

    filename
      Name of the image file. Can be of any format supported by ffmpeg.

    with_mask
      If the image has a transparency layer, ``with_mask=true`` will save
      this layer as the mask of the returned ImageClip

    pixel_format
      Optional: Pixel format for the image to read. If is not specified
      'rgb24' will be used as the default format unless ``with_mask`` is set
      as ``True``, then 'rgba' will be used.

    rgbar   F)r-   r
   )r   rX   )r   	with_maskr-   readerims        r8   ffmpeg_read_imager     s6    2 !*v|EF 
		BIr:   c                   Z    e Zd ZdZ	 	 	 ddZd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zy)FFmpegInfosParsera.  Finite state ffmpeg `-i` command option file information parser.
    Is designed to parse the output fast, in one loop. Iterates line by
    line of the `ffmpeg -i <filename> [-f null -]` command output changing
    the internal state of the parser.

    Parameters
    ----------

    filename
      Name of the file parsed, only used to raise accurate error messages.

    infos
      Information returned by FFmpeg.

    fps_source
      Indicates what source data will be preferably used to retrieve fps data.

    check_duration
      Enable or disable the parsing of the duration of the file. Useful to
      skip the duration check, for example, for images.

    decode_file
      Indicates if the whole file has been decoded. The duration parsing strategy
      will differ depending on this argument.
    c                 r    || _         || _        || _        || _        |rdnd| _        | j                          y )Ntime=
Duration: )r,   r   r
   r   duration_tag_separator_reset_state)r1   r,   r   r   r
   r   s         r8   r9   zFFmpegInfosParser.__init__W  s9     
 ,$1<g,#r:   c                     d| _         d| _        d| _        dg i| _        d| _        d| _        ddi g d| _        d| _        y)zReinitializes the state of the parser. Used internally at
        initialization and at the end of the parsing process.
        FstreamsN)video_foundaudio_foundmetadatainputs)_inside_file_metadata_inside_output_default_stream_found_current_input_file_current_stream_current_chapterrt   _last_metadata_field_addedry   s    r8   r   zFFmpegInfosParser._reset_stateg  s_     &+" $ &+" %.r? # $ ! 	
 +/'r:   c                    g }| j                   j                         dd D ]#  }| j                  dk(  r/| j                  r#d|v r| j	                  |      | j
                  d<   B| j                  s|d   dk7  r%| j                  dk(  sf| j                  rsd| _        {| j                  s|j                  d      rd| _        |j                  d	      rd
| _        | j                  r-| j                  dk(  r| j	                  |      | j
                  d<   t        j                  d|      }|rt        |j                  d            nd| j
                  d<   t        j                  d|      }|rt        |j                  d            nd| j
                  d<   u| j                  rY| j                  |      \  }}|dk(  r%| j                  }| j
                  d   |   dz   |z   }n|| _        || j
                  d   |<   |j!                         j                  d      r| j"                  r(| j$                  d   j'                  | j"                         t        j                  d|j!                               }|j)                         \  }}	}
}t        |      }t        |	      }	|j+                         }|
dk(  rd}
||	||
| j,                   xs |j/                  d      d| _        d| _        | j"                  d   r&|| j
                  d| d<   |	| j
                  d| d<   | j0                  r%||   j'                  | j0                         d| _        d| j$                  vr|| j$                  d<   nf| j$                  d   |k7  rTt3        |      |dz   k\  r||   | j$                  d<   | j
                  d   j'                  | j$                         d|i| _        	 | j5                  ||      \  }}| j
                  j7                  |       | j"                  j7                  |       |j                  d!      r| j"                  rd| j"                  vri | j"                  d<   | j                  |      \  }}| j"                  d"   d#k(  r)| jC                  ||      \  }}|d$k(  r|| j
                  d%<   |dk(  r%| j                  }| j"                  d   |   dz   |z   }n|| _        || j"                  d   |<   |j                  d&      r| j0                  rZt3        |      | j0                  d   dz   k  r|j'                  g        || j0                  d      j'                  | j0                         t        j                  d'|      }|j)                         \  }}}}t        |      t        |      t        |      t        |      d(| _        | j0                  sd| j0                  vri | j0                  d<   | j                  |      \  }}|dk(  r%| j                  }| j0                  d   |   dz   |z   }n|| _        || j0                  d   |<   & | j$                  r| j$                  d   j'                  | j"                         d| j$                  v r=t3        |      | j$                  d   dz   k(  r|| j$                  d      | j$                  d<   | j
                  d   j'                  | j$                         | j
                  d)   rk| j                  r_| j
                  d   | j
                  d*<   t        | j
                  d   | j
                  jE                  d+d      z        | j
                  d,<   nd| j
                  d,<   d-| j
                  d*<   | j
                  d.   r| j
                  jE                  d/      sld| j
                  d/<   | j
                  d   D ]K  }|d   D ]0  }|d"   d0k(  s|jE                  d      s|d   | j
                  d/<    n | j
                  d/   K n | j
                  }| jG                          |S # t8        $ r=}t;        j<                  t?        |       d | j                    t@               Y d}~[d}~ww xY w)1zParses the information returned by FFmpeg in stderr executing their binary
        for a file with ``-i`` option and returns a dictionary with all data needed
        by MoviePy.
        r   Nr   r   r   rG   Tz  Metadata:z  Duration:Fr   zbitrate: (\d+) kb/sr+   zstart: (\d+\.?\d+)start r   
zStream r   z6^Stream\s#(\d+):(\d+)(?:\[\w+\])?\(?(\w+)?\)?:\s(\w+):undz	(default))input_numberstream_numberstream_typelanguagedefaultr   default__input_number_stream_numberr   chaptersr   z
ffmpeg output:

z    Metadata:r   videorotater   z    Chapterz?^    Chapter #(\d+):(\d+): start (\d+\.?\d+?), end (\d+\.?\d+?))r   chapter_numberr   endr   r   r   r   r   r   audio_bitrateaudio)$r,   
splitlinesr   r
   parse_durationrt   r   r   
startswithresearchr'   groupfloatparse_metadata_field_valuer   lstripr   r   appendgroupslowerr   endswithr   ri   parse_data_by_stream_typeupdateNotImplementedErrorrj   rk   strrl   video_metadata_type_castingr!   r   )r1   input_chapterslinebitrate_matchstart_matchfieldvaluemain_info_matchr   r   r   r   stream_type_lowerglobal_datastream_dataexcchapter_data_matchr   r   r   streams_inputstreamrt   s                          r8   parsezFFmpegInfosParser.parse  sE    JJ))+AB/ s	AD++w6''tO +/*=*=d*CJ'$$Q3..'9$BUBU*.D'//DOOM4R-1*/-2*&&4+F+F,+V.2.A.A$.GDKK
+ !#		*@$ G3@C++A./d I&
 !ii(=tD3>E+++A./D G$ ++#>>tDu B; ;;E KK
3E:TAEIE6;D316J'.)))4'',,Y7>>t?S?ST #%))MKKM# $**, !"<0 #M 2$/$5$5$7!u$#H %1%2#4 (#'#=#==  2}}[1($ .2* ''	2 % KK"#4"5]C
 & KK"#4"5^D
 (("<0778M8MN,0D)!)A)AA?KD,,^<--n=M >*lQ.>>?M(@00<
 KK)001I1IJ0>/MD,
=/3/M/M#T0,K KK&&{3((//<1%%T%9%9979D((4#>>tDu''6'A#'#C#CE5#QLE5(8=$45 B; ;;E 00<UCdJURE6;D3:?$$Z07/((>*T-B-B>-RUV-VV&--b1"4#8#8#HIPP--
 &(YYV&" <N;T;T;V8neS %($5&).&9"5\ :	)% &&T%:%::8:D))*5#>>tDu B; ;;E 11*=eDtKeSE6;D3;@%%j1%8gs	Al ##$$Y/66t7K7KL $":"::'4+C+CN+SVW+WW7E,,^<8((4 KK!(()A)AB ;;}%$*=*=,0KK
,CDKK(),/J'$++//+q*II-DKK() -.DKK(),/DKK()
 ;;}%dkkooo.N+/DKK(!%X!6 +I6 Fm,7FJJy<Q7=i7HO4
 ;;/;  	] + MMs8*$8E{ s   `::	b 2a;;b c                     	  | j                   | j                  d d|   |      S # t        $ r t        | d      w xY w)z1Parses data from "Stream ... {stream_type}" line.c                 
    i i fS r   r   )_lines    r8   <lambda>z=FFmpegInfosParser.parse_data_by_stream_type.<locals>.<lambda>z  s
    r2h r:   )AudioVideoDataz? stream parsing is not supported by moviepy and will be ignored)parse_audio_stream_dataparse_video_stream_dataKeyErrorr   )r1   r   r   s      r8   r   z+FFmpegInfosParser.parse_data_by_stream_typet  sl    
	5555. 	  	! !
  	%-  # # 	s   #& >c                 Z   ddii }}	 t        t        j                  d|      j                  d            |d<   t        j                  d|      }|rt        |j                  d            nd|d	<   | j                  d
   r|d   |d<   |d	   |d<   ||fS # t        t
        f$ r d|d<   Y pw xY w)z)Parses data from "Stream ... Audio" line.r   Tz	 (\d+) Hzr   r"   unknown
(\d+) kb/sNr+   r   	audio_fpsr   )r'   r   r   r   AttributeError
ValueErrorr   )r1   r   r   r   match_audio_bitrates        r8   r   z)FFmpegInfosParser.parse_audio_stream_data  s    %2D$92[	+!$RYY|T%B%H%H%K!LK
 !iit<1DC#))!,-$ 	I 	*'25'9K$+6y+AK([)) 
+ 	+ "+K	+s   1B B*)B*c                    ddii }}	 t        j                  d|      }|r*|j                         D cg c]  }t        |       c}|d<   t        j                  d|      }|rt        |j                  d            nd	|d
<   | j                  dk(  r	 | j                  |      }nH| j                  dk(  r	 | j                  |      }n&t        d| j                  d| j                  d      d}dD ]"  }	||	k7  s	t        ||	|z  z
        dk  s|	|z  }$ ||d<   t        j                  d|j                               }
|
|
j                         \  }}||d<   ||d<   | j                   d   sd| j"                  vr|j%                  dd	      |d<   | j                   d   sd| j"                  vr|j%                  dd	      |d<   | j                   d   sd| j"                  vr|j%                  dd	      |d<   | j                   d   sd| j"                  vr|j%                  d
d	      |d<   | j                   d   sd| j"                  vr|d   |d<   ||fS c c}w # t        $ r& t        d| j                  d| j                        w xY w# t        t        f$ r | j                  |      }Y w xY w# t        t        f$ r | j                  |      }Y w xY w)z)Parses data from "Stream ... Video" line.r   Tz (\d+)x(\d+)[,\s]r#   z8MoviePy error: failed to read video dimensions in file 'z/'.
Here are the file infos returned byffmpeg:

r   r   Nr+   r"   tbrzfps source 'z#' not supported parsing the video ''g	.l?)            2   g{Gz?zVideo:\s(\w+)?\s?(\([^)]+\))?r\   profiler   r>   video_profiler   r   r   )r   r   r   r'   	Exceptionrn   r   r,   r   r   	parse_fpsr   r   	parse_tbrr$   r   r   rt   r!   )r1   r   r   r   match_video_sizenummatch_bitrater"   coefxr   r\   r   s                r8   r   z)FFmpegInfosParser.parse_video_stream_data  s   %2D$92[	!yy)=tD;K;R;R;T&UCs3x&UF# 		-6@M]%8%8%;!<SWI ??e#+nnT* __%+nnT* ??DMM3  % 	Aqc#D.1D8$h	 !E )),KKM
 &$3$:$:$<!Z(2K%%,K	"	*.@.S.9oolD.QK*+	*oT[[.P+6??9d+KK(	*l$++.M(3(EK%	*oT[[.P+6??9d+KK(	*k.L'25'9K$[))K 'V 	 ==$**. 	0 #J/ +nnT*+
 #J/ +nnT*+s@   *I II J 3J+ I /J J('J(+ KKc                 ^    t        t        j                  d|      j                  d            S )zEParses number of FPS from a line of the ``ffmpeg -i`` command output.z (\d+.?\d*) fpsr   )r   r   r   r   )r1   r   s     r8   r   zFFmpegInfosParser.parse_fps  s$    RYY148>>qABBr:   c                     t        j                  d|      j                  d      }|d   dk(  rt        |dd       dz  }|S t        |      }|S )zEParses number of TBS from a line of the ``ffmpeg -i`` command output.z (\d+.?\d*k?) tbrr   r   kNi  )r   r   r   r   )r1   r   s_tbrr   s       r8   r   zFFmpegInfosParser.parse_tbr  sX    		.5;;A> 9cr
#d*C 
 ,C
r:   c                    	 |j                  | j                        d   }t        j                  d|      }t	        |j                  d            S # t        $ r& t        d| j                  d| j                        w xY w)z]Parse the duration from the line that outputs the duration of
        the container.
        r   z-([0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9])r   z4MoviePy error: failed to read the duration of file 'z0'.
Here are the file infos returned by ffmpeg:

)
splitr   r   r   r   r   r   rn   r   r,   )r1   r   time_raw_stringmatch_durations       r8   r   z FFmpegInfosParser.parse_duration  s|    	"jj)D)DEbIOYY@N &n&:&:1&=>> 	
 ==$**	. 	s   AA /A?c                 p    |j                  dd      \  }}|j                  d      |j                  d      fS )zjReturns a tuple with a metadata field-value pair given a ffmpeg `-i`
        command output line.
        :r   rG   )r  strip)r1   r   	raw_field	raw_values       r8   r   z,FFmpegInfosParser.parse_metadata_field_value  s6      $zz#q1	9$iooc&:;;r:   c                 .    |dk(  r|t        |      fS ||fS )zFCast needed video metadata fields to other types than the default str.r   )r   )r1   r   r   s      r8   r   z-FFmpegInfosParser.video_metadata_type_casting  s#    H5<((u~r:   N)r"   TF)r   r   r   r   r9   r   r   r   r   r   r   r   r   r   r   r   r:   r8   r   r   <  sO    <  "/HgR*$M*^C	(<r:   r   c                    t         ddt        |       g}|r|j                  g d       t        dt        j
                  t        j
                  t        j                  d      }t	        j                  |fi |}|j                         \  }}	|	j                  dd      }
|j                          ~|rt        |
       	 t        |
| |||	      j                         S # t        $ rp}t        j                   j#                  |       rt%        d
|  d      t        j                   j'                  |       st)        d
|  d      t+        d|
       |d}~ww xY w)a  Get the information of a file using ffmpeg.

    Returns a dictionary with next fields:

    - ``"duration"``
    - ``"metadata"``
    - ``"inputs"``
    - ``"video_found"``
    - ``"video_fps"``
    - ``"video_n_frames"``
    - ``"video_duration"``
    - ``"video_bitrate"``
    - ``"video_metadata"``
    - ``"audio_found"``
    - ``"audio_fps"``
    - ``"audio_bitrate"``
    - ``"audio_metadata"``
    - ``"video_codec_name"``
    - ``"video_profile"``

    Note that "video_duration" is slightly smaller than "duration" to avoid
    fetching the incomplete frames at the end, which raises an error.

    Parameters
    ----------

    filename
      Name of the file parsed, only used to raise accurate error messages.

    infos
      Information returned by FFmpeg.

    fps_source
      Indicates what source data will be preferably used to retrieve fps data.

    check_duration
      Enable or disable the parsing of the duration of the file. Useful to
      skip the duration check, for example, for images.

    decode_file
      Indicates if the whole file must be read to retrieve their duration.
      This is needed for some files in order to get the correct duration (see
      https://github.com/Zulko/moviepy/pull/1222).
    z-hide_bannerr=   )rC   nullrF   i rH   utf8ignore)errors)r   r
   r   r   z' is a directoryz' not foundz+Error passing `ffmpeg -i` command output:

N)r   r   extendr   rQ   rR   rS   rT   communicatedecoder~   rN   r   r   r   ospathisdirIsADirectoryErrorexistsFileNotFoundErrorrn   )r   r
   r   r   r   r]   r^   r   outputrB   r,   r   s               r8   r    r      s>   h .$0Fx0P
QC

&'.ggggZZ		
L 88C(<(D&&(OVULLL1ENNeX !)#
 %'	  X77=="#az1A$BCC)#az$=>>EeWMNTWWXs   >C 	E%A+EE)TN)Tr"   FF)r   r  r   
subprocessrQ   rj   numpyro   moviepy.configr   moviepy.toolsr   r   r   r   r   r   r    r   r:   r8   <module>r     sY    M 	 	    ( D DN FX Xz YXr:   