diff options
author | metamuffin <metamuffin@disroot.org> | 2023-09-30 22:19:19 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-09-30 22:19:19 +0200 |
commit | d546caa3f5053ade763430490911fefd6257af9f (patch) | |
tree | 5834ea5aa352239ab9a3f57ee96dee20af51ca77 /transcoder | |
parent | c8fe73a7b160d4ada3136de9c87ad2eb0091ff7b (diff) | |
download | jellything-d546caa3f5053ade763430490911fefd6257af9f.tar jellything-d546caa3f5053ade763430490911fefd6257af9f.tar.bz2 jellything-d546caa3f5053ade763430490911fefd6257af9f.tar.zst |
make cache async and fix parallel write bug
Diffstat (limited to 'transcoder')
-rw-r--r-- | transcoder/Cargo.toml | 1 | ||||
-rw-r--r-- | transcoder/src/bin/reproduce_decode_error.rs | 4 | ||||
-rw-r--r-- | transcoder/src/image.rs | 89 | ||||
-rw-r--r-- | transcoder/src/lib.rs | 1 |
4 files changed, 53 insertions, 42 deletions
diff --git a/transcoder/Cargo.toml b/transcoder/Cargo.toml index e39b07c..ecb2bc8 100644 --- a/transcoder/Cargo.toml +++ b/transcoder/Cargo.toml @@ -18,3 +18,4 @@ rav1e = { version = "0.6.6", default-features = false, features = [ rayon = "1.8.0" imgref = "1.9.4" ravif = "0.11.3" +tokio = { workspace = true } diff --git a/transcoder/src/bin/reproduce_decode_error.rs b/transcoder/src/bin/reproduce_decode_error.rs index 84fa6fd..3e0ca3a 100644 --- a/transcoder/src/bin/reproduce_decode_error.rs +++ b/transcoder/src/bin/reproduce_decode_error.rs @@ -1,11 +1,13 @@ use jellytranscoder::image::transcode; -fn main() { +#[tokio::main] +async fn main() { transcode( jellycommon::AssetLocation::Cache(std::env::args().nth(2).unwrap().into()), 1.0, 1, 1, ) + .await .unwrap(); } diff --git a/transcoder/src/image.rs b/transcoder/src/image.rs index 6da1be7..3865348 100644 --- a/transcoder/src/image.rs +++ b/transcoder/src/image.rs @@ -1,53 +1,60 @@ use anyhow::Context; use image::{imageops::FilterType, ImageFormat}; -use jellybase::{cache_file, AssetLocationExt}; +use jellybase::{async_cache_file, AssetLocationExt}; use jellycommon::AssetLocation; use log::{debug, info}; use rgb::FromSlice; -use std::{ - fs::File, - io::{BufReader, Write}, - path::PathBuf, -}; +use std::{fs::File, io::BufReader}; +use tokio::io::AsyncWriteExt; -pub fn transcode( +pub async fn transcode( asset: AssetLocation, quality: f32, speed: u8, width: usize, -) -> anyhow::Result<PathBuf> { +) -> anyhow::Result<AssetLocation> { let original_path = asset.path(); - let path = cache_file(&[ - original_path.as_os_str().to_str().unwrap(), - &format!("{width} {quality} {speed}"), - ]) - .path(); - if !path.exists() { - info!("encoding {path:?} (speed={speed}, quality={quality}, width={width})"); - // TODO shouldn't be neccessary with guessed format. - let file = BufReader::new(File::open(&original_path).context("opening source")?); - let mut reader = image::io::Reader::new(file); - reader.set_format(ImageFormat::Avif); - let reader = reader.with_guessed_format().context("guessing format")?; - debug!("guessed format (or fallback): {:?}", reader.format()); - let original = reader.decode().context("decoding image")?.to_rgba8(); - let image = image::imageops::resize( - &original, - width as u32, - width as u32 * original.height() / original.width(), - FilterType::Lanczos3, - ); - let pixels = image.to_vec(); - let encoded = ravif::Encoder::new() - .with_speed(speed.clamp(1, 10)) - .with_quality(quality.clamp(1., 100.)) - .encode_rgba(imgref::Img::new( - pixels.as_rgba(), - image.width() as usize, - image.height() as usize, - ))?; - info!("transcode finished"); - File::create(&path)?.write_all(&encoded.avif_file)?; - } - Ok(path) + let asset = asset.clone(); + Ok(async_cache_file( + &[ + original_path.as_os_str().to_str().unwrap(), + &format!("{width} {quality} {speed}"), + ], + move |mut output| async move { + let encoded = tokio::task::spawn_blocking(move || { + let original_path = asset.path(); + info!( + "encoding {original_path:?} (speed={speed}, quality={quality}, width={width})" + ); + // TODO shouldn't be neccessary with guessed format. + let file = BufReader::new(File::open(&original_path).context("opening source")?); + let mut reader = image::io::Reader::new(file); + reader.set_format(ImageFormat::Avif); + let reader = reader.with_guessed_format().context("guessing format")?; + debug!("guessed format (or fallback): {:?}", reader.format()); + let original = reader.decode().context("decoding image")?.to_rgba8(); + let image = image::imageops::resize( + &original, + width as u32, + width as u32 * original.height() / original.width(), + FilterType::Lanczos3, + ); + let pixels = image.to_vec(); + let encoded = ravif::Encoder::new() + .with_speed(speed.clamp(1, 10)) + .with_quality(quality.clamp(1., 100.)) + .encode_rgba(imgref::Img::new( + pixels.as_rgba(), + image.width() as usize, + image.height() as usize, + ))?; + info!("transcode finished"); + Ok::<_, anyhow::Error>(encoded) + }) + .await??; + output.write_all(&encoded.avif_file).await?; + Ok(()) + }, + ) + .await?) } diff --git a/transcoder/src/lib.rs b/transcoder/src/lib.rs index e74a7f5..010a7dd 100644 --- a/transcoder/src/lib.rs +++ b/transcoder/src/lib.rs @@ -3,4 +3,5 @@ which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2023 metamuffin <metamuffin.org> */ +#![feature(async_closure)] pub mod image; |