From fe918433e8be9866c51dbc1f7ea99fb2be702524 Mon Sep 17 00:00:00 2001 From: TolaMironcenko Date: Sun, 15 Feb 2026 21:42:44 +0700 Subject: [PATCH] Update upload.rs --- src/api/upload.rs | 99 +++++++++++++++++++++++++++++++---------------- 1 file changed, 66 insertions(+), 33 deletions(-) diff --git a/src/api/upload.rs b/src/api/upload.rs index 47e9cf4..19fa701 100644 --- a/src/api/upload.rs +++ b/src/api/upload.rs @@ -259,47 +259,80 @@ enum FileType { // Function to extract duration from audio/video files async fn extract_duration(filepath: &str) -> Option { + use std::panic; use symphonia::core::io::MediaSourceStream; - let file = match std::fs::File::open(filepath) { - Ok(file) => file, - Err(_) => return None, - }; + // Wrap the Symphonia call in catch_unwind to prevent panics + let result = panic::catch_unwind(|| { + // Ensure the file is fully written before trying to read it + std::thread::sleep(std::time::Duration::from_millis(10)); - let mss = MediaSourceStream::new(Box::new(file), Default::default()); - - let mut hint = Hint::new(); - if let Some(ext) = Path::new(filepath).extension().and_then(|ext| ext.to_str()) { - hint.with_extension(ext); - } - - let format_opts = FormatOptions::default(); - let metadata_opts = MetadataOptions::default(); - - let probed = - match symphonia::default::get_probe().format(&hint, mss, &format_opts, &metadata_opts) { - Ok(probed) => probed, - Err(_) => return None, + // Open the file using std::fs::File to avoid async file issues with Symphonia + let file = match std::fs::File::open(filepath) { + Ok(file) => file, + Err(e) => { + eprintln!("Error opening media file: {}", e); + return None; + } }; - let track = match probed - .format - .tracks() - .iter() - .find(|t| t.codec_params.codec != symphonia::core::codecs::CODEC_TYPE_NULL) - { - Some(track) => track, - None => return None, - }; + // Create a MediaSourceStream with proper buffering + let mss = MediaSourceStream::new(Box::new(file), Default::default()); - let duration = track.codec_params.time_base.and_then(|tb| { - track - .codec_params - .n_frames - .and_then(|frames| Some(tb.calc_time(frames).seconds as f64)) + let mut hint = Hint::new(); + if let Some(ext) = Path::new(filepath).extension().and_then(|ext| ext.to_str()) { + hint.with_extension(ext); + } + + // Configure format options to be more permissive with EBML formats like WebM + let format_opts = FormatOptions { + enable_gapless: true, + ..Default::default() + }; + + let metadata_opts = MetadataOptions::default(); + + let probed = match symphonia::default::get_probe().format(&hint, mss, &format_opts, &metadata_opts) { + Ok(probed) => probed, + Err(e) => { + eprintln!("Error probing media file: {}", e); + return None; + } + }; + + // Try to get the duration from the format reader's capabilities + // Note: Symphonia doesn't have a direct duration() method, so we'll skip this approach + // and rely on track-based duration calculation + + // Fallback: try to get duration from track parameters + let track = match probed + .format + .tracks() + .iter() + .find(|t| t.codec_params.codec != symphonia::core::codecs::CODEC_TYPE_NULL) + { + Some(track) => track, + None => return None, + }; + + // Try to get duration from track's time base and frame count + let duration = track.codec_params.time_base.and_then(|tb| { + track + .codec_params + .n_frames + .and_then(|frames| Some(tb.calc_time(frames).seconds as f64)) + }); + + duration }); - duration + match result { + Ok(duration) => duration, + Err(panic_info) => { + eprintln!("Symphonia panic caught: {:?}", panic_info); + None + } + } } fn determine_file_type(content_type: &str, filename: &str) -> Option {