Video Recording¶
KangEngine can record the framebuffer of an App to MP4. Recording captures
the rendered scene, while the red REC status shown in the viewer is not
included in the output.
By default, recordings use libx264 through imageio-ffmpeg, are written to
tmp/recordings, and are capped at 1920x1080. Larger framebuffers are scaled
before capture, while smaller framebuffers are not enlarged.
Viewer shortcuts¶
T: save one screenshot.Shift+T: start or stop video recording.
Configure recording¶
Configure the output directory, frame rate, or resolution before recording:
import kangengine as ke
app = ke.App()
app.set_video_recording_dir("captures")
app.set_video_recording_fps(60)
app.set_video_recording_resolution(1920, 1080)
Pass None to record at the native framebuffer resolution:
app.set_video_recording_resolution(None)
Programmatic recording¶
app.start_video_recording("captures/run.mp4")
# Render frames normally.
path = app.stop_video_recording()
stop_video_recording() finalizes the encoder and returns the output path.
Closing an App also finalizes an active recording.
Interactive recording follows wall-clock time. Frames are selected or repeated as needed so that the video duration matches the elapsed recording time, independently of the viewer render rate.
Offscreen recording¶
An App initialized with headless=True uses offscreen rendering:
app = ke.App()
app.initialize(1280, 720, hide_ui=True, headless=True)
app.configure_timing(
ke.SimulationTimingConfig(
render_hz=0,
physics_hz=120,
fixed_update_hz=60,
)
)
app.start_video_recording("captures/offscreen.mp4")
for _ in range(600):
app.render_frame_once()
app.stop_video_recording()
Offscreen recording writes one video frame for each rendered frame and uses
fixed_update_hz as its default video FPS. HEADLESS_FAST creates no renderer
and therefore cannot record video.
Record RGB frames directly¶
VideoRecorder can also encode uint8 RGB arrays shaped
[height, width, 3] without an App:
recorder: ke.recording.VideoRecorder = ke.recording.VideoRecorder(
output_path="output.mp4",
fps=60,
)
with recorder:
recorder.write(frame=rgb_frame)
Pass codec to VideoRecorder to select another available encoder.
All frames in one recording must have the same resolution.