This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

1use super::Video; 2use crate::Timestamp; 3use crate::ui::{Log, Pretty}; 4use crate::video::encoders::Encoder; 5use crate::video::engine::{EngineControl, EngineController, EngineOutput}; 6use anyhow::{Result, anyhow}; 7use measure_time::debug_time; 8use std::path::PathBuf; 9use std::thread; 10 11impl<C: Default> Video<C> { 12 pub fn encode( 13 &mut self, 14 output_file: impl Into<PathBuf> + Clone, 15 ) -> Result<std::time::Duration> { 16 let actual_ms_range = self.constrained_ms_range(); 17 if actual_ms_range != self.total_ms_range() { 18 self.progress_bars.rendering.log( 19 "Constrained", 20 &Timestamp::from_ms_range(&actual_ms_range).pretty(), 21 ); 22 } 23 24 self.encode_controlled(output_file, &move |ctx| { 25 if actual_ms_range.contains(&ctx.ms) { 26 EngineControl::Render 27 } else if ctx.ms > actual_ms_range.end { 28 EngineControl::Stop 29 } else { 30 EngineControl::Skip 31 } 32 }) 33 } 34 35 pub fn encode_controlled( 36 &mut self, 37 output_file: impl Into<PathBuf> + Clone, 38 engine_controller: &EngineController<C>, 39 ) -> Result<std::time::Duration> { 40 debug_time!("encode"); 41 42 let encoder = self.setup_encoder(output_file.clone())?; 43 let encoder_name = encoder.name(); 44 45 let result = self.encode_with(encoder, engine_controller); 46 47 let _ = notify_rust::Notification::new() 48 .appname("Shapemaker") 49 .summary(&match result { 50 Ok(_) => format!("{} is ready", &output_file.into().pretty()), 51 Err(_) => format!("{} failed", &output_file.into().pretty()), 52 }) 53 .body(&match result { 54 Err(ref e) => format!("Encoding failed: {e}"), 55 Ok(time_taken) => format!( 56 "Encoded with {encoder_name} in {}", 57 time_taken.pretty() 58 ), 59 }) 60 .show(); 61 62 result 63 } 64 65 pub fn encode_with( 66 &mut self, 67 mut encoder: Box<dyn Encoder + Send>, 68 engine_controller: &EngineController<C>, 69 ) -> Result<std::time::Duration> { 70 debug_time!("encode_with"); 71 72 self.progress.remove(&self.progress_bars.loading); 73 74 let pb = self.progress_bars.encoding.clone(); 75 76 pb.set_length(self.ms_to_frames(self.duration_ms()) as _); 77 pb.set_message(""); 78 79 let (tx, rx) = std::sync::mpsc::sync_channel::<EngineOutput>(1_000); 80 81 let encoder_thread = 82 thread::spawn(move || -> Result<std::time::Duration> { 83 for output in rx.iter() { 84 match output { 85 EngineOutput::Finished => break, 86 EngineOutput::Frame { .. } => { 87 pb.inc(1); 88 pb.set_message(encoder.progress_message( 89 pb.position(), 90 pb.length().unwrap(), 91 )); 92 } 93 } 94 95 encoder.encode_frame(output)?; 96 } 97 98 let time_taken = pb.elapsed(); 99 let finish_message = encoder.finish_message(time_taken); 100 101 encoder.finish()?; 102 103 pb.finish(); 104 pb.log("Encoded", &finish_message); 105 106 Ok(time_taken) 107 }); 108 109 self.render(tx, engine_controller)?; 110 111 let time_taken = encoder_thread 112 .join() 113 .map_err(|e| anyhow!("Encoder thread panicked: {e:?}")) 114 .flatten()?; 115 116 let _ = self.progress.clear(); 117 118 Ok(time_taken) 119 } 120 121 #[allow(dead_code)] 122 fn add_audio_track(&mut self, _output_file: String) -> Result<()> { 123 todo!( 124 "Look into https://github.com/zmwangx/rust-ffmpeg/blob/master/examples/transcode-x264.rs and maybe contribute to video-rs (see https://github.com/oddity-ai/video-rs/issues/44)" 125 ); 126 } 127}