Skip to content

Video recorder

video_recorder

VideoRecorder dataclass

Python
VideoRecorder(
    path: Path,
    camera_name: CameraName,
    show_loads: bool = False,
    show_net_force: bool = False,
    show_contacts: bool = False,
    show_proximities: bool = False,
    fps: int = 30,
    width: int = 640,
    height: int = 480,
    _frames: list = list(),
)

capture_frame

Python
capture_frame(
    mj_model: MjModel,
    mj_data: MjData,
    custom_arrows: list[ArrowConfig],
    custom_lines: list[LineConfig],
)

Captures the current state as a video frame.

Source code in src/mujoco_mojo/runtime/video_recorder.py
Python
def capture_frame(
    self,
    mj_model: mujoco.MjModel,
    mj_data: mujoco.MjData,
    custom_arrows: list[ArrowConfig],
    custom_lines: list[LineConfig],
):
    """Captures the current state as a video frame."""
    if mj_data.time < self._next_record_time:
        return

    # update standard mujoco objects in scene
    self._renderer.update_scene(
        data=mj_data,
        camera=self.camera_name,
        scene_option=self._vopt,
    )

    if custom_arrows and self.show_loads:
        for arrow in custom_arrows:
            arrow.draw_in_scene(mj_model, self._renderer.scene)

    if custom_lines and self.show_proximities:
        for line in custom_lines:
            line.draw_in_scene(self._renderer.scene)

    # capture and increment the clock for the next frame
    self._frames.append(self._renderer.render())
    self._next_record_time += 1 / self.fps

save

Python
save()

Writes the captured frames to a video file.

Source code in src/mujoco_mojo/runtime/video_recorder.py
Python
def save(self):
    """Writes the captured frames to a video file."""
    if not self._frames:
        return
    import mediapy as media

    if self.path.suffix.lower() == ".gif":
        from PIL import Image

        # convert arrays to PIL images
        pil_images = [Image.fromarray(frame) for frame in self._frames]

        # save gif
        pil_images[0].save(
            self.path,
            save_all=True,
            append_images=pil_images[1:],
            duration=int(1000 / self.fps),  # ms per frame
            loop=0,  # loop forever
        )
    else:
        media.write_video(path=self.path, images=self._frames, fps=self.fps)
    logger.info(f"Video saved to {self.path}")