Genesis icon indicating copy to clipboard operation
Genesis copied to clipboard

[Bug]: Missing frames in cam.render()

Open BugDigK opened this issue 4 months ago • 3 comments

Bug Description

When I use the following code, I notice that cam.render() is called 120 times, but the video only saves 119 frames instead of 120. Is the missing frame the starting frame or the ending frame? Is this by design?

import genesis as gs

gs.init(backend=gs.cpu)

scene = gs.Scene(
    show_viewer = True,
    viewer_options = gs.options.ViewerOptions(
        res           = (1280, 960),
        camera_pos    = (3.5, 0.0, 2.5),
        camera_lookat = (0.0, 0.0, 0.5),
        camera_fov    = 40,
        max_FPS       = 60,
    ),
    vis_options = gs.options.VisOptions(
        show_world_frame = True,
        world_frame_size = 1.0,
        show_link_frame  = False,
        show_cameras     = False,
        plane_reflection = True,
        ambient_light    = (0.1, 0.1, 0.1),
    ),
    renderer=gs.renderers.Rasterizer(),
)

plane = scene.add_entity(
    gs.morphs.Plane(),
)
franka = scene.add_entity(
    gs.morphs.MJCF(file='xml/franka_emika_panda/panda.xml'),
)

cam = scene.add_camera(
    res    = (640, 480),
    pos    = (3.5, 0.0, 2.5),
    lookat = (0, 0, 0.5),
    fov    = 30,
    GUI    = False,
)

scene.build()

# 渲染rgb、深度、分割掩码和法线图
# rgb, depth, segmentation, normal = cam.render(rgb=True, depth=True, segmentation=True, normal=True)

cam.start_recording()
import numpy as np

for i in range(120):
    scene.step()
    cam.set_pose(
        pos    = (3.0 * np.sin(i / 60), 3.0 * np.cos(i / 60), 2.5),
        lookat = (0, 0, 0.5),
    )
    cam.render()
cam.stop_recording(save_to_filename='video.mp4', fps=60)

Steps to Reproduce

code

Expected Behavior

fix

Screenshots/Videos

No response

Relevant log output


Environment

  • OS: [e.g. Ubuntu 22.04]
  • GPU/CPU [e.g. A100, RTX 4090, M3pr, Intel I9-9900k, Ryzen 5900x] (N/A if no GPU/CPU)
  • GPU-driver version (N/A if no GPU)
  • CUDA / CUDA-toolkit version (N/A if non-Nvidia)

Release version or Commit ID

0.3.1

Additional Context

No response

BugDigK avatar Aug 26 '25 16:08 BugDigK

The bug occurs in the animate function at genesis/utils/tools.py, lines 33–44:

from moviepy import ImageSequenceClip

imgs = ImageSequenceClip(imgs, fps=fps)
imgs.write_videofile(
    filename,
    fps=fps,
    logger=None,
    codec="libx264",
    preset="ultrafast",
    # ffmpeg_params=["-crf", "0"],
)
gs.logger.info("Video saved.")

The video appears to save fine (no error), but the last frame gets dropped.

I tested with the following script:

import os
import cv2
import numpy as np
from moviepy import ImageSequenceClip

# Generate 120 frames with center text, text start from 1, end at 120
def generate_frames(n=120, h=60, w=120):
    frames = []
    font = cv2.FONT_HERSHEY_SIMPLEX
    for i in range(n):
        img = np.full((h, w, 3), (i * 2 % 255, 100, 200), dtype=np.uint8)
        img = cv2.cvtColor(img, cv2.COLOR_HSV2BGR)
        text = f"{i+1}"
        (w_text, h_text), _ = cv2.getTextSize(text, font, 0.5, 1)
        cv2.putText(img, text, ((w - w_text) // 2, (h + h_text) // 2), font, 0.5, (255, 255, 255), 1)
        frames.append(img[:, :, ::-1])  # BGR -> RGB
    return frames

# Save video with moviepy
imgs = generate_frames(120)
video_file = "test.mp4"
if os.path.exists(video_file):
    os.remove(video_file)

clip = ImageSequenceClip(imgs, fps=60)
clip.write_videofile(video_file, fps=60, logger=None, codec="libx264", preset="ultrafast")

# Count frames with OpenCV
cap = cv2.VideoCapture(video_file)
count = 0
while cap.read()[0]:
    count += 1
cap.release()

print(f"Generated: 120 frames")
print(f"Read by OpenCV: {count} frames")
print("Pass" if count == 120 else "Fail: Last frame lost")

Looks like this is a moviepy issue — when I downgraded moviepy to version 1.0.0, the frame count became correct.

https://github.com/user-attachments/assets/10b5c932-eda2-4e09-b6ba-cde04dbaea03

ceasor-mao avatar Aug 29 '25 12:08 ceasor-mao

Thank you for your detailed analysis. Good to know it may be related to moviepy. We should probably switch to pyav, it is just strictly superior.

duburcqa avatar Aug 30 '25 06:08 duburcqa

A new recorder based on PyAV has been implemented, but camera needs to be updated to leverage this new capability. This should fix this issue.

duburcqa avatar Sep 18 '25 09:09 duburcqa