Skip to content

Conversation

@mockersf
Copy link
Member

@mockersf mockersf commented Sep 27, 2025

Objective

Solution

  • Make a new EasyScreenRecordPlugin in the dev tools

Testing

  • Add to any example
        .add_plugins(bevy::dev_tools::EasyScreenRecordPlugin::default())
  • Run the example with the feature bevy_internal/screenrecording enabled
  • press the space bar
  • wait for it...
  • press the space bar again
  • screen recording! 🎉
  • almost... you now have a h264 file. VLC can read them, but they are not the most friendly format
  • ffmpeg is our friend! for file in *.h264; do ffmpeg -i $file $file.mp4; done
  • you now have a .mp4 file that can be shared anywhere!

Showcase

directly taken by Bevy

load_gltf-1758937494581.h264.mp4

@mockersf mockersf force-pushed the easy-screenrecording branch from b901e65 to 746e1fc Compare September 27, 2025 01:55
@mockersf mockersf force-pushed the easy-screenrecording branch from 72d67c1 to 5e206e0 Compare September 27, 2025 10:16
@mockersf mockersf force-pushed the easy-screenrecording branch from 5e206e0 to 88f3173 Compare September 27, 2025 10:18
@mockersf mockersf mentioned this pull request Sep 27, 2025
@torsteingrindvik
Copy link
Contributor

Would be even better imo if I could choose which resolution to record at.

One way could be to have the plugin take care to copy the source texture to another texture then rescale as part of the render graph.

Another could be to just use the CPU data and resize via e.g. the image crate or similar.

The user-responsibility way is probably to have them choose the correct primary window size, but if I have a low res screen and want to record e.g. 4k then it's better to have an off-screen render target.

@torsteingrindvik
Copy link
Contributor

Also, why not https://crates.io/crates/video-rs?

@mockersf
Copy link
Member Author

Would be even better imo if ...

I agree, but I think out of scope of this PR, that's part of the frame capture pipeline, this PR is mostly on what to do with the frames once captured. And hopefully to stay "easy and simple".

@mockersf
Copy link
Member Author

mockersf commented Sep 27, 2025

Also, why not https://crates.io/crates/video-rs?

Mainly because I'm so used to use ffmeg on the command line that I didn't look for a crate for it but directly for an encoder

@alice-i-cecile alice-i-cecile added M-Release-Note Work that should be called out in the blog due to impact A-Dev-Tools Tools used to debug Bevy applications. S-Needs-Review Needs reviewer attention (from anyone!) to move forward C-Feature A new feature, making something new possible labels Sep 28, 2025
@alice-i-cecile alice-i-cecile added this to the 0.18 milestone Sep 28, 2025
@github-actions
Copy link
Contributor

It looks like your PR has been selected for a highlight in the next release blog post, but you didn't provide a release note.

Please review the instructions for writing release notes, then expand or revise the content in the release notes directory to showcase your changes.

@mockersf mockersf marked this pull request as ready for review September 30, 2025 06:03
@mockersf
Copy link
Member Author

mockersf commented Oct 15, 2025

now with a fixed frame time:

  • when recording, pause virtual time
  • every time a frame is captured, advance time by the target frame time
  • when done recording, unpause virtual time
  • use the target frame time when encoding the video

@it-me-joda
Copy link
Contributor

More of a note for the future that may or may not be worth it but it would be nice to have a way to conveniently playback what was just recorded.

@torsteingrindvik
Copy link
Contributor

torsteingrindvik commented Oct 28, 2025

I agree, but I think out of scope of this PR, that's part of the frame capture pipeline, this PR is mostly on what to do with the frames once captured. And hopefully to stay "easy and simple".

I still disagree with this, the video crate lets you

// One time init...
video_rs::init().unwrap();

let settings = Settings::preset_h264_yuv420p(1920, 1080, false);
let mut encoder = Encoder::new("foo.mp4", settings)?;

let frame_duration = Time::from_nth_of_a_second(30);
let mut position = Time::zero();

// For all screenshots
let to_encode = Frame::from_shape_vec([1080, 1920, 3], screenshot.to_rgb8()).unwrap();
encoder.encode(to_encode, position);
position = position.aligned_with(frame_duration).add();

Then the finished foo.mp4 is ready (on encoder Drop, or explicitly if wanted), no need to have lots of images lying around or to post-process an h264 file.

@kerkmann
Copy link
Contributor

Adding my two cents (tldr): Using mp4 is not a good solution for a file recording (in terms of fail safety/corruption), please use formats like mkv.

If the application is crashing, then the entire mp4 is corrupted. There are container formats like mkv which are safe (in terms of cutting of the end in case of an exception/emergency exit/unfinished write). If you are using mkv and your bevy application is crashing, then the entire video file is still working, only the time duration is missing, but this can be repaired afterwards. If you are using mp4 and your bevy application is crashing, then you are screwed, all you have is garbage data and the recording itself cannot be used anymore. :)

@kerkmann
Copy link
Contributor

kerkmann commented Nov 19, 2025

Also please note: x264 is GPL-licensed, but the H.264/AVC codec itself is covered by MPEG-LA patents. This means even open-source projects might need to pay license fees when distributing software that includes H.264 encoding. So using x264 can have legal and licensing risks. I would rather use VP8/VP9 or (even better but there are no good software decoder and less hardware decoder) AV1.

Source: https://stackoverflow.com/questions/2328092/im-creating-opensource-gpl-h264-encoding-lib-app-based-on-x264-do-i-need-to-p

Edit: I would recommend the vpx-rs crate, this is much better, it supports vp8/vp9 and there are no patent/license problems. :)

Copy link
Contributor

@kerkmann kerkmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move from x264 to vp8/vp9 or av1 regards MPEG/LA patents.

Copy link
Contributor

@pablo-lua pablo-lua left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have an example on how to use this feature?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Dev-Tools Tools used to debug Bevy applications. C-Feature A new feature, making something new possible M-Release-Note Work that should be called out in the blog due to impact S-Needs-Review Needs reviewer attention (from anyone!) to move forward

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants