Crate bevy_capture

Source
Expand description

§bevy_capture

License Build Status crates.io docs.rs

A Bevy plugin for capturing frames from a Bevy application. It comes with some built-in encoders, e.g. for creating gifs or videos, and can be easily extended with custom encoders.

§Current Limitations

  • Only headless rendering is supported, but windowed rendering should be possible as well. PRs are welcome!

§Built-in Encoders

NameDescriptionRequired Features
FramesEncoderEncodes frames into individual images.
GifEncoderEncodes frames into a gif.gif
Mp4Openh264EncoderEncodes frames into an mp4 using openh264.mp4_openh264
Mp4FfmpegCliEncoderEncodes frames into an mp4 using the ffmpeg CLI (ffmpeg must be in PATH).mp4_ffmpeg_cli

§Usage

For a complete example, see the simple example.

// Add plugins
app.add_plugins((
    DefaultPlugins
        .build()
        // Disable the WinitPlugin to prevent the creation of a window
        .disable::<WinitPlugin>()
        // Make sure pipelines are ready before rendering
        .set(RenderPlugin {
            synchronous_pipeline_compilation: true,
            ..default()
        }),
    // Add the ScheduleRunnerPlugin to run the app in loop mode
    ScheduleRunnerPlugin {
        run_mode: RunMode::Loop { wait: None },
    },
    // Add the CapturePlugin
    bevy_capture::CapturePlugin,
));

// Spawn a camera with the CaptureBundle
fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
  commands.spawn((
      Camera2d,
      Camera::default().target_headless(512, 512, &mut images),
      CaptureBundle::default(),
  ));
}

// Start capturing
fn update(mut capture: Query<&mut Capture>) {
  let mut capture = capture.single_mut().unwrap();
  if !capture.is_capturing() {
    capture.start(
      GifEncoder::new(File::create("my_capture.gif").unwrap())
        .with_repeat(gif::Repeat::Infinite)
    );
  }
}

§Implementing a Custom Encoder

struct MyCustomEncoder;

impl Encoder for MyCustomEncoder {
    fn encode(&mut self, image: &Image) -> Result<()> {
        // Called for each frame.
        todo!("Encode the image into your custom format.")
    }

    fn finish(self: Box<Self>) {
      // Called when the encoder is stopped.
      todo!("Finish encoding the frames, if necessary.")
    }
}

§Alternatives

  • bevy_image_export: Less opinionated, no encoders included, only image sequences. This might be a better fit, if you end up using ffmpeg on the frames anyway.

§License

Licensed under either of

at your option.

Modules§

encoder
Encoders for different formats.

Structs§

Capture
The capture component.
CaptureBundle
Bundle for the capture plugin. This is usually attached to a camera.
CapturePlugin
A Bevy plugin for capturing frames.

Enums§

CaptureSource
The source of the capture.

Traits§

CameraTargetHeadless
Extension trait for the camera to set the target to a headless image.
Encoder
An encoder that encodes a sequence of images into a custom format.
IntoEncoders
Convert a value into a sequence of encoders.