Created
December 29, 2024 08:02
-
-
Save ilsubyeega/2e08867e3ed79d0268fc2455e098c629 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use mpv::FrameTimeInfo; | |
use std::process; | |
mod mpv; | |
const VIDEO_URL: &str = "/home/sob/Downloads/2024-12-09_23-11-21-00.22.12.245-00.22.40.000.mp4"; | |
#[tokio::main] | |
async fn main() { | |
// Arg parsing | |
let args = std::env::args().collect::<Vec<String>>(); | |
//if args.len() < 2 { | |
// println!("Usage: {} <url>", args[0]); | |
// return; | |
//} | |
let video_url = args.get(1).cloned() | |
.or_else(|| Some(String::from(VIDEO_URL))) | |
.unwrap(); | |
println!("Start time"); | |
let start_time = get_time_until_exit(&video_url).await; | |
println!("End time"); | |
let end_time = get_time_until_exit(&video_url).await; | |
println!("\n\ | |
# Result \n\ | |
- Start: {start_time:?} \n\ | |
- End: {end_time:?} | |
"); | |
// Run ffmpeg to cut the video | |
// ffmpeg -i input.mp4 -ss 00:00:00 -to 00:00:10 -c copy output.mp4 | |
process::Command::new("ffmpeg") | |
.args(["-i", &video_url]) | |
// Start time | |
.args(["-ss", &format!("{}s", start_time.time)]) | |
// End time | |
.args(["-to", &format!("{}s", end_time.time)]) | |
// Copy codec. ** No re-encoding but not precise timing. NEED TO INVESTIGATE ** | |
.args(["-c:v", "copy"]) // Video | |
.args(["-c:a", "copy"]) // Audio | |
// See https://ffmpeg.org/ffmpeg-formats.html | |
// make_zero: Shift timestamps so that the first timestamp is 0. | |
.args(["-avoid_negative_ts", "make_zero"]) | |
.arg("output.mp4") | |
.spawn() | |
.expect("Failed to execute ffmpeg"); | |
} | |
async fn get_time_until_exit(video_url: &str) -> FrameTimeInfo { | |
let mpv = mpv::Mpv::initialize(&"Pause the video and then exit to continue.").unwrap(); | |
mpv.load_file(video_url).unwrap(); | |
let mut event_context = mpv.get_event_context(); | |
let mut frametime = FrameTimeInfo::default(); | |
loop { | |
// Polling without delays | |
if let Some(result) = event_context.wait_event(0.0) { | |
match result { | |
Ok(libmpv2::events::Event::EndFile(_)) => { | |
println!("End of file"); | |
break; | |
} | |
Ok(e) => println!("Ok: {:?}", e), | |
Err(err) => println!("Error: {:?}", err), | |
} | |
} | |
// Retrive frameinfo and print it whether it's available or not. | |
let frame_time_info = mpv.get_frame_time_info(); | |
if let Ok(frame_time_info) = frame_time_info { | |
println!("{frame_time_info:?}"); | |
frametime = frame_time_info; | |
} | |
} | |
frametime | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub struct Mpv { | |
mpv: libmpv2::Mpv | |
} | |
#[derive(Debug)] | |
pub struct FrameTimeInfo { | |
/// Time in seconds. | |
pub time: f64, | |
/// Frame number. | |
pub frame_number: i64, | |
/// Total frame count of video. | |
pub frame_count: i64 | |
} | |
impl Default for FrameTimeInfo { | |
fn default() -> Self { | |
FrameTimeInfo { | |
time: 0.0, | |
frame_number: 0, | |
frame_count: 0 | |
} | |
} | |
} | |
impl Mpv { | |
/// Initialize mpv. | |
pub fn initialize(title: &str) -> Result<Mpv, libmpv2::Error> { | |
Ok(Mpv { | |
mpv: libmpv2::Mpv::with_initializer(|init| { | |
// Set Title | |
init.set_property("title", title)?; | |
// Enable mouse and keyboard control | |
init.set_property("osc", "yes")?; | |
init.set_property("input-default-bindings", "yes")?; | |
// Use precise seeking | |
init.set_property("hr-seek", "yes")?; | |
// Make window size 50% and 50%. | |
init.set_property("geometry", "50%x50%")?; | |
init.set_property("osd-msg1", title)?; | |
init.set_property("script-opts", "osc-layout=slimbox")?; | |
Ok(()) | |
})? | |
}) | |
} | |
/// Load a file into mpv. | |
pub fn load_file(&self, file: &str) -> Result<(), libmpv2::Error> { | |
self.mpv.command("loadfile", &[file, "append-play"]) | |
} | |
pub fn get_frame_time_info(&self) -> Result<FrameTimeInfo, libmpv2::Error> { | |
let time: f64 = self.mpv.get_property("time-pos/full")?; | |
let frame_number: i64 = self.mpv.get_property("estimated-frame-number")?; | |
let frame_count: i64 = self.mpv.get_property("estimated-frame-count")?; | |
Ok(FrameTimeInfo { | |
time, | |
frame_number, | |
frame_count | |
}) | |
} | |
pub fn get_event_context(&self) -> libmpv2::events::EventContext { | |
libmpv2::events::EventContext::new(self.mpv.ctx) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment