aboutsummaryrefslogtreecommitdiff
path: root/transcoder/src
diff options
context:
space:
mode:
Diffstat (limited to 'transcoder/src')
-rw-r--r--transcoder/src/lib.rs1
-rw-r--r--transcoder/src/thumbnail.rs35
2 files changed, 36 insertions, 0 deletions
diff --git a/transcoder/src/lib.rs b/transcoder/src/lib.rs
index d540e57..63d2cb8 100644
--- a/transcoder/src/lib.rs
+++ b/transcoder/src/lib.rs
@@ -10,6 +10,7 @@ use tokio::sync::Semaphore;
pub mod image;
pub mod snippet;
pub mod subtitles;
+pub mod thumbnail;
static LOCAL_IMAGE_TRANSCODING_TASKS: Semaphore = Semaphore::const_new(8);
static LOCAL_VIDEO_TRANSCODING_TASKS: Semaphore = Semaphore::const_new(2);
diff --git a/transcoder/src/thumbnail.rs b/transcoder/src/thumbnail.rs
new file mode 100644
index 0000000..5baf888
--- /dev/null
+++ b/transcoder/src/thumbnail.rs
@@ -0,0 +1,35 @@
+use crate::LOCAL_IMAGE_TRANSCODING_TASKS;
+use jellybase::cache::async_cache_file;
+use jellycommon::AssetLocation;
+use log::info;
+use std::{path::Path, process::Stdio};
+use tokio::{io::copy, process::Command};
+
+pub async fn create_thumbnail(path: &Path, time: f64) -> anyhow::Result<AssetLocation> {
+ Ok(async_cache_file(
+ &["thumb", path.to_str().unwrap(), &format!("{time}")],
+ move |mut output| async move {
+ let _permit = LOCAL_IMAGE_TRANSCODING_TASKS.acquire().await?;
+ info!("creating thumbnail of {path:?} at {time}s",);
+
+ let mut proc = Command::new("ffmpeg")
+ .stdout(Stdio::piped())
+ .args(&["-ss", &format!("{time}")])
+ .args(&["-f", "matroska", "-i", path.to_str().unwrap()])
+ .args(&["-frames:v", "1"])
+ .args(&["-c:v", "qoi"])
+ .args(&["-f", "image2"])
+ .args(&["-update", "1"])
+ .arg("pipe:1")
+ .spawn()?;
+
+ let mut stdout = proc.stdout.take().unwrap();
+ copy(&mut stdout, &mut output).await?;
+
+ proc.wait().await.unwrap().exit_ok()?;
+ info!("done");
+ Ok(())
+ },
+ )
+ .await?)
+}