Skip to content

Latest commit

 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bevy-ffmpeg

A Bevy plugin for playing video with FFmpeg.

The aim is a Bevy-native playback API, not a thin FFmpeg wrapper. You spawn a VideoPlayer entity, the plugin decodes on a background thread, and frames land in a Bevy Image you can use with sprites, UI, or materials. Playback time is in seconds so it lines up with Bevy's Time. The decode engine itself stays free of Bevy, in case you want it without an ECS.

This project is a work in progress and the API is unstable.

Examples

cargo run --example bevy_media_player --features examples -- path/to/video.mp4
cargo run --example rotating_video_cube --features example-3d -- path/to/video.mp4

bevy_media_player

bevy-ffmpeg-pixfx.mp4

This demo is from pixfx, a project I am working on that will let users edit their videos using shaders. pixfx is essentially based on bevy_media_player, with a considerable amount of configuration for shader effects. It is still a WIP, but once it is available, it can be found there.

rotating_video_cube

bevy-ffmpeg-rotating-cube.mp4

Both demos use copyrighted material from Young Justice Season 1 Episode 22. The video is available on YouTube.

Status

Working today:

  • Video decode for anything FFmpeg can open
  • Play, pause, seek, and looping
  • Several videos at once, each on its own entity
  • VideoMessage for ready, ended, and error

Not there yet (but one day :D):

  • Audio
  • Hardware-accelerated decode

Usage

Add FfmpegPlugin, spawn a VideoPlayer, and attach a sprite (or anything else that takes an Image handle) when the track is ready:

use bevy::prelude::*;
use bevy_ffmpeg::{FfmpegPlugin, VideoImage, VideoMessage, VideoPlayer};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(FfmpegPlugin)
        .add_systems(Startup, setup)
        .add_systems(Update, on_video_ready)
        .run();
}

fn setup(mut commands: Commands) {
    commands.spawn(Camera2d::default());
    commands.spawn(VideoPlayer::new("video.mp4".into()).autoplay().looping());
}

fn on_video_ready(
    mut commands: Commands,
    mut messages: MessageReader<VideoMessage>,
    images: Query<&VideoImage>,
) {
    for message in messages.read() {
        let VideoMessage::Ready { entity, .. } = message else {
            continue;
        };
        let Ok(image) = images.get(*entity) else {
            continue;
        };
        commands.spawn(Sprite::from_image(image.0.clone()));
    }
}

Control playback by mutating the component: play(), pause(), toggle_playing(), seek_to(seconds), and looping(). Read get_position() and get_duration() for the playhead.

You need FFmpeg development libraries on the system. This crate binds to them through ffmpeg-next.

License

MIT

About

Bevy + FFmpeg = Dream come true

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages