adding an ffmpeg.rs and thumbnailing fn
This module adds a bg_from_video function that takes uses the ffmpeg binary to create thumbnails and adds them to the apps local data directory.
This commit is contained in:
parent
67d7f960ed
commit
529be1a519
3 changed files with 80 additions and 17 deletions
56
src/rust/ffmpeg.rs
Normal file
56
src/rust/ffmpeg.rs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
use dirs;
|
||||||
|
use std::fs;
|
||||||
|
use std::io::{self, Write};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::process::Command;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
pub fn bg_from_video(video: &Path) -> PathBuf {
|
||||||
|
let video = PathBuf::from(video);
|
||||||
|
println!("{:?}", video);
|
||||||
|
println!("{:?}", video.file_name());
|
||||||
|
let mut data_dir = dirs::data_local_dir().unwrap();
|
||||||
|
data_dir.push("librepresenter");
|
||||||
|
data_dir.push("thumbnails");
|
||||||
|
if !data_dir.exists() {
|
||||||
|
fs::create_dir(&data_dir).expect("Could not create thumbnails dir");
|
||||||
|
}
|
||||||
|
let mut screenshot = data_dir.clone();
|
||||||
|
screenshot.push(video.file_name().unwrap());
|
||||||
|
screenshot.set_extension("png");
|
||||||
|
if !screenshot.exists() {
|
||||||
|
let output_duration = Command::new("ffprobe")
|
||||||
|
.args(&["-i", &video.to_string_lossy()])
|
||||||
|
.output()
|
||||||
|
.expect("failed to execute ffprobe");
|
||||||
|
let mut duration = String::from("");
|
||||||
|
let mut at_second: i32;
|
||||||
|
at_second = 2;
|
||||||
|
let mut log = str::from_utf8(&output_duration.stdout)
|
||||||
|
.expect("Using non UTF-8 characters")
|
||||||
|
.to_string();
|
||||||
|
if let Some(duration_index) = &log.find("Duration") {
|
||||||
|
duration = log.split_off(*duration_index + 10);
|
||||||
|
duration.truncate(11);
|
||||||
|
println!("rust-duration-is: {duration}");
|
||||||
|
}
|
||||||
|
let output = Command::new("ffmpeg")
|
||||||
|
.args(&[
|
||||||
|
"-i",
|
||||||
|
&video.to_string_lossy(),
|
||||||
|
"-ss",
|
||||||
|
&at_second.to_string(),
|
||||||
|
"-vframes",
|
||||||
|
"1",
|
||||||
|
"-y",
|
||||||
|
&screenshot.to_string_lossy(),
|
||||||
|
])
|
||||||
|
.output()
|
||||||
|
.expect("failed to execute ffmpeg");
|
||||||
|
io::stdout().write_all(&output.stdout).unwrap();
|
||||||
|
io::stderr().write_all(&output.stderr).unwrap();
|
||||||
|
} else {
|
||||||
|
println!("Screenshot already exists");
|
||||||
|
}
|
||||||
|
screenshot
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub mod ffmpeg;
|
||||||
mod file_helper;
|
mod file_helper;
|
||||||
pub mod image_model;
|
pub mod image_model;
|
||||||
pub mod models;
|
pub mod models;
|
||||||
|
|
|
@ -124,26 +124,15 @@ mod slide_model {
|
||||||
|
|
||||||
// use crate::video_thumbnail;
|
// use crate::video_thumbnail;
|
||||||
// use image::{ImageBuffer, Rgba};
|
// use image::{ImageBuffer, Rgba};
|
||||||
|
use crate::ffmpeg;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
impl qobject::SlideyMod {
|
impl qobject::SlideyMod {
|
||||||
#[qinvokable]
|
pub fn video_thumbnail(mut self: Pin<&mut Self>, video: &QString) -> QString {
|
||||||
pub fn video_thumbnail(
|
|
||||||
mut self: Pin<&mut Self>,
|
|
||||||
video: QString,
|
|
||||||
service_item_id: i32,
|
|
||||||
index: i32,
|
|
||||||
) -> QString {
|
|
||||||
let video = video.to_string();
|
let video = video.to_string();
|
||||||
let mut path = PathBuf::from(video);
|
let path = PathBuf::from(video);
|
||||||
println!("{:?}", path);
|
let video = ffmpeg::bg_from_video(&path);
|
||||||
// let mut image_iter = video_thumbnail::ImageIter::new(path)?;
|
|
||||||
// image_iter.seek(2.0);
|
|
||||||
|
|
||||||
// if let Some(image) = image_iter.next() {
|
QString::from(video.to_str().unwrap())
|
||||||
// image.save("image.jpg");
|
|
||||||
// }
|
|
||||||
|
|
||||||
QString::default()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[qinvokable]
|
#[qinvokable]
|
||||||
|
@ -218,7 +207,16 @@ mod slide_model {
|
||||||
fn add_slide(mut self: Pin<&mut Self>, slide: &Slidey) {
|
fn add_slide(mut self: Pin<&mut Self>, slide: &Slidey) {
|
||||||
let index = self.as_ref().slides().len() as i32;
|
let index = self.as_ref().slides().len() as i32;
|
||||||
println!("{:?}", slide);
|
println!("{:?}", slide);
|
||||||
let slide = slide.clone();
|
let mut slide = slide.clone();
|
||||||
|
if !&slide.video_background.is_empty() {
|
||||||
|
slide.video_thumbnail = self
|
||||||
|
.as_mut()
|
||||||
|
.video_thumbnail(&slide.video_background)
|
||||||
|
.insert(0, &QString::from("file://"))
|
||||||
|
.to_owned();
|
||||||
|
println!("rust-inserted: {:?}", slide.video_thumbnail);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.as_mut()
|
self.as_mut()
|
||||||
.begin_insert_rows(&QModelIndex::default(), index, index);
|
.begin_insert_rows(&QModelIndex::default(), index, index);
|
||||||
|
@ -230,6 +228,14 @@ mod slide_model {
|
||||||
fn insert_slide(mut self: Pin<&mut Self>, slide: &Slidey, id: i32) {
|
fn insert_slide(mut self: Pin<&mut Self>, slide: &Slidey, id: i32) {
|
||||||
let mut slide = slide.clone();
|
let mut slide = slide.clone();
|
||||||
slide.slide_index = id;
|
slide.slide_index = id;
|
||||||
|
if !&slide.video_background.is_empty() {
|
||||||
|
slide.video_thumbnail = self
|
||||||
|
.as_mut()
|
||||||
|
.video_thumbnail(&slide.video_background)
|
||||||
|
.insert(0, &QString::from("file://"))
|
||||||
|
.to_owned();
|
||||||
|
println!("rust-inserted: {:?}", slide.video_thumbnail);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.as_mut()
|
self.as_mut()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue