2022-04-02 22:40:04 +00:00
|
|
|
use crate::{
|
|
|
|
concurrent_processor::CancelSafeProcessor,
|
|
|
|
config::ImageFormat,
|
|
|
|
details::Details,
|
|
|
|
error::Error,
|
2022-10-02 02:17:18 +00:00
|
|
|
ffmpeg::{ThumbnailFormat, VideoFormat},
|
2022-04-02 22:40:04 +00:00
|
|
|
repo::{Alias, FullRepo},
|
|
|
|
store::Store,
|
|
|
|
};
|
|
|
|
use actix_web::web::Bytes;
|
|
|
|
use std::path::PathBuf;
|
|
|
|
use tokio::io::AsyncReadExt;
|
2022-04-07 17:56:40 +00:00
|
|
|
use tracing::Instrument;
|
2022-04-02 22:40:04 +00:00
|
|
|
|
2022-10-01 01:02:46 +00:00
|
|
|
#[allow(clippy::too_many_arguments)]
|
2022-04-07 02:40:49 +00:00
|
|
|
#[tracing::instrument(skip(hash))]
|
2022-04-02 22:40:04 +00:00
|
|
|
pub(crate) async fn generate<R: FullRepo, S: Store + 'static>(
|
|
|
|
repo: &R,
|
|
|
|
store: &S,
|
|
|
|
format: ImageFormat,
|
|
|
|
alias: Alias,
|
|
|
|
thumbnail_path: PathBuf,
|
|
|
|
thumbnail_args: Vec<String>,
|
2022-10-02 02:17:18 +00:00
|
|
|
input_format: Option<VideoFormat>,
|
2022-10-01 00:38:11 +00:00
|
|
|
thumbnail_format: Option<ThumbnailFormat>,
|
2022-04-02 22:40:04 +00:00
|
|
|
hash: R::Bytes,
|
|
|
|
) -> Result<(Details, Bytes), Error> {
|
|
|
|
let process_fut = process(
|
|
|
|
repo,
|
|
|
|
store,
|
|
|
|
format,
|
|
|
|
alias,
|
|
|
|
thumbnail_path.clone(),
|
|
|
|
thumbnail_args,
|
2022-10-01 00:38:11 +00:00
|
|
|
input_format,
|
|
|
|
thumbnail_format,
|
2022-04-02 22:40:04 +00:00
|
|
|
hash.clone(),
|
|
|
|
);
|
|
|
|
|
|
|
|
let (details, bytes) =
|
|
|
|
CancelSafeProcessor::new(hash.as_ref(), thumbnail_path, process_fut).await?;
|
|
|
|
|
|
|
|
Ok((details, bytes))
|
|
|
|
}
|
|
|
|
|
2022-10-01 01:02:46 +00:00
|
|
|
#[allow(clippy::too_many_arguments)]
|
2022-04-07 02:40:49 +00:00
|
|
|
#[tracing::instrument(skip(hash))]
|
2022-04-02 22:40:04 +00:00
|
|
|
async fn process<R: FullRepo, S: Store + 'static>(
|
|
|
|
repo: &R,
|
|
|
|
store: &S,
|
|
|
|
format: ImageFormat,
|
|
|
|
alias: Alias,
|
|
|
|
thumbnail_path: PathBuf,
|
|
|
|
thumbnail_args: Vec<String>,
|
2022-10-02 02:17:18 +00:00
|
|
|
input_format: Option<VideoFormat>,
|
2022-10-01 00:38:11 +00:00
|
|
|
thumbnail_format: Option<ThumbnailFormat>,
|
2022-04-02 22:40:04 +00:00
|
|
|
hash: R::Bytes,
|
|
|
|
) -> Result<(Details, Bytes), Error> {
|
2022-04-07 17:56:40 +00:00
|
|
|
let permit = crate::PROCESS_SEMAPHORE.acquire().await;
|
2022-04-02 22:40:04 +00:00
|
|
|
|
|
|
|
let identifier = if let Some(identifier) = repo
|
|
|
|
.still_identifier_from_alias::<S::Identifier>(&alias)
|
|
|
|
.await?
|
|
|
|
{
|
|
|
|
identifier
|
|
|
|
} else {
|
|
|
|
let identifier = repo.identifier(hash.clone()).await?;
|
2022-09-24 22:18:53 +00:00
|
|
|
let reader = crate::ffmpeg::thumbnail(
|
2022-04-02 22:40:04 +00:00
|
|
|
store.clone(),
|
|
|
|
identifier,
|
2022-10-02 02:17:18 +00:00
|
|
|
input_format.unwrap_or(VideoFormat::Mp4),
|
2022-10-01 00:38:11 +00:00
|
|
|
thumbnail_format.unwrap_or(ThumbnailFormat::Jpeg),
|
2022-04-02 22:40:04 +00:00
|
|
|
)
|
|
|
|
.await?;
|
2022-09-24 22:18:53 +00:00
|
|
|
let motion_identifier = store.save_async_read(reader).await?;
|
2022-04-02 22:40:04 +00:00
|
|
|
|
|
|
|
repo.relate_motion_identifier(hash.clone(), &motion_identifier)
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
motion_identifier
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut processed_reader =
|
|
|
|
crate::magick::process_image_store_read(store.clone(), identifier, thumbnail_args, format)?;
|
|
|
|
|
|
|
|
let mut vec = Vec::new();
|
2022-04-07 17:56:40 +00:00
|
|
|
processed_reader
|
|
|
|
.read_to_end(&mut vec)
|
|
|
|
.instrument(tracing::info_span!("Reading processed image to vec"))
|
|
|
|
.await?;
|
2022-04-02 22:40:04 +00:00
|
|
|
let bytes = Bytes::from(vec);
|
|
|
|
|
|
|
|
drop(permit);
|
|
|
|
|
|
|
|
let details = Details::from_bytes(bytes.clone(), format.as_hint()).await?;
|
|
|
|
|
|
|
|
let identifier = store.save_bytes(bytes.clone()).await?;
|
|
|
|
repo.relate_details(&identifier, &details).await?;
|
|
|
|
repo.relate_variant_identifier(
|
|
|
|
hash,
|
|
|
|
thumbnail_path.to_string_lossy().to_string(),
|
|
|
|
&identifier,
|
|
|
|
)
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
Ok((details, bytes)) as Result<(Details, Bytes), Error>
|
|
|
|
}
|