
    h                        S r SSKJr  SSKrSSKJr  SSKrSSKJr   SSK	J
r
  S
S jr       S                 SS	 jjrg! \ a!  r\R                  R                  S5      \eSrCff = f)z+Utility functions to save rendering videos.    )annotationsN)Callablelogger)ImageSequenceClipz>moviepy is not installed, run `pip install "gymnasium[other]"`c                X    U S:  a  [        [        U S-  5      5      S-  U :H  $ U S-  S:H  $ )zThe default episode trigger.

This function will trigger recordings at the episode indices :math:`\{0, 1, 4, 8, 27, ..., k^3, ..., 729, 1000, 2000, 3000, ...\}`

Args:
    episode_id: The episode number

Returns:
    If to apply a video schedule number
i  gUUUUUU?   r   )intround)
episode_ids    T/home/james-whalen/.local/lib/python3.13/site-packages/gymnasium/utils/save_video.pycapped_cubic_video_scheduler      s;     D5012a7:EED A%%    c	                8   [        U [        5      (       d#  [        R                  " S[	        U 5       S35        Uc	  Uc  [
        n[        R                  R                  U5      n[        R                  " USS9  U SU 3n
Ub2  U" U5      (       a%  [        U SU 40 U	D6nUR                  U
 SU S3US	9  Ubc  [        [        S
[        U 5      5      US9 HA  u  pU" U5      (       d  M  Ub  X-   OSn[        XU 40 U	D6nUR                  U
 SU S3US	9  MC     gg)a  Save videos from rendering frames.

This function extract video from a list of render frame episodes.

Args:
    frames (List[RenderFrame]): A list of frames to compose the video.
    video_folder (str): The folder where the recordings will be stored
    episode_trigger: Function that accepts an integer and returns ``True`` iff a recording should be started at this episode
    step_trigger: Function that accepts an integer and returns ``True`` iff a recording should be started at this step
    video_length (int): The length of recorded episodes. If it isn't specified, the entire episode is recorded.
        Otherwise, snippets of the specified length are captured.
    name_prefix (str): Will be prepended to the filename of the recordings.
    episode_index (int): The index of the current episode.
    step_starting_index (int): The step index of the first frame.
    save_logger: If to log the video saving progress, helpful for long videos that take a while, use "bar" to enable.
    **kwargs: The kwargs that will be passed to moviepy's ImageSequenceClip.
        You need to specify either fps or duration.

Example:
    >>> import gymnasium as gym
    >>> from gymnasium.utils.save_video import save_video
    >>> env = gym.make("FrozenLake-v1", render_mode="rgb_array_list")
    >>> _ = env.reset()
    >>> step_starting_index = 0
    >>> episode_index = 0
    >>> for step_index in range(199): # doctest: +SKIP
    ...    action = env.action_space.sample()
    ...    _, _, terminated, truncated, _ = env.step(action)
    ...
    ...    if terminated or truncated:
    ...       save_video(
    ...          frames=env.render(),
    ...          video_folder="videos",
    ...          fps=env.metadata["render_fps"],
    ...          step_starting_index=step_starting_index,
    ...          episode_index=episode_index
    ...       )
    ...       step_starting_index = step_index + 1
    ...       episode_index += 1
    ...       env.reset()
    >>> env.close()
z!Expected a list of frames, got a z	 instead.NT)exist_ok/z	-episode-z.mp4r      )startz-step-)
isinstancelistr   errortyper   ospathabspathmakedirsr   write_videofile	enumeraterangelen)framesvideo_folderepisode_triggerstep_triggervideo_lengthname_prefixepisode_indexstep_starting_indexsave_loggerkwargspath_prefixclip
step_indexframe_index	end_indexs                  r   
save_videor0   %   sB   l fd##8fiPQ<#7577??<0LKKt,!N!K=1K"}'E'E !6A&Am9]O48 	 	
 '0!S[!)<(
#J J''2>2JK.PT  )I)FQ&Q$$"m6*T:; % (
  r   )r   r
   returnbool)NNNzrl-videor   r   N)r!   r   r"   strr#   Callable[[int], bool]r$   r4   r%   z
int | Noner&   r3   r'   r
   r(   r
   r)   z
str | None)__doc__
__future__r   r   collections.abcr   	gymnasiumgymr   "moviepy.video.io.ImageSequenceClipr   ImportErrorer   DependencyNotInstalledr   r0    r   r   <module>r?      s    1 " 	 $  D&( .2*.#! "QQQ +Q (	Q
 Q Q Q Q Q/  
))
*
*Hs   A	 	A0A++A0