Expand description
A hardware-accelerated video widget for egui, backed by libmpv2.
This crate provides an immediate-mode video player for eframe
applications.
§Overview
-
PlayerState: Manages thelibmpvcontext, media properties, and playback state. This requires access to the graphics context and must be initialized once using theeframe::CreationContext.A single
PlayerStatemaps to a single video stream. Displaying multiple videos simultaneously requires independent state instances. -
SharkPlayer: The actual UI widget. This is what you create in youruimethod.
The video player works best with the glow backend because libmpv2’s render
API only supports OpenGL. When using the wgpu feature, instead of a direct
VRAM copy, image data has to roundtrip through main system memory. If at all
possible, use glow and disable the wgpu feature.
Because playback is driven with mpv, and video frames are rendered straight
into an OpenGL framebuffer, this only works when using eframe’s glow
rendering backend; wgpu is not supported.
§Features
- Integrated contol overlays (play/pause, volume, seekbar, info overlay, etc.)
- Fullscreening support
§Quick Start
use eframe::egui;
use egui_sharkplayer::{PlayerState, SharkPlayer};
struct App {
player: PlayerState,
}
impl App {
fn new(cc: &eframe::CreationContext<'_>) -> Self {
let player = PlayerState::new(cc).expect("failed to initialize player");
player.load_file("video.mp4").expect("failed to load video.mp4");
Self { player }
}
}
impl eframe::App for App {
fn on_exit(&mut self, _gl: Option<&eframe::glow::Context>) {
// Required: see "Cleaning up".
self.player.destroy_gl_resources();
}
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show_inside(ui, |ui| {
ui.add(SharkPlayer::new(&mut self.player));
});
}
}
fn main() {
eframe::run_native(
"Sharkplayer",
eframe::NativeOptions::default(),
Box::new(|cc| Ok(Box::new(App::new(cc)))),
)
.unwrap();
}If you want to play multiple videos at the same time, you’ll need to have
multiple PlayerStates.
§Player Size
By default, the widget claims all the space available in its panel. However,
it’s possible to contrain one of the axes using SharkPlayer::sizing to
pin one axis instead — the other is derived from the video’s aspect ratio,
so the player doesn’t letterbox.
ui.add(SharkPlayer::new(player).sizing(Sizing::Width(640.0)));§Styling Controls
For the most part, the controls use standard egui styling, but some components have special styling options.
§Bar Height
The player bar has a default height, but it can be overridden with
SharkPlayer::bar_height.
ui.add(
SharkPlayer::new(player)
.sizing(Sizing::Height(360.0))
.bar_height(32.0),
);§Custom icons
To customize which icons are used for the controls, you need a
ControlsIconProvider.
use egui_sharkplayer::{ControlsIconProvider, PlayerState, SharkPlayer};
struct Icons;
impl ControlsIconProvider for Icons {
fn play(&self) -> egui::WidgetText { "Play".into() }
fn pause(&self) -> egui::WidgetText { "Pause".into() }
}
ui.add(SharkPlayer::new_with_icons(player, Icons));§Cleaning Up
To clean up the player’s OpenGL resources, call
PlayerState::destroy_gl_resources from eframe::App::on_exit.
This isn’t strictly necessary it’s fine to leak VRAM, like if the process stops when the UI closes.
Structs§
- Default
Controls Icon Provider - The default
ControlsIconProvider. - Keybinds
- Player
State - The persistant state for the video player. This must be created on the UI thread and persist across frames.
- Shark
Player - The video player widget. This is what actually get’s created in the
uifunction.
Enums§
- Backend
Error - Sizing
- Constrain
SharkPlayerdimensions. To maintain the aspect ratio, only the width or height can be specified.