2
0
Fork 0
mirror of https://git.asonix.dog/asonix/pict-rs synced 2024-11-09 22:14:59 +00:00

Start introducing more video controls

This commit is contained in:
asonix 2022-09-25 17:36:07 -05:00
parent c9a74a73ca
commit c57a48db8a
6 changed files with 45 additions and 2 deletions

View file

@ -51,7 +51,9 @@ impl Args {
media_max_height, media_max_height,
media_max_area, media_max_area,
media_max_file_size, media_max_file_size,
media_max_frame_count,
media_enable_silent_video, media_enable_silent_video,
media_enable_full_video,
media_filters, media_filters,
media_format, media_format,
media_cache_duration, media_cache_duration,
@ -69,7 +71,9 @@ impl Args {
max_height: media_max_height, max_height: media_max_height,
max_area: media_max_area, max_area: media_max_area,
max_file_size: media_max_file_size, max_file_size: media_max_file_size,
max_frame_count: media_max_frame_count,
enable_silent_video: media_enable_silent_video, enable_silent_video: media_enable_silent_video,
enable_full_video: media_enable_full_video,
filters: media_filters, filters: media_filters,
format: media_format, format: media_format,
cache_duration: media_cache_duration, cache_duration: media_cache_duration,
@ -312,8 +316,12 @@ struct Media {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
max_file_size: Option<usize>, max_file_size: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
max_frame_count: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
enable_silent_video: Option<bool>, enable_silent_video: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
enable_full_video: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
filters: Option<Vec<String>>, filters: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
format: Option<ImageFormat>, format: Option<ImageFormat>,
@ -412,9 +420,15 @@ struct Run {
/// The maximum size, in megabytes, for uploaded media /// The maximum size, in megabytes, for uploaded media
#[clap(long)] #[clap(long)]
media_max_file_size: Option<usize>, media_max_file_size: Option<usize>,
/// Whether to enable GIF and silent MP4 uploads. Full videos are unsupported /// The maximum number of frames allowed for uploaded GIF and MP4s.
#[clap(long)]
media_max_frame_count: Option<usize>,
/// Whether to enable GIF and silent MP4 uploads
#[clap(long)] #[clap(long)]
media_enable_silent_video: Option<bool>, media_enable_silent_video: Option<bool>,
/// Whether to enable full MP4 uploads
#[clap(long)]
media_enable_full_video: Option<bool>,
/// Which media filters should be enabled on the `process` endpoint /// Which media filters should be enabled on the `process` endpoint
#[clap(long)] #[clap(long)]
media_filters: Option<Vec<String>>, media_filters: Option<Vec<String>>,

View file

@ -65,7 +65,9 @@ struct MediaDefaults {
max_height: usize, max_height: usize,
max_area: usize, max_area: usize,
max_file_size: usize, max_file_size: usize,
max_frame_count: usize,
enable_silent_video: bool, enable_silent_video: bool,
enable_full_video: bool,
filters: Vec<String>, filters: Vec<String>,
skip_validate_imports: bool, skip_validate_imports: bool,
cache_duration: i64, cache_duration: i64,
@ -150,7 +152,9 @@ impl Default for MediaDefaults {
max_height: 10_000, max_height: 10_000,
max_area: 40_000_000, max_area: 40_000_000,
max_file_size: 40, max_file_size: 40,
max_frame_count: 3_600,
enable_silent_video: true, enable_silent_video: true,
enable_full_video: false,
filters: vec![ filters: vec![
"blur".into(), "blur".into(),
"crop".into(), "crop".into(),

View file

@ -98,8 +98,12 @@ pub(crate) struct Media {
pub(crate) max_file_size: usize, pub(crate) max_file_size: usize,
pub(crate) max_frame_count: usize,
pub(crate) enable_silent_video: bool, pub(crate) enable_silent_video: bool,
pub(crate) enable_full_video: bool,
pub(crate) filters: BTreeSet<String>, pub(crate) filters: BTreeSet<String>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]

View file

@ -12,6 +12,7 @@ enum MaybeHumanDate {
pub(crate) struct Details { pub(crate) struct Details {
width: usize, width: usize,
height: usize, height: usize,
frames: Option<usize>,
content_type: Serde<mime::Mime>, content_type: Serde<mime::Mime>,
created_at: MaybeHumanDate, created_at: MaybeHumanDate,
} }
@ -33,6 +34,7 @@ impl Details {
details.width, details.width,
details.height, details.height,
details.mime_type, details.mime_type,
details.frames,
)) ))
} }
@ -48,13 +50,15 @@ impl Details {
details.width, details.width,
details.height, details.height,
details.mime_type, details.mime_type,
details.frames,
)) ))
} }
pub(crate) fn now(width: usize, height: usize, content_type: mime::Mime) -> Self { pub(crate) fn now(width: usize, height: usize, content_type: mime::Mime, frames: Option<usize>) -> Self {
Details { Details {
width, width,
height, height,
frames,
content_type: Serde::new(content_type), content_type: Serde::new(content_type),
created_at: MaybeHumanDate::HumanDate(time::OffsetDateTime::now_utc()), created_at: MaybeHumanDate::HumanDate(time::OffsetDateTime::now_utc()),
} }

View file

@ -99,6 +99,9 @@ pub(crate) enum UploadError {
#[error("Invalid media dimensions")] #[error("Invalid media dimensions")]
Dimensions, Dimensions,
#[error("Too many frames")]
Frames,
#[error("Unable to download image, bad response {0}")] #[error("Unable to download image, bad response {0}")]
Download(actix_web::http::StatusCode), Download(actix_web::http::StatusCode),

View file

@ -86,6 +86,7 @@ pub(crate) struct Details {
pub(crate) mime_type: mime::Mime, pub(crate) mime_type: mime::Mime,
pub(crate) width: usize, pub(crate) width: usize,
pub(crate) height: usize, pub(crate) height: usize,
pub(crate) frames: Option<usize>,
} }
#[tracing::instrument(name = "Clear Metadata", skip(input))] #[tracing::instrument(name = "Clear Metadata", skip(input))]
@ -210,6 +211,8 @@ pub(crate) async fn details_file(path_str: &str) -> Result<Details, Error> {
} }
fn parse_details(s: std::borrow::Cow<'_, str>) -> Result<Details, Error> { fn parse_details(s: std::borrow::Cow<'_, str>) -> Result<Details, Error> {
let frames = s.lines().count();
let mut lines = s.lines(); let mut lines = s.lines();
let first = lines.next().ok_or(UploadError::UnsupportedFormat)?; let first = lines.next().ok_or(UploadError::UnsupportedFormat)?;
@ -257,6 +260,11 @@ fn parse_details(s: std::borrow::Cow<'_, str>) -> Result<Details, Error> {
mime_type, mime_type,
width, width,
height, height,
frames: if frames > 1 {
Some(frames)
} else {
None
},
}) })
} }
@ -307,6 +315,12 @@ impl Details {
return Err(UploadError::Dimensions.into()); return Err(UploadError::Dimensions.into());
} }
if let Some(frames) = self.frames {
if frames > crate::CONFIG.media.max_frame_count {
return Err(UploadError::Frames.into());
}
}
let input_type = match (self.mime_type.type_(), self.mime_type.subtype()) { let input_type = match (self.mime_type.type_(), self.mime_type.subtype()) {
(mime::VIDEO, mime::MP4 | mime::MPEG) => ValidInputType::Mp4, (mime::VIDEO, mime::MP4 | mime::MPEG) => ValidInputType::Mp4,
(mime::IMAGE, mime::GIF) => ValidInputType::Gif, (mime::IMAGE, mime::GIF) => ValidInputType::Gif,