Ë
    ¼Ó^jÂB  ã                  óž  — 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mZ d dlmZ d dlmZmZmZ d dlmZ d dlZd dlZd dlmZ d dlmZ d d	lmZ  ee«      Ze G d
„ d«      «       Z  G d„ d«      Z!dd„Z"	 d	 	 	 	 	 	 	 	 	 dd„Z#	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 dd„Z$dddddddœ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Z% G d„ d«      Z&y)é    )ÚannotationsN)Údeque)ÚCallableÚ	Generator)Ú	dataclass)ÚEmptyÚFullÚQueue)ÚAny)Útqdm)Ú_get_loggerc                  ób   — e Zd ZU dZded<   ded<   ded<   dZded	<   edd
„«       Zedd„«       Z	y)Ú	VideoInfoaõ  
    A class to store video information, including width, height, fps and
        total number of frames.

    Attributes:
        width: width of the video in pixels
        height: height of the video in pixels
        fps: frames per second of the video as a float. Common values include
            23.976, 24.0, 25.0, 29.97, 30.0, 59.94, and 60.0.
        total_frames: total number of frames in the video,
            default is None

    Examples:
        ```python
        import supervision as sv

        video_info = sv.VideoInfo.from_video_path(video_path="<SOURCE_VIDEO_FILE>")

        video_info
        # VideoInfo(width=3840, height=2160, fps=25.0, total_frames=538)

        video_info.resolution_wh
        # (3840, 2160)
        ```
    ÚintÚwidthÚheightÚfloatÚfpsNú
int | NoneÚtotal_framesc                óä  — t        j                  |«      }|j                  «       st        d|› �«      ‚t	        |j                  t         j                  «      «      }t	        |j                  t         j                  «      «      }t        |j                  t         j                  «      «      }t	        |j                  t         j                  «      «      }|j                  «        t        ||||«      S )NúCould not open video at )Úcv2ÚVideoCaptureÚisOpenedÚ	Exceptionr   ÚgetÚCAP_PROP_FRAME_WIDTHÚCAP_PROP_FRAME_HEIGHTr   ÚCAP_PROP_FPSÚCAP_PROP_FRAME_COUNTÚreleaser   )ÚclsÚ
video_pathÚvideor   r   r   r   s          úb/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/supervision/utils/video.pyÚfrom_video_pathzVideoInfo.from_video_path:   s­   € ä× Ñ  Ó,ˆØ�~‰~ÔÜÐ6°z°lÐCÓDÐDä�E—I‘Iœc×6Ñ6Ó7Ó8ˆÜ�U—Y‘Yœs×8Ñ8Ó9Ó:ˆÜ�E—I‘Iœc×.Ñ.Ó/Ó0ˆÜ˜5Ÿ9™9¤S×%=Ñ%=Ó>Ó?ˆØ�‰ŒÜ˜ ¨¨\Ó:Ð:ó    c                ó2   — | j                   | j                  fS ©N)r   r   ©Úselfs    r&   Úresolution_whzVideoInfo.resolution_whG   s   € à�z‰z˜4Ÿ;™;Ð&Ð&r(   )r$   ÚstrÚreturnr   )r/   ztuple[int, int])
Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú__annotations__r   Úclassmethodr'   Úpropertyr-   © r(   r&   r   r      sH   … ñð4 ƒJØƒKØ	ƒJØ#€L�*Ó#àò
;ó ð
;ð ò'ó ñ'r(   r   c                  óB   — e Zd ZdZddd„Zd	d„Zd
d„Z	 	 	 	 	 	 	 	 dd„Zy)Ú	VideoSinkaØ  
    Context manager that saves video frames to a file using OpenCV.

    Attributes:
        target_path: The path to the output file where the video will be saved.
        video_info: Information about the video resolution, fps,
            and total frame count.
        codec: FOURCC code for video format

    Example:
        ```python
        import supervision as sv

        video_info = sv.VideoInfo.from_video_path("<SOURCE_VIDEO_PATH>")
        frames_generator = sv.get_video_frames_generator("<SOURCE_VIDEO_PATH>")

        with sv.VideoSink(target_path="<TARGET_VIDEO_PATH>", video_info=video_info) as sink:
            for frame in frames_generator:
                sink.write_frame(frame=frame)
        ```
    c                ó<   — || _         || _        || _        d | _        y r*   )Útarget_pathÚ
video_infoÚ_VideoSink__codecÚ_VideoSink__writer)r,   r;   r<   Úcodecs       r&   Ú__init__zVideoSink.__init__c   s   € Ø&ˆÔØ$ˆŒØˆŒØˆ�r(   c                ó”  — 	 t        j                  | j                  Ž | _        t        j                  | j                  | j                  | j                  j                  | j                  j                  «      | _        | S # t        $ r@}t
        j                  dt        |«      «       t        j                  dŽ | _        Y d }~ŒŸd }~ww xY w)Nz%s. Defaulting to mp4v...Úmp4v)r   ÚVideoWriter_fourccr=   Ú_VideoSink__fourccÚ	TypeErrorÚloggerÚwarningr.   ÚVideoWriterr;   r<   r   r-   r>   )r,   Úes     r&   Ú	__enter__zVideoSink.__enter__i   s™   € ð	<Ü×2Ñ2°D·L±LÐAˆDŒMô Ÿ™Ø×ÑØ�M‰MØ�O‰O×ÑØ�O‰O×)Ñ)ó	
ˆŒð ˆøô ò 	<Ü�N‰NÐ6¼¸A»Ô?Ü×2Ñ2°FÐ;ˆD�M‰Mûð	<ús   ‚!A> Á>	CÂ6CÃCc                óT   — | j                   �| j                   j                  |«       yy)zË
        Writes a single video frame to the target video file.

        Args:
            frame: The video frame to be written to the file. The frame
                must be in BGR color format.
        N)r>   Úwrite)r,   Úframes     r&   Úwrite_framezVideoSink.write_framew   s%   € ð �=‰=Ð$Ø�M‰M×Ñ Õ&ð %r(   c                óR   — | j                   �| j                   j                  «        y y r*   )r>   r"   )r,   Úexc_typeÚ	exc_valueÚexc_tracebacks       r&   Ú__exit__zVideoSink.__exit__‚   s#   € ð �=‰=Ð$Ø�M‰M×!Ñ!Õ#ð %r(   N)rB   )r;   r.   r<   r   r?   r.   )r/   r9   )rM   znpt.NDArray[np.uint8]r/   ÚNone)rP   ztype[BaseException] | NonerQ   zBaseException | NonerR   r   r/   rT   )r0   r1   r2   r3   r@   rJ   rN   rS   r7   r(   r&   r9   r9   L   sA   „ ñô,óó	'ð$à,ð$ð (ð$ð ð	$ð
 
ô$r(   r9   c                óª  — t        j                  d«      }|€t        j                  d«       yd}	 t	        j
                  t        j                  j                  |«      d   t        j                  j                  t        j                  j                  |«      «      ¬«      \  }}t        j                  |«       t        j                  |dddd	d
|d
| ddddddddd|gt        j                  t        j                  d¬«      }|j                   dk7  rŒ|j"                  j%                  d¬«      j'                  «       }t        j                  d|j                   |rd|› �nd«       	 |�6t        j                  j)                  |«      rt        j*                  |«       yyyt        j,                  ||«       |�6t        j                  j)                  |«      rt        j*                  |«       yyy# t.        $ r }t        j                  d|«       Y d}~Œ]d}~ww xY w# |�6t        j                  j)                  |«      rt        j*                  |«       w w w xY w)zñMux audio from `source_path` into `video_path` in-place using ffmpeg.

    Args:
        source_path: Path to the original video file containing the audio stream.
        video_path: Path to the video-only file to be updated with audio.
    ÚffmpegNzcffmpeg not found on PATH. Audio will not be preserved. Install ffmpeg to enable audio preservation.é   )ÚsuffixÚdirz-yz	-loglevelÚerrorz-nostatsz-iz-c:vÚcopyz-c:az-mapz0:v:0z1:a:0?z	-shortesti,  )ÚstdoutÚstderrÚtimeoutr   Úreplace)ÚerrorszTffmpeg failed to mux audio (return code %d)%s. The output video will not have audio.z: Ú z:Audio muxing failed: %s. Output video will not have audio.)ÚshutilÚwhichrF   rG   ÚtempfileÚmkstempÚosÚpathÚsplitextÚdirnameÚabspathÚcloseÚ
subprocessÚrunÚDEVNULLÚPIPEÚ
returncoder]   ÚdecodeÚstripÚexistsÚremover_   r   )Úsource_pathr$   Úffmpeg_pathÚtmp_pathÚtmp_fdÚresultÚ
stderr_msgÚexcs           r&   Ú
_mux_audior|   Œ   s  € ô —,‘,˜xÓ(€KØÐÜ�‰ð;ô	
ð 	à€Hð0 Ü#×+Ñ+Ü—7‘7×#Ñ# JÓ/°Ñ2Ü—‘—‘¤§¡§¡°
Ó ;Ó<ô
Ñˆ�ô 	�‰�ÔÜ—‘àØØØØØØØØØØØØØØØØØØð'ô* ×%Ñ%Ü—?‘?Øô1
ˆð4 ×Ñ Ò!ØŸ™×-Ñ-°YÐ-Ó?×EÑEÓGˆJÜ�N‰Nð8à×!Ñ!Ù%/�"�Z�LÑ!°Rô	ð ð Ð¤B§G¡G§N¡N°8Ô$<Ü�I‰I�hÕð %=Ðô 	�
‰
�8˜ZÔ(ð Ð¤B§G¡G§N¡N°8Ô$<Ü�I‰I�hÕð %=Ðøô ò 
Ü�‰ØHÈ#÷	
ñ 	
ûð
ûð
 Ð¤B§G¡G§N¡N°8Ô$<Ü�I‰I�hÕð %=Ðús0   ±D2G, ÆG, Ç,	HÇ5HÈH ÈHÈH È:IFc                ó´  — t        j                  | «      }|j                  «       st        d| › �«      ‚t	        |j                  t         j                  «      «      }|�||kD  rt        d«      ‚t        |d«      }|�t        ||«      n|}|r$|dkD  rD|j                  «       }|sn1|dz  }|dkD  rŒn%|dkD  r |j                  t         j                  |«       |||fS )Nr   zRequested frames are outboundr   rW   )r   r   r   r   r   r   r!   ÚmaxÚminÚgrabÚsetÚCAP_PROP_POS_FRAMES)ru   ÚstartÚendÚiterative_seekr%   r   Úsuccesss          r&   Ú_validate_and_setup_videor‡   Ï   sÖ   € ô ×Ñ˜[Ó)€EØ�>‰>ÔÜÐ2°;°-Ð@ÓAÐAÜ�u—y‘y¤×!9Ñ!9Ó:Ó;€LØ
€˜3 Ò-ÜÐ7Ó8Ð8Ü��q‹M€EØ$' OŒ#ˆc�<Ô
 ¸€CáØ�aŠiØ—j‘j“lˆGÙØØ�Q‰JˆEð	 �aŒið
 
�ŠØ�	‰	”#×)Ñ)¨5Ô1à�%˜ÐÐr(   c              #  óò   K  — t        | |||«      \  }}}|}	 |j                  «       \  }}|r||k\  rn3|�|–— t        |dz
  «      D ]  }	|j                  «       }|rŒ n ||z  }ŒN|j	                  «        y­w)aØ  
    Get a generator that yields the frames of the video.

    Args:
        source_path: The path of the video file.
        stride: Indicates the interval at which frames are returned,
            skipping stride - 1 frames between each.
        start: Indicates the starting position from which
            video should generate frames
        end: Indicates the ending position at which video
            should stop generating frames. If None, video will be read to the end.
        iterative_seek: If True, the generator will seek to the
            `start` frame by grabbing each frame, which is much slower. This is a
            workaround for videos that don't open at all when you set the `start` value.

    Returns:
        A generator that yields the
            frames of the video.

    Examples:
        ```python
        import supervision as sv

        for frame in sv.get_video_frames_generator(source_path="<SOURCE_VIDEO_PATH>"):
            ...
        ```
    NrW   )r‡   ÚreadÚranger€   r"   )
ru   Ústriderƒ   r„   r…   r%   Úframe_positionr†   rM   Ú_s
             r&   Úget_video_frames_generatorrŽ   ç   s™   è ø€ ôD 2Ø�U˜C óÑ€Eˆ5�#ð €NØ
ØŸ™›‰ˆ�Ù˜.¨CÒ/ØØÐØŠKÜ�v ‘zÓ"ò 	ˆAØ—j‘j“lˆGÚÙð	ð 	˜&Ñ ˆð ð 
‡M�M…Oùs   ‚AA7ÁA7é    zProcessing video)Ú
max_framesÚprefetchÚwriter_bufferÚshow_progressÚprogress_messageÚpreserve_audioc               ó€  ‡ ‡‡‡— t         j                  ‰ ¬«      }	‰�t        |	j                  xs d‰«      n|	j                  xs d}
t	        |¬«      Št	        |¬«      Šdˆˆˆ fd„}dˆfd„}t        j                  |d¬«      }t        ||	¬	«      5 }t        j                  ||fd¬
«      }|j                  «        |j                  «        t        |
| |¬«      }d}d}	 	 ‰j                  «       }|€d}n2|\  }}	  |||«      }‰j                  |«       |j                  d«       ŒG	 ‰j                  dd¬«       |s	 	 ‰j                  d¬«      }|€n	 Œ|j#                  d¬«       |j#                  d¬«       |j%                  «        |�|‚	 ddd«       |r4j!                  «       rt&        j)                  d«       yt+        ‰ |¬«       yy# t        $ r}|}Y d}~Œ·d}~ww xY w# t        $ r Y Œ¶w xY w# t        $ r |j!                  «       sY ŒºY ŒÕw xY w# 	 ‰j                  dd¬«       n# t        $ r Y nw xY w|s:	 	 ‰j                  d¬«      }|€n#n!# t        $ r |j!                  «       sY nY Œ5w xY wŒ9|j#                  d¬«       |j#                  d¬«       |j%                  «        |�|‚w xY w# 1 sw Y   �Œ&xY w)uh
  
    Process video frames asynchronously using a threaded pipeline.

    This function orchestrates a three-stage pipeline to optimize video processing
    throughput:

    1. Reader thread: Continuously reads frames from the source video file and
       enqueues them into a bounded queue (`frame_read_queue`). The queue size is
       limited by the `prefetch` parameter to control memory usage.
    2. Main thread (Processor): Dequeues frames from `frame_read_queue`, applies the
       user-defined `callback` function to process each frame, then enqueues the
       processed frames into another bounded queue (`frame_write_queue`) for writing.
       The processing happens in the main thread, simplifying use of stateful objects
       without synchronization.
    3. Writer thread: Dequeues processed frames from `frame_write_queue` and writes
       them sequentially to the output video file.

    Args:
        source_path: Path to the input video file.
        target_path: Path where the processed video will be saved.
        callback: Function called for
            each frame, accepting the frame as a numpy array and its zero-based index,
            returning the processed frame.
        max_frames: Optional maximum number of frames to process.
            If None, the entire video is processed (default).
        prefetch: Maximum number of frames buffered by the reader thread.
            Controls memory use; default is 32.
        writer_buffer: Maximum number of frames buffered before writing.
            Controls output buffer size; default is 32.
        show_progress: Whether to display a tqdm progress bar during processing.
            Default is False.
        progress_message: Description shown in the progress bar.
        preserve_audio: If True, copy the audio stream from `source_path` into
            `target_path` after frame processing. Requires `ffmpeg` on PATH
            (e.g. `apt install ffmpeg`, `brew install ffmpeg`). If ffmpeg is
            not found or the mux step fails, a warning is logged and the output
            video is saved without audio â€” no exception is raised. Audio is
            truncated to match the processed video duration. Default is False.

    Returns:
        None

    Example:
        ```python
        import supervision as sv
        from rfdetr import RFDETRMedium

        model = RFDETRMedium()

        def callback(frame, frame_index):
            return model.predict(frame)

        sv.process_video(
            source_path="source.mp4",
            target_path="target.mp4",
            callback=callback,
            preserve_audio=True,
        )
        ```
    )r$   Nr   )Úmaxsizec                 óŽ   •— t        ‰‰¬«      } t        | «      D ]  \  }}‰j                  ||f«       Œ ‰j                  d «       y )N)ru   r„   )rŽ   Ú	enumerateÚput)Úframe_generatorÚframe_indexrM   Úframe_read_queuer�   ru   s      €€€r&   Úreader_threadz$process_video.<locals>.reader_threadq  sO   ø€ Ü4Ø#Øô
ˆô #,¨OÓ"<ò 	7ÑˆK˜Ø× Ñ  +¨uÐ!5Õ6ð	7à×Ñ˜TÕ"r(   c                óR   •— 	 ‰j                  «       }|€y | j                  |¬«       Œ&)N)rM   )r   rN   )Ú
video_sinkrM   Úframe_write_queues     €r&   Úwriter_threadz$process_video.<locals>.writer_threadz  s2   ø€ ØØ%×)Ñ)Ó+ˆEØˆ}ØØ×"Ñ"¨Ð"Ô/ð	 r(   T)ÚtargetÚdaemon)r;   r<   )r£   Úargsr¤   )ÚtotalÚdisableÚdescFrW   )r^   é
   zdWriter thread did not finish in time; skipping audio mux to avoid reading an incomplete output file.)ru   r$   ©r/   rT   )r    r9   r/   rT   )r   r'   r   r   r
   Ú	threadingÚThreadr9   rƒ   r   r   rš   Úupdater   r	   r   Úis_aliveÚjoinrk   rF   rG   r|   )ru   r;   Úcallbackr�   r‘   r’   r“   r”   r•   r<   r   rž   r¢   Úreader_workerr    Úwriter_workerÚprogress_barÚexception_in_workerÚread_finishedÚ	read_itemrœ   rM   Úprocessed_framer{   r�   r¡   s   `  `                    @@r&   Úprocess_videor¸     s?  û€ ôP ×*Ñ*°kÐ*ÓB€Jð Ð!ô 	ˆJ×#Ñ#Ò( q¨*Ô5à×$Ñ$Ò)¨ð ô INØôIÐô >CØô>Ð÷#õ0ô ×$Ñ$¨MÀ$ÔG€MÜ	˜{°zÔ	Bð =*ÀjÜ!×(Ñ(Ø Ø�Øô
ˆð 	×ÑÔØ×ÑÔäØØ%Ð%Ø!ô
ˆð 15ÐØˆð*	*ØØ,×0Ñ0Ó2�	ØÐ$Ø$(�MØà%.Ñ"�˜UðÙ&.¨u°kÓ&B�OØ%×)Ñ)¨/Ô:Ø ×'Ñ'¨Ô*ð ðØ!×%Ñ% d°AÐ%Ô6ñ !Øð!Ø$4×$8Ñ$8ÀÐ$8Ó$C˜	Ø$Ð,Ø!ð -ð	 ð ×Ñ rÐÔ*Ø×Ñ rÐÔ*Ø×ÑÔ Ø"Ð.Ø)Ð)ð /÷y=*ñ~ Ø×!Ñ!Ô#Ü�N‰Nð>õô
  ;¸;ÖGð øôA !ò Ø*-Ð'Üûðûô ò ñ ð	ûô !ò !Ø,×5Ñ5Ô7Ù!á ð	!ûð#Ø!×%Ñ% d°AÐ%Õ6øÜò ñ ð	úñ
 !Øð!Ø$4×$8Ñ$8ÀÐ$8Ó$C˜	Ø$Ð,Ø!ð -øô
 !ò !Ø,×5Ñ5Ô7Ù!á ð	!úð ð ×Ñ rÐÔ*Ø×Ñ rÐÔ*Ø×ÑÔ Ø"Ð.Ø)Ð)ð /ú÷y=*ñ =*úsÙ   ÂAJ3ÃHÃ;+GÄ&HÄ(G&Ä;J3Ä?G5Å;J3Ç	G#ÇGÇHÇG#Ç#HÇ&	G2Ç/J3Ç1G2Ç2J3Ç5HÈJ3ÈHÈJ3ÈJ0ÈH,È+J0È,	H8	È5J0È7H8	È8J0È?IÉJ0ÉI3	É.J0É2I3	É3=J0Ê0J3Ê3J=c                  ó<   — e Zd ZdZddd„Zed	d„«       Zd
d„Zd
d„Zy)Ú
FPSMonitorzN
    A class for monitoring frames per second (FPS) to benchmark latency.
    c                ó&   — t        |¬«      | _        y)a  
        Args:
            sample_size: The maximum number of observations for latency
                benchmarking.

        Examples:
            ```python
            import supervision as sv

            frames_generator = sv.get_video_frames_generator(
                source_path="<SOURCE_FILE_PATH>")
            fps_monitor = sv.FPSMonitor()

            for frame in frames_generator:
                # your processing code here
                fps_monitor.tick()
                fps = fps_monitor.fps
            ```
        )ÚmaxlenN)r   Úall_timestamps)r,   Úsample_sizes     r&   r@   zFPSMonitor.__init__Ð  s   € ô( -2¸Ô,EˆÕr(   c                ó˜   — | j                   sy| j                   d   | j                   d   z
  }|dk7  rt        | j                   «      |z  S dS )z°
        Computes and returns the average FPS based on the stored time stamps.

        Returns:
            The average FPS. Returns 0.0 if no time stamps are stored.
        g        éÿÿÿÿr   )r½   Úlen)r,   Ú
taken_times     r&   r   zFPSMonitor.fpsæ  sQ   € ð ×"Ò"ØØ×(Ñ(¨Ñ,¨t×/BÑ/BÀ1Ñ/EÑEˆ
Ø:DÈº/”�D×'Ñ'Ó(¨JÑ6ÐRÈsÐRr(   c                ó^   — | j                   j                  t        j                  «       «       y)zI
        Adds a new time stamp to the deque for FPS calculation.
        N)r½   ÚappendÚtimeÚ	monotonicr+   s    r&   ÚtickzFPSMonitor.tickó  s   € ð 	×Ñ×"Ñ"¤4§>¡>Ó#3Õ4r(   c                ó8   — | j                   j                  «        y)z<
        Clears all the time stamps from the deque.
        N)r½   Úclearr+   s    r&   ÚresetzFPSMonitor.resetù  s   € ð 	×Ñ×!Ñ!Õ#r(   N)é   )r¾   r   )r/   r   rª   )	r0   r1   r2   r3   r@   r6   r   rÇ   rÊ   r7   r(   r&   rº   rº   Ë  s-   „ ñôFð, ò
Só ð
Só5ô$r(   rº   )ru   r.   r$   r.   r/   rT   )F)
ru   r.   rƒ   r   r„   r   r…   Úboolr/   z!tuple[cv2.VideoCapture, int, int])rW   r   NF)ru   r.   r‹   r   rƒ   r   r„   r   r…   rÌ   r/   z,Generator[npt.NDArray[np.uint8], None, None])ru   r.   r;   r.   r°   z=Callable[[npt.NDArray[np.uint8], int], npt.NDArray[np.uint8]]r�   r   r‘   r   r’   r   r“   rÌ   r”   r.   r•   rÌ   r/   rT   )'Ú
__future__r   rf   rb   rl   rd   r«   rÅ   Úcollectionsr   Úcollections.abcr   r   Údataclassesr   Úqueuer   r	   r
   Útypingr   r   ÚnumpyÚnpÚnumpy.typingÚnptÚ	tqdm.autor   Úsupervision.utils.loggerr   r0   rF   r   r9   r|   r‡   rŽ   r¸   rº   r7   r(   r&   ú<module>rÙ      sŒ  ðÝ "ã 	Û Û Û Û Û Ý ß /Ý !ß $Ñ $Ý ã 
Û Ý Ý å 0á	�XÓ	€ð ÷/'ð /'ó ð/'÷d=$ñ =$ó@@ ðH KPðØðØ ðØ'1ðØCGðà&óð4 ØØØ ð1Øð1àð1ð ð1ð 
ð	1ð
 ð1ð 2ó1ðr "ØØØØ.Ø ñmHØðmHàðmHð LðmHð
 ðmHð ðmHð ðmHð ðmHð ðmHð ðmHð 
ómH÷`2$ò 2$r(   