feat(player): add chunk/scene markers on progress bar
This commit is contained in:
@@ -19,6 +19,9 @@ pub struct Config {
|
|||||||
#[arg(short = 'y', long = "yolo", help = "YOLO JSON file path")]
|
#[arg(short = 'y', long = "yolo", help = "YOLO JSON file path")]
|
||||||
pub yolo: Option<PathBuf>,
|
pub yolo: Option<PathBuf>,
|
||||||
|
|
||||||
|
#[arg(short = 'c', long = "chunks", help = "Chunk/Cut JSON file path")]
|
||||||
|
pub chunks: Option<PathBuf>,
|
||||||
|
|
||||||
#[arg(
|
#[arg(
|
||||||
short = 'w',
|
short = 'w',
|
||||||
long = "width",
|
long = "width",
|
||||||
|
|||||||
68
src/main.rs
68
src/main.rs
@@ -15,7 +15,7 @@ mod player;
|
|||||||
mod web;
|
mod web;
|
||||||
|
|
||||||
use config::Config;
|
use config::Config;
|
||||||
use overlay::{AsrLoader, YoloLoader};
|
use overlay::{AsrLoader, ChunkLoader, YoloLoader};
|
||||||
use player::ffmpeg::FFmpegDecoder;
|
use player::ffmpeg::FFmpegDecoder;
|
||||||
use player::state::{PlaybackState, PlayerState};
|
use player::state::{PlaybackState, PlayerState};
|
||||||
|
|
||||||
@@ -63,6 +63,7 @@ fn run(config: &Config) -> Result<()> {
|
|||||||
let mut video_info = None;
|
let mut video_info = None;
|
||||||
let mut asr: Option<AsrLoader> = None;
|
let mut asr: Option<AsrLoader> = None;
|
||||||
let mut yolo: Option<YoloLoader> = None;
|
let mut yolo: Option<YoloLoader> = None;
|
||||||
|
let mut chunks: Option<ChunkLoader> = None;
|
||||||
let mut is_fullscreen = false;
|
let mut is_fullscreen = false;
|
||||||
|
|
||||||
if let Some(ref video_path) = config.video {
|
if let Some(ref video_path) = config.video {
|
||||||
@@ -111,6 +112,19 @@ fn run(config: &Config) -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(ref chunks_path) = config.chunks {
|
||||||
|
info!("Loading Chunks: {:?}", chunks_path);
|
||||||
|
match ChunkLoader::load(Path::new(chunks_path)) {
|
||||||
|
Ok(loader) => {
|
||||||
|
info!("Chunks loaded: {} scenes", loader.scene_count());
|
||||||
|
chunks = Some(loader);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("Failed to load Chunks: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut player_state = PlayerState::default();
|
let mut player_state = PlayerState::default();
|
||||||
if let Some(ref info) = video_info {
|
if let Some(ref info) = video_info {
|
||||||
player_state.total_frames = info.frame_count;
|
player_state.total_frames = info.frame_count;
|
||||||
@@ -510,6 +524,58 @@ fn run(config: &Config) -> Result<()> {
|
|||||||
progress_width,
|
progress_width,
|
||||||
progress_bar_height as u32,
|
progress_bar_height as u32,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
if player_state.show_chunks {
|
||||||
|
if let Some(ref chunk_loader) = chunks {
|
||||||
|
let bar_start = 10i32;
|
||||||
|
let bar_width = config.width as i32 - 20;
|
||||||
|
let boundaries = chunk_loader.get_scene_boundaries();
|
||||||
|
for &boundary_frame in &boundaries {
|
||||||
|
let ratio = boundary_frame as f64 / player_state.total_frames as f64;
|
||||||
|
let x_pos = (bar_start + (bar_width as f64 * ratio) as i32)
|
||||||
|
.min(bar_start + bar_width - 1);
|
||||||
|
if x_pos > bar_start && x_pos < bar_start + bar_width {
|
||||||
|
canvas.set_draw_color(sdl2::pixels::Color::RGB(255, 200, 50));
|
||||||
|
let _ = canvas.fill_rect(Rect::new(
|
||||||
|
x_pos,
|
||||||
|
progress_y - 2,
|
||||||
|
2,
|
||||||
|
(progress_bar_height + 4) as u32,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(current_scene) =
|
||||||
|
chunk_loader.get_current_scene(player_state.current_frame)
|
||||||
|
{
|
||||||
|
if let Some(ref font) = font {
|
||||||
|
let scene_text = format!("Scene {}", current_scene.scene_number);
|
||||||
|
if let Ok(surface) = font
|
||||||
|
.render(&scene_text)
|
||||||
|
.solid(sdl2::pixels::Color::RGB(255, 200, 50))
|
||||||
|
{
|
||||||
|
if let Ok(tex) =
|
||||||
|
texture_creator.create_texture_from_surface(&surface)
|
||||||
|
{
|
||||||
|
let rect = Rect::new(
|
||||||
|
bar_start + bar_width - surface.width() as i32 - 10,
|
||||||
|
progress_y - 25,
|
||||||
|
surface.width(),
|
||||||
|
surface.height(),
|
||||||
|
);
|
||||||
|
canvas.set_draw_color(sdl2::pixels::Color::RGBA(0, 0, 0, 180));
|
||||||
|
let _ = canvas.fill_rect(Rect::new(
|
||||||
|
rect.x() - 4,
|
||||||
|
rect.y() - 2,
|
||||||
|
rect.width() + 8,
|
||||||
|
rect.height() + 4,
|
||||||
|
));
|
||||||
|
canvas.copy(&tex, None, Some(rect)).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.present();
|
canvas.present();
|
||||||
|
|||||||
52
src/overlay/chunk.rs
Normal file
52
src/overlay/chunk.rs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
use anyhow::Context;
|
||||||
|
use log::info;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct CutData {
|
||||||
|
pub frame_count: u64,
|
||||||
|
pub fps: f64,
|
||||||
|
pub scenes: Vec<Scene>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
|
pub struct Scene {
|
||||||
|
pub scene_number: u32,
|
||||||
|
pub start_frame: u64,
|
||||||
|
pub end_frame: u64,
|
||||||
|
pub start_time: f64,
|
||||||
|
pub end_time: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ChunkLoader {
|
||||||
|
pub data: CutData,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChunkLoader {
|
||||||
|
pub fn load(path: &Path) -> anyhow::Result<Self> {
|
||||||
|
let content = fs::read_to_string(path)
|
||||||
|
.with_context(|| format!("Failed to read chunk file: {:?}", path))?;
|
||||||
|
let data: CutData = serde_json::from_str(&content)
|
||||||
|
.with_context(|| format!("Failed to parse chunk JSON: {:?}", path))?;
|
||||||
|
info!("Loaded {} scenes from {:?}", data.scenes.len(), path);
|
||||||
|
Ok(Self { data })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scene_count(&self) -> usize {
|
||||||
|
self.data.scenes.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_scene_boundaries(&self) -> Vec<u64> {
|
||||||
|
self.data.scenes.iter().map(|s| s.start_frame).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_current_scene(&self, frame: u64) -> Option<&Scene> {
|
||||||
|
self.data
|
||||||
|
.scenes
|
||||||
|
.iter()
|
||||||
|
.find(|s| frame >= s.start_frame && frame <= s.end_frame)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
//! Overlay module
|
//! Overlay module
|
||||||
//!
|
//!
|
||||||
//! ASR subtitle and YOLO bbox overlay management
|
//! ASR subtitle, YOLO bbox, and chunk marker overlay management
|
||||||
|
|
||||||
pub mod asr;
|
pub mod asr;
|
||||||
|
pub mod chunk;
|
||||||
pub mod yolo;
|
pub mod yolo;
|
||||||
|
|
||||||
pub use asr::AsrLoader;
|
pub use asr::AsrLoader;
|
||||||
|
pub use chunk::ChunkLoader;
|
||||||
pub use yolo::YoloLoader;
|
pub use yolo::YoloLoader;
|
||||||
|
|||||||
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,11 +1,12 @@
|
|||||||
/Users/accusys/momentry_playground/target/release/deps/momentry-d0e10ec51fcac34b.d: src/main.rs src/config.rs src/overlay/mod.rs src/overlay/asr.rs src/overlay/yolo.rs src/player/mod.rs src/player/ffmpeg.rs src/player/renderer.rs src/player/state.rs src/player/video.rs src/web/mod.rs src/web/bridge.rs
|
/Users/accusys/momentry_playground/target/release/deps/momentry-d0e10ec51fcac34b.d: src/main.rs src/config.rs src/overlay/mod.rs src/overlay/asr.rs src/overlay/chunk.rs src/overlay/yolo.rs src/player/mod.rs src/player/ffmpeg.rs src/player/renderer.rs src/player/state.rs src/player/video.rs src/web/mod.rs src/web/bridge.rs
|
||||||
|
|
||||||
/Users/accusys/momentry_playground/target/release/deps/momentry-d0e10ec51fcac34b: src/main.rs src/config.rs src/overlay/mod.rs src/overlay/asr.rs src/overlay/yolo.rs src/player/mod.rs src/player/ffmpeg.rs src/player/renderer.rs src/player/state.rs src/player/video.rs src/web/mod.rs src/web/bridge.rs
|
/Users/accusys/momentry_playground/target/release/deps/momentry-d0e10ec51fcac34b: src/main.rs src/config.rs src/overlay/mod.rs src/overlay/asr.rs src/overlay/chunk.rs src/overlay/yolo.rs src/player/mod.rs src/player/ffmpeg.rs src/player/renderer.rs src/player/state.rs src/player/video.rs src/web/mod.rs src/web/bridge.rs
|
||||||
|
|
||||||
src/main.rs:
|
src/main.rs:
|
||||||
src/config.rs:
|
src/config.rs:
|
||||||
src/overlay/mod.rs:
|
src/overlay/mod.rs:
|
||||||
src/overlay/asr.rs:
|
src/overlay/asr.rs:
|
||||||
|
src/overlay/chunk.rs:
|
||||||
src/overlay/yolo.rs:
|
src/overlay/yolo.rs:
|
||||||
src/player/mod.rs:
|
src/player/mod.rs:
|
||||||
src/player/ffmpeg.rs:
|
src/player/ffmpeg.rs:
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/Users/accusys/momentry_playground/target/release/deps/momentry_playground-f7686bde04eb7bb7.d: src/lib.rs src/player/mod.rs src/player/ffmpeg.rs src/player/renderer.rs src/player/state.rs src/player/video.rs src/overlay/mod.rs src/overlay/asr.rs src/overlay/yolo.rs src/web/mod.rs src/web/bridge.rs src/config.rs
|
/Users/accusys/momentry_playground/target/release/deps/momentry_playground-f7686bde04eb7bb7.d: src/lib.rs src/player/mod.rs src/player/ffmpeg.rs src/player/renderer.rs src/player/state.rs src/player/video.rs src/overlay/mod.rs src/overlay/asr.rs src/overlay/chunk.rs src/overlay/yolo.rs src/web/mod.rs src/web/bridge.rs src/config.rs
|
||||||
|
|
||||||
/Users/accusys/momentry_playground/target/release/deps/libmomentry_playground-f7686bde04eb7bb7.rlib: src/lib.rs src/player/mod.rs src/player/ffmpeg.rs src/player/renderer.rs src/player/state.rs src/player/video.rs src/overlay/mod.rs src/overlay/asr.rs src/overlay/yolo.rs src/web/mod.rs src/web/bridge.rs src/config.rs
|
/Users/accusys/momentry_playground/target/release/deps/libmomentry_playground-f7686bde04eb7bb7.rlib: src/lib.rs src/player/mod.rs src/player/ffmpeg.rs src/player/renderer.rs src/player/state.rs src/player/video.rs src/overlay/mod.rs src/overlay/asr.rs src/overlay/chunk.rs src/overlay/yolo.rs src/web/mod.rs src/web/bridge.rs src/config.rs
|
||||||
|
|
||||||
/Users/accusys/momentry_playground/target/release/deps/libmomentry_playground-f7686bde04eb7bb7.rmeta: src/lib.rs src/player/mod.rs src/player/ffmpeg.rs src/player/renderer.rs src/player/state.rs src/player/video.rs src/overlay/mod.rs src/overlay/asr.rs src/overlay/yolo.rs src/web/mod.rs src/web/bridge.rs src/config.rs
|
/Users/accusys/momentry_playground/target/release/deps/libmomentry_playground-f7686bde04eb7bb7.rmeta: src/lib.rs src/player/mod.rs src/player/ffmpeg.rs src/player/renderer.rs src/player/state.rs src/player/video.rs src/overlay/mod.rs src/overlay/asr.rs src/overlay/chunk.rs src/overlay/yolo.rs src/web/mod.rs src/web/bridge.rs src/config.rs
|
||||||
|
|
||||||
src/lib.rs:
|
src/lib.rs:
|
||||||
src/player/mod.rs:
|
src/player/mod.rs:
|
||||||
@@ -12,6 +12,7 @@ src/player/state.rs:
|
|||||||
src/player/video.rs:
|
src/player/video.rs:
|
||||||
src/overlay/mod.rs:
|
src/overlay/mod.rs:
|
||||||
src/overlay/asr.rs:
|
src/overlay/asr.rs:
|
||||||
|
src/overlay/chunk.rs:
|
||||||
src/overlay/yolo.rs:
|
src/overlay/yolo.rs:
|
||||||
src/web/mod.rs:
|
src/web/mod.rs:
|
||||||
src/web/bridge.rs:
|
src/web/bridge.rs:
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
/Users/accusys/momentry_playground/target/release/libmomentry_playground.rlib: /Users/accusys/momentry_playground/src/config.rs /Users/accusys/momentry_playground/src/lib.rs /Users/accusys/momentry_playground/src/overlay/asr.rs /Users/accusys/momentry_playground/src/overlay/mod.rs /Users/accusys/momentry_playground/src/overlay/yolo.rs /Users/accusys/momentry_playground/src/player/ffmpeg.rs /Users/accusys/momentry_playground/src/player/mod.rs /Users/accusys/momentry_playground/src/player/renderer.rs /Users/accusys/momentry_playground/src/player/state.rs /Users/accusys/momentry_playground/src/player/video.rs /Users/accusys/momentry_playground/src/web/bridge.rs /Users/accusys/momentry_playground/src/web/mod.rs
|
/Users/accusys/momentry_playground/target/release/libmomentry_playground.rlib: /Users/accusys/momentry_playground/src/config.rs /Users/accusys/momentry_playground/src/lib.rs /Users/accusys/momentry_playground/src/overlay/asr.rs /Users/accusys/momentry_playground/src/overlay/chunk.rs /Users/accusys/momentry_playground/src/overlay/mod.rs /Users/accusys/momentry_playground/src/overlay/yolo.rs /Users/accusys/momentry_playground/src/player/ffmpeg.rs /Users/accusys/momentry_playground/src/player/mod.rs /Users/accusys/momentry_playground/src/player/renderer.rs /Users/accusys/momentry_playground/src/player/state.rs /Users/accusys/momentry_playground/src/player/video.rs /Users/accusys/momentry_playground/src/web/bridge.rs /Users/accusys/momentry_playground/src/web/mod.rs
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
|||||||
/Users/accusys/momentry_playground/target/release/momentry: /Users/accusys/momentry_playground/src/config.rs /Users/accusys/momentry_playground/src/lib.rs /Users/accusys/momentry_playground/src/main.rs /Users/accusys/momentry_playground/src/overlay/asr.rs /Users/accusys/momentry_playground/src/overlay/mod.rs /Users/accusys/momentry_playground/src/overlay/yolo.rs /Users/accusys/momentry_playground/src/player/ffmpeg.rs /Users/accusys/momentry_playground/src/player/mod.rs /Users/accusys/momentry_playground/src/player/renderer.rs /Users/accusys/momentry_playground/src/player/state.rs /Users/accusys/momentry_playground/src/player/video.rs /Users/accusys/momentry_playground/src/web/bridge.rs /Users/accusys/momentry_playground/src/web/mod.rs
|
/Users/accusys/momentry_playground/target/release/momentry: /Users/accusys/momentry_playground/src/config.rs /Users/accusys/momentry_playground/src/lib.rs /Users/accusys/momentry_playground/src/main.rs /Users/accusys/momentry_playground/src/overlay/asr.rs /Users/accusys/momentry_playground/src/overlay/chunk.rs /Users/accusys/momentry_playground/src/overlay/mod.rs /Users/accusys/momentry_playground/src/overlay/yolo.rs /Users/accusys/momentry_playground/src/player/ffmpeg.rs /Users/accusys/momentry_playground/src/player/mod.rs /Users/accusys/momentry_playground/src/player/renderer.rs /Users/accusys/momentry_playground/src/player/state.rs /Users/accusys/momentry_playground/src/player/video.rs /Users/accusys/momentry_playground/src/web/bridge.rs /Users/accusys/momentry_playground/src/web/mod.rs
|
||||||
|
|||||||
Reference in New Issue
Block a user