diff options
author | metamuffin <metamuffin@disroot.org> | 2025-04-18 23:33:29 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-04-18 23:33:29 +0200 |
commit | a123a1997f3ab527ab83b44ca18bec94883f46d0 (patch) | |
tree | 761c4f0e8e9bbb7834e59af3d6904dee39932923 /transcoder/src | |
parent | 5b6fd021cc84ae7f5e1719ff398ff4627493a13c (diff) | |
download | jellything-a123a1997f3ab527ab83b44ca18bec94883f46d0.tar jellything-a123a1997f3ab527ab83b44ca18bec94883f46d0.tar.bz2 jellything-a123a1997f3ab527ab83b44ca18bec94883f46d0.tar.zst |
use impl Hash for cache key instead of string
Diffstat (limited to 'transcoder/src')
-rw-r--r-- | transcoder/src/fragment.rs | 120 | ||||
-rw-r--r-- | transcoder/src/image.rs | 14 | ||||
-rw-r--r-- | transcoder/src/thumbnail.rs | 41 |
3 files changed, 83 insertions, 92 deletions
diff --git a/transcoder/src/fragment.rs b/transcoder/src/fragment.rs index 88a311e..3e07ad7 100644 --- a/transcoder/src/fragment.rs +++ b/transcoder/src/fragment.rs @@ -3,7 +3,6 @@ which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2025 metamuffin <metamuffin.org> */ - use crate::LOCAL_VIDEO_TRANSCODING_TASKS; use jellybase::{ cache::{async_cache_file, CachePath}, @@ -21,78 +20,75 @@ use tokio::{ // TODO with an implementation that cant handle it (SVT-AV1 is such an impl). pub async fn transcode( - key: &str, kind: TrackKind, format: &StreamFormatInfo, + input_key: &str, input: impl FnOnce(ChildStdin), ) -> anyhow::Result<CachePath> { - async_cache_file( - &["frag-tc", key, &format!("{format:?}")], - move |mut output| async move { - let _permit = LOCAL_VIDEO_TRANSCODING_TASKS.acquire().await?; - debug!("transcoding fragment with {format:?}"); + let template = match format.codec.as_str() { + "V_MPEG4/ISO/AVC" => CONF.encoders.avc.as_ref(), + "V_MPEGH/ISO/HEVC" => CONF.encoders.hevc.as_ref(), + "V_VP8" => CONF.encoders.vp8.as_ref(), + "V_VP9" => CONF.encoders.vp9.as_ref(), + "V_AV1" => CONF.encoders.av1.as_ref(), + _ => None, + } + .or(CONF.encoders.generic.as_ref()) + .cloned() + .unwrap_or("ffmpeg %i %f %e %o".to_owned()); - let template = match format.codec.as_str() { - "V_MPEG4/ISO/AVC" => CONF.encoders.avc.as_ref(), - "V_MPEGH/ISO/HEVC" => CONF.encoders.hevc.as_ref(), - "V_VP8" => CONF.encoders.vp8.as_ref(), - "V_VP9" => CONF.encoders.vp9.as_ref(), - "V_AV1" => CONF.encoders.av1.as_ref(), - _ => None, - } - .or(CONF.encoders.generic.as_ref()) - .cloned() - .unwrap_or("ffmpeg %i %f %e %o".to_owned()); + let filter = match kind { + TrackKind::Video => format!("-vf scale={}:-1", format.width.unwrap()), + TrackKind::Audio => format!(""), + TrackKind::Subtitle => String::new(), + }; + let typechar = match kind { + TrackKind::Video => "v", + TrackKind::Audio => "a", + TrackKind::Subtitle => "s", + }; + let fallback_encoder = match format.codec.as_str() { + "A_OPUS" => "libopus", + "V_VP8" => "libvpx", + "V_VP9" => "libvpx-vp9", + "V_AV1" => "libaom", // svtav1 is x86 only :( + "V_MPEG4/ISO/AVC" => "libx264", + "V_MPEGH/ISO/HEVC" => "libx265", + _ => "", + }; - let filter = match kind { - TrackKind::Video => format!("-vf scale={}:-1", format.width.unwrap()), - TrackKind::Audio => format!(""), - TrackKind::Subtitle => String::new(), - }; - let typechar = match kind { - TrackKind::Video => "v", - TrackKind::Audio => "a", - TrackKind::Subtitle => "s", - }; - let fallback_encoder = match format.codec.as_str() { - "A_OPUS" => "libopus", - "V_VP8" => "libvpx", - "V_VP9" => "libvpx-vp9", - "V_AV1" => "libaom", // svtav1 is x86 only :( - "V_MPEG4/ISO/AVC" => "libx264", - "V_MPEGH/ISO/HEVC" => "libx265", - _ => "", - }; + let args = template + .replace("%i", "-f matroska -i pipe:0 -copyts") + .replace("%o", "-f matroska pipe:1") + .replace("%f", &filter) + .replace("%e", "-c:%t %c -b:%t %r") + .replace("%t", typechar) + .replace("%c", fallback_encoder) + .replace("%r", &(format.bitrate as i64).to_string()) + .replace(" ", " "); - let args = template - .replace("%i", "-f matroska -i pipe:0 -copyts") - .replace("%o", "-f matroska pipe:1") - .replace("%f", &filter) - .replace("%e", "-c:%t %c -b:%t %r") - .replace("%t", typechar) - .replace("%c", fallback_encoder) - .replace("%r", &(format.bitrate as i64).to_string()) - .replace(" ", " "); + async_cache_file("frag-tc", (input_key, &args), async |mut output| { + let _permit = LOCAL_VIDEO_TRANSCODING_TASKS.acquire().await?; + debug!("transcoding fragment with {format:?}"); - info!("encoding with {:?}", args); + info!("encoding with {:?}", args); - let mut args = args.split(" "); - let mut proc = Command::new(args.next().unwrap()) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .args(args) - .spawn()?; + let mut args = args.split(" "); + let mut proc = Command::new(args.next().unwrap()) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .args(args) + .spawn()?; - let stdin = proc.stdin.take().unwrap(); - let mut stdout = proc.stdout.take().unwrap(); + let stdin = proc.stdin.take().unwrap(); + let mut stdout = proc.stdout.take().unwrap(); - input(stdin); - copy(&mut stdout, &mut output).await?; + input(stdin); + copy(&mut stdout, &mut output).await?; - proc.wait().await.unwrap().exit_ok()?; - info!("done"); - Ok(()) - }, - ) + proc.wait().await.unwrap().exit_ok()?; + info!("done"); + Ok(()) + }) .await } diff --git a/transcoder/src/image.rs b/transcoder/src/image.rs index 28b253a..c6e1367 100644 --- a/transcoder/src/image.rs +++ b/transcoder/src/image.rs @@ -12,25 +12,23 @@ use rgb::FromSlice; use std::{ fs::File, io::{BufReader, Read, Seek, SeekFrom}, - path::PathBuf, + path::Path, }; use tokio::io::AsyncWriteExt; pub async fn transcode( - path: PathBuf, + path: &Path, quality: f32, speed: u8, width: usize, ) -> anyhow::Result<CachePath> { async_cache_file( - &[ - "image-tc", - path.clone().as_os_str().to_str().unwrap(), - &format!("{width} {quality} {speed}"), - ], - move |mut output| async move { + "image-tc", + (path, width, quality as i32, speed), + |mut output| async move { let _permit = LOCAL_IMAGE_TRANSCODING_TASKS.acquire().await?; info!("encoding {path:?} (speed={speed}, quality={quality}, width={width})"); + let path = path.to_owned(); let encoded = tokio::task::spawn_blocking(move || { let mut file = BufReader::new(File::open(&path).context("opening source")?); diff --git a/transcoder/src/thumbnail.rs b/transcoder/src/thumbnail.rs index c8bfb1c..caef397 100644 --- a/transcoder/src/thumbnail.rs +++ b/transcoder/src/thumbnail.rs @@ -5,30 +5,27 @@ use std::{path::Path, process::Stdio}; use tokio::{io::copy, process::Command}; pub async fn create_thumbnail(path: &Path, time: f64) -> anyhow::Result<CachePath> { - 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",); + async_cache_file("thumb", (path, time as i64), 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 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?; + let mut stdout = proc.stdout.take().unwrap(); + copy(&mut stdout, &mut output).await?; - proc.wait().await.unwrap().exit_ok()?; - info!("done"); - Ok(()) - }, - ) + proc.wait().await.unwrap().exit_ok()?; + info!("done"); + Ok(()) + }) .await } |