aboutsummaryrefslogtreecommitdiff
path: root/transcoder/src
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2023-09-30 22:19:19 +0200
committermetamuffin <metamuffin@disroot.org>2023-09-30 22:19:19 +0200
commitd546caa3f5053ade763430490911fefd6257af9f (patch)
tree5834ea5aa352239ab9a3f57ee96dee20af51ca77 /transcoder/src
parentc8fe73a7b160d4ada3136de9c87ad2eb0091ff7b (diff)
downloadjellything-d546caa3f5053ade763430490911fefd6257af9f.tar
jellything-d546caa3f5053ade763430490911fefd6257af9f.tar.bz2
jellything-d546caa3f5053ade763430490911fefd6257af9f.tar.zst
make cache async and fix parallel write bug
Diffstat (limited to 'transcoder/src')
-rw-r--r--transcoder/src/bin/reproduce_decode_error.rs4
-rw-r--r--transcoder/src/image.rs89
-rw-r--r--transcoder/src/lib.rs1
3 files changed, 52 insertions, 42 deletions
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;