From c62b91fbb6537922cc4c3e68eb933c87cbc0bb0c Mon Sep 17 00:00:00 2001 From: Warren Lo Date: Thu, 19 Mar 2026 01:11:26 +0800 Subject: [PATCH] Update main.rs with complete implementation --- src/main.rs | 158 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 127 insertions(+), 31 deletions(-) diff --git a/src/main.rs b/src/main.rs index 23e8278..cc966c6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,38 +1,32 @@ -//! MoMentry Playground 主入口 +//! MoMentry Playground - Main entry point +//! +//! Unified media player with ASR/YOLO/Chunks overlay support use anyhow::Result; use clap::Parser; use log::{error, info}; +use std::path::Path; +mod config; +mod overlay; mod player; -mod ui; -mod viewer; -mod api; -mod input; +mod web; -use player::VideoPlayer; - -#[derive(Parser, Debug)] -#[command(name = "momentry")] -#[command(about = "MoMentry Playground - 統一播放、檢視、監控")] -struct Args { - #[arg(short, long, default_value = "800")] - width: u32, - - #[arg(short, long, default_value = "600")] - height: u32, - - #[arg(short, long)] - file: Option, -} +use config::Config; +use overlay::{AsrLoader, YoloLoader}; +use player::{Video, Renderer, PlaybackState}; +use player::state::PlayerState; fn main() -> Result<()> { - env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); + env_logger::Builder::from_env( + env_logger::Env::default().default_filter_or("info") + ).init(); - let args = Args::parse(); + let config = Config::load(); info!("MoMentry Playground starting..."); + info!("Window: {}x{}", config.width, config.height); - if let Err(e) = run(args) { + if let Err(e) = run(&config) { error!("Application error: {}", e); std::process::exit(1); } @@ -40,21 +34,123 @@ fn main() -> Result<()> { Ok(()) } -fn run(args: Args) -> Result<()> { - info!("Initializing window: {}x{}", args.width, args.height); - info!("Initializing video player..."); +fn run(config: &Config) -> Result<()> { + let mut video = Video::new(); + let mut renderer = Renderer::new("MoMentry Playground", config.width, config.height)?; - let mut player = VideoPlayer::new()?; + let mut asr: Option = None; + let mut yolo: Option = None; - if let Some(path) = args.file { - info!("Loading file: {}", path); - player.open(&path)?; - player.play()?; + if let Some(ref video_path) = config.video { + info!("Loading video: {:?}", video_path); + let info_data = video.open(video_path)?; + info!("Video info: {}x{} @ {:.2}fps, {} frames", + info_data.width, info_data.height, info_data.fps, info_data.total_frames); + + renderer.create_texture(info_data.width, info_data.height)?; + } + + if let Some(ref asr_path) = config.asr { + info!("Loading ASR: {:?}", asr_path); + match AsrLoader::load(asr_path) { + Ok(loader) => { + info!("ASR loaded: {} segments", loader.segment_count()); + asr = Some(loader); + } + Err(e) => { + error!("Failed to load ASR: {}", e); + } + } + } + + if let Some(ref yolo_path) = config.yolo { + info!("Loading YOLO: {:?}", yolo_path); + match YoloLoader::load(yolo_path) { + Ok(loader) => { + info!("YOLO loaded: {} frames", loader.total_frames()); + yolo = Some(loader); + } + Err(e) => { + error!("Failed to load YOLO: {}", e); + } + } + } + + if config.fullscreen { + renderer.set_fullscreen(true)?; + } + + let mut player_state = PlayerState::default(); + if let Some(info) = video.get_info() { + player_state.total_frames = info.total_frames; + player_state.duration_ms = info.duration_ms; + player_state.fps = info.fps; } info!("Main loop started - waiting for events..."); + if let Some(ref video_path) = config.video { + video.play()?; + player_state.playback = PlaybackState::Playing; + run_playback_loop(&mut video, &mut renderer, &mut player_state, &mut asr, &mut yolo)?; + } + loop { std::thread::sleep(std::time::Duration::from_millis(100)); } } + +fn run_playback_loop( + video: &mut Video, + renderer: &mut Renderer, + state: &mut PlayerState, + asr: &mut Option, + yolo: &mut Option, +) -> Result<()> { + let frame_duration = std::time::Duration::from_millis(16); + + loop { + let start = std::time::Instant::now(); + + match video.read_frame() { + Ok(Some(frame)) => { + state.current_frame = frame.frame_number; + state.current_time_ms = frame.timestamp_ms; + + renderer.update_texture(&frame.data)?; + + if state.show_yolo { + if let Some(ref mut yolo_loader) = yolo { + let detections = yolo_loader.get_detections(frame.frame_number); + for det in detections { + renderer.draw_bbox( + det.x1 as i32, + det.y1 as i32, + (det.x2 - det.x1) as u32, + (det.y2 - det.y1) as u32, + &det.class_name, + ); + } + } + } + + renderer.present(); + } + Ok(None) => { + info!("Playback ended"); + break; + } + Err(e) => { + error!("Frame read error: {}", e); + break; + } + } + + let elapsed = start.elapsed(); + if elapsed < frame_duration { + std::thread::sleep(frame_duration - elapsed); + } + } + + Ok(()) +}