52 lines
1.7 KiB
Rust
52 lines
1.7 KiB
Rust
use iced_video_player::Position;
|
|
use image::{DynamicImage, ImageFormat, RgbaImage};
|
|
use std::{error::Error, num::NonZero, path::Path, time::Duration};
|
|
use url::Url;
|
|
|
|
use super::video;
|
|
|
|
pub fn main(
|
|
input: &Url,
|
|
output: &Path,
|
|
size_opt: Option<(u32, u32)>,
|
|
) -> Result<(), Box<dyn Error>> {
|
|
let mut image = {
|
|
let thumbnails = {
|
|
let mut video = match video::new_video(input, video::VideoSettings { mute: true }) {
|
|
Ok(ok) => ok,
|
|
Err(_err) => return Err(Into::into(format!("missing required plugin"))),
|
|
};
|
|
|
|
let duration = video.duration();
|
|
//TODO: how best to decide time?
|
|
let position = if duration.as_secs_f64() < 20.0 {
|
|
// If less than 20 seconds, divide duration by 2
|
|
Position::Time(duration / 2)
|
|
} else {
|
|
// If more than 20 seconds, thumbnail at 10 seconds
|
|
Position::Time(Duration::new(10, 0))
|
|
};
|
|
video.thumbnails([position], NonZero::new(1).unwrap())?
|
|
};
|
|
// TODO: do not require clone of pixels data
|
|
match &thumbnails[0] {
|
|
cosmic::widget::image::Handle::Rgba {
|
|
id: _,
|
|
width,
|
|
height,
|
|
pixels,
|
|
} => RgbaImage::from_raw(*width, *height, pixels.to_vec())
|
|
.map(DynamicImage::ImageRgba8)
|
|
.ok_or_else(|| format!("failed to convert thumbnail")),
|
|
_ => Err(format!("unsupported thumbnail handle {:?}", thumbnails[0])),
|
|
}
|
|
}?;
|
|
|
|
if let Some((width, height)) = size_opt {
|
|
image = image.thumbnail(width, height);
|
|
}
|
|
|
|
image.save_with_format(output, ImageFormat::Png)?;
|
|
|
|
Ok(())
|
|
}
|