diff --git a/src/main.rs b/src/main.rs index a9384a3..64b0ad9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -171,18 +171,21 @@ async fn fetch_frame_as_image( input_path: &str, output_path: &str, frame_index: usize, + frame_rate: f64, // X/1sec ) -> anyhow::Result<()> { let frame_index_param = format!("select=eq(n\\,{})", frame_index); + let timeline_index: f64 = frame_index as f64 / frame_rate; + let timeline_index_param = format!("{:.5}", timeline_index); let builder = ffmpeg_cli::FfmpegBuilder::new() .stderr(Stdio::piped()) .option(Parameter::Single("nostdin")) .option(Parameter::Single("y")) - .input(ffmpeg_cli::File::new(input_path)) - .output( - ffmpeg_cli::File::new(output_path) - .option(Parameter::KeyValue("vf", &frame_index_param)) - .option(Parameter::KeyValue("vframes", "1")), - ); + // fast seeking with -ss instead of select filter + .input( + ffmpeg_cli::File::new(input_path) + .option(Parameter::KeyValue("ss", &timeline_index_param)), + ) + .output(ffmpeg_cli::File::new(output_path).option(Parameter::KeyValue("vframes", "1"))); log::debug!("running {:?}", builder); let ffmpeg = builder.run().await.unwrap(); @@ -259,36 +262,41 @@ async fn upload_file( let frame_rate_str = stream.r_frame_rate.clone(); let parts = frame_rate_str.split("/").into_iter().collect::>(); - let frame_rate = - parts.get(0).unwrap().parse::()? / parts.get(1).unwrap().parse::()?; + let frame_rate: f64 = + parts.get(0).unwrap().parse::()? / parts.get(1).unwrap().parse::()?; - let total_length_in_seconds = total_frame_count / frame_rate; - let wanted_frame_skip_seconds = match total_length_in_seconds { + let total_length_in_seconds = total_frame_count as f64 / frame_rate; + let wanted_frame_skip_seconds = match total_length_in_seconds as usize { 0..=10 => 2, 11..=60 => 10, 61..=120 => 15, - 121.. => 20, - }; - let wanted_frame_skip = (wanted_frame_skip_seconds * frame_rate).try_into().unwrap(); + 121..=300 => 20, + 301.. => 30, + _ => 33, + } as f64; + let wanted_frame_skip = wanted_frame_skip_seconds * frame_rate; let temporary_frame_dir = tempfile::tempdir()?; let temporary_frame_path = format!("{}/frame.png", temporary_frame_dir.path().to_string_lossy()); - log::info!("path: '{}'", &temporary_frame_path); + log::info!("frame path: '{}'", &temporary_frame_path); log::info!("wanted_frame_skip: {}", &wanted_frame_skip_seconds); - for frame_number in (0..total_frame_count).step_by(wanted_frame_skip) { + for frame_number in (0..total_frame_count).step_by(wanted_frame_skip as usize) { log::info!("extracting frame {:?}", frame_number); fetch_frame_as_image( temp_file.path().to_str().unwrap(), &temporary_frame_path, frame_number.try_into().unwrap(), + frame_rate, ) .await?; + log::info!("extracted frame {:?}", frame_number); let mut actual_frame_file = std::fs::File::open(&temporary_frame_path)?; let mut frame_data = vec![]; actual_frame_file.read_to_end(&mut frame_data)?; + log::info!("sending frame {:?}", frame_number); let tags_from_frame = if let WrappedResponse::Tags(tags_from_frame) = send_image_to_dd(frame_data, "amongus.png".to_string(), "image/png", &options) .await?