Merge branch 'master' into jul-18-mithoo

This commit is contained in:
Brandon Thomas authored and GitHub committed 2024-07-26 23:07:42 -04:00
commit 62e81a89dc
62 files changed
+899 -254

No files matched your search

Generated
+8
View File
@@ -2006,6 +2006,14 @@ dependencies = [
"chrono",
]
[[package]]
name = "dimensions"
version = "0.0.1"
dependencies = [
"errors",
"my-workspace-hack",
]
[[package]]
name = "displaydoc"
version = "0.2.4"
+1
View File
@@ -40,6 +40,7 @@ members = [
"crates/lib/deprecated/config", # TODO(bt, 2023-02-13): Deprecate or repurpose
"crates/lib/deprecated/container_common", # TODO(bt, 2023-02-13): Pull apart and rehome pieces
"crates/lib/deprecated/http_server_common", # TODO(bt, 2023-03-20): Move useful pieces to actix_helpers
"crates/lib/dimensions",
"crates/lib/easyenv", # NB: Vendored version of https://github.com/echelon/easyenv.rs that we'll improve.
"crates/lib/elasticsearch_schema",
"crates/lib/email_sender",
@@ -31,20 +31,10 @@ and m.created_at > (CURDATE() - INTERVAL 1 DAY)
and m.is_intermediate_system_file = false
and m.media_class = 'video'
and u.username NOT IN (
'bflat',
'candyfoxxx',
'crossproduct1',
'echelon',
'endtimes',
'heart_ribbon',
'kasisnu',
'mechacosm',
'moonchamp',
'olivicmic',
'printrman',
'vegito1089',
'wilwong',
'yae_ph'
'bflat', 'candyfoxxx', 'crossproduct1', 'echelon',
'endtimes', 'heart_ribbon', 'kasisnu', 'mechacosm',
'moonchamp', 'olivicmic', 'printrman', 'vegito1089',
'wilwong', 'yae_ph'
)
group by u.token
order by created_at desc;
+9 -2
View File
@@ -30,6 +30,7 @@ CREATE TABLE media_files (
-- * 'processed' for processed file (eg. mp3 encoding, stem splitting, etc.)
-- * 'upload' for direct user upload (from the filesystem)
-- * 'device_api' for direct user uploads recorded using Browser/Device APIs.
-- * 'studio' for storyteller studio jobs
origin_category VARCHAR(16) NOT NULL,
-- TODO(bt,2024-01-12): Rename to origin_product.
@@ -45,14 +46,18 @@ CREATE TABLE media_files (
-- Possible values:
-- * 'unknown' for legacy records without an associated product
-- * 'face_animator' for uploads and outputs
-- * 'face_mirror' for uploads and outputs
-- * 'vst' for uploads and outputs
-- * 'studio' for engine renders and outputs
-- * 'tts' for text to speech outputs
-- * 'voice_conversion' for uploads or outputs (RVC or SVC)
-- * 'zs_voice' for uploads or outputs for zero shot voice products
-- * 'video_filter' filters on videos
-- * 'mocap' for files uploaded or processed by motion capture
-- * 'image_gen' for image generation
origin_product_category VARCHAR(16) NOT NULL DEFAULT "unknown",
-- For inference that can be tied back to a model, the type of model.
-- DO NOT EXPOSE THIS TO USERS VIA THE API, as we may leak secrets in doing so.
-- * 'sad_talker', which doesn't have a value for maybe_origin_model_token (!!!)
-- * (more tome come)
maybe_origin_model_type VARCHAR(32) DEFAULT NULL,
@@ -95,7 +100,7 @@ CREATE TABLE media_files (
-- The token is a media file token.
maybe_style_transfer_source_media_file_token VARCHAR(32) DEFAULT NULL,
-- If this media file was generated generated by a scene from the engine, this is a link to that file.
-- If this media file was generated by a scene from the engine, this is a link to that file.
-- The token is a media file token.
maybe_scene_source_media_file_token VARCHAR(32) DEFAULT NULL,
@@ -131,12 +136,14 @@ CREATE TABLE media_files (
-- * 'dimensional' for a variety of 3d types
media_class VARCHAR(16) NOT NULL DEFAULT "unknown",
-- DEPRECATED / DO NOT USE. THIS FIELD IS NO LONGER RELEVANT.
-- A media file's possible subtype. Typically used for Storyteller Studio.
-- * 'mixamo' for mixamo animations (eg. for BVH, GLB, FBX, etc. files)
-- * 'mocap_net' for mocapnet animations (eg. for BVH files)
-- * 'scene'
-- * 'character'
-- * 'animation'
-- DO NOT USE THE `maybe_media_subtype` FIELD!
maybe_media_subtype VARCHAR(32) DEFAULT NULL,
-- The file's mime type.
@@ -28,6 +28,11 @@ pub enum MediaFileOriginCategory {
DeviceApi,
/// From Storyteller Studio Engine
#[serde(rename = "studio")]
StorytellerStudio,
/// From Storyteller Studio Engine
#[deprecated(note = "Use StorytellerStudio instead")]
StoryEngine,
}
@@ -44,6 +49,7 @@ impl MediaFileOriginCategory {
Self::Processed => "processed",
Self::Upload => "upload",
Self::DeviceApi => "device_api",
Self::StorytellerStudio => "studio",
Self::StoryEngine => "story_engine",
}
}
@@ -54,6 +60,7 @@ impl MediaFileOriginCategory {
"processed" => Ok(Self::Processed),
"upload" => Ok(Self::Upload),
"device_api" => Ok(Self::DeviceApi),
"studio" => Ok(Self::StorytellerStudio),
"story_engine" => Ok(Self::StoryEngine),
_ => Err(format!("invalid value: {:?}", value)),
}
@@ -67,6 +74,7 @@ impl MediaFileOriginCategory {
Self::Processed,
Self::Upload,
Self::DeviceApi,
Self::StorytellerStudio,
Self::StoryEngine,
])
}
@@ -86,6 +94,7 @@ mod tests {
assert_serialization(MediaFileOriginCategory::Processed, "processed");
assert_serialization(MediaFileOriginCategory::Upload, "upload");
assert_serialization(MediaFileOriginCategory::DeviceApi, "device_api");
assert_serialization(MediaFileOriginCategory::StorytellerStudio, "studio");
assert_serialization(MediaFileOriginCategory::StoryEngine, "story_engine");
}
@@ -95,6 +104,7 @@ mod tests {
assert_eq!(MediaFileOriginCategory::Processed.to_str(), "processed");
assert_eq!(MediaFileOriginCategory::Upload.to_str(), "upload");
assert_eq!(MediaFileOriginCategory::DeviceApi.to_str(), "device_api");
assert_eq!(MediaFileOriginCategory::StorytellerStudio.to_str(), "studio");
assert_eq!(MediaFileOriginCategory::StoryEngine.to_str(), "story_engine");
}
@@ -104,6 +114,7 @@ mod tests {
assert_eq!(MediaFileOriginCategory::from_str("processed").unwrap(), MediaFileOriginCategory::Processed);
assert_eq!(MediaFileOriginCategory::from_str("upload").unwrap(), MediaFileOriginCategory::Upload);
assert_eq!(MediaFileOriginCategory::from_str("device_api").unwrap(), MediaFileOriginCategory::DeviceApi);
assert_eq!(MediaFileOriginCategory::from_str("studio").unwrap(), MediaFileOriginCategory::StorytellerStudio);
assert_eq!(MediaFileOriginCategory::from_str("story_engine").unwrap(), MediaFileOriginCategory::StoryEngine);
assert!(MediaFileOriginCategory::from_str("foo").is_err());
}
@@ -111,11 +122,12 @@ mod tests {
#[test]
fn all_variants() {
let mut variants = MediaFileOriginCategory::all_variants();
assert_eq!(variants.len(), 5);
assert_eq!(variants.len(), 6);
assert_eq!(variants.pop_first(), Some(MediaFileOriginCategory::Inference));
assert_eq!(variants.pop_first(), Some(MediaFileOriginCategory::Processed));
assert_eq!(variants.pop_first(), Some(MediaFileOriginCategory::Upload));
assert_eq!(variants.pop_first(), Some(MediaFileOriginCategory::DeviceApi));
assert_eq!(variants.pop_first(), Some(MediaFileOriginCategory::StorytellerStudio));
assert_eq!(variants.pop_first(), Some(MediaFileOriginCategory::StoryEngine));
assert_eq!(variants.pop_first(), None);
}
@@ -15,6 +15,9 @@ use utoipa::ToSchema;
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum MediaFileOriginModelType {
#[serde(rename = "live_portrait")]
LivePortrait,
/// RVC (v2) voice conversion models
#[serde(rename = "rvc_v2")]
RvcV2,
@@ -30,18 +33,9 @@ pub enum MediaFileOriginModelType {
#[serde(rename = "tacotron2")]
Tacotron2,
#[serde(rename = "vall_e_x")]
VallEX,
#[serde(rename = "rerender")]
Rerender,
#[serde(rename = "mocap_net")]
MocapNet,
#[serde(rename = "comfy_ui")]
ComfyUi,
#[serde(rename = "styletts2")]
StyleTTS2,
@@ -50,6 +44,24 @@ pub enum MediaFileOriginModelType {
#[serde(rename = "gpt_sovits")]
GptSovits,
#[serde(rename = "studio")]
StorytellerStudio,
#[serde(rename = "vst")]
VideoStyleTransfer,
#[deprecated(note = "This is not a model type!")]
#[serde(rename = "comfy_ui")]
ComfyUi,
#[deprecated(note = "We don't use this anymore")]
#[serde(rename = "vall_e_x")]
VallEX,
#[deprecated(note = "We don't use this anymore")]
#[serde(rename = "rerender")]
Rerender,
}
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
@@ -61,33 +73,39 @@ impl_mysql_from_row!(MediaFileOriginModelType);
impl MediaFileOriginModelType {
pub fn to_str(&self) -> &'static str {
match self {
Self::LivePortrait => "live_portrait",
Self::RvcV2 => "rvc_v2",
Self::SadTalker => "sad_talker",
Self::SoVitsSvc => "so_vits_svc",
Self::Tacotron2 => "tacotron2",
Self::VallEX => "vall_e_x",
Self::Rerender => "rerender",
Self::MocapNet => "mocap_net",
Self::ComfyUi => "comfy_ui",
Self::StyleTTS2 => "styletts2",
Self::StableDiffusion15 => "stable_diffusion_1_5",
Self::GptSovits => "gpt_sovits",
Self::StorytellerStudio => "studio",
Self::VideoStyleTransfer => "vst",
Self::ComfyUi => "comfy_ui",
Self::VallEX => "vall_e_x",
Self::Rerender => "rerender",
}
}
pub fn from_str(value: &str) -> Result<Self, String> {
match value {
"live_portrait" => Ok(Self::LivePortrait),
"rvc_v2" => Ok(Self::RvcV2),
"sad_talker" => Ok(Self::SadTalker),
"so_vits_svc" => Ok(Self::SoVitsSvc),
"tacotron2" => Ok(Self::Tacotron2),
"vall_e_x" => Ok(Self::VallEX),
"rerender" => Ok(Self::Rerender),
"mocap_net" => Ok(Self::MocapNet),
"comfy_ui" => Ok(Self::ComfyUi),
"styletts2" => Ok(Self::StyleTTS2),
"stable_diffusion_1_5" => Ok(Self::StableDiffusion15),
"gpt_sovits" => Ok(Self::GptSovits),
"studio" => Ok(Self::StorytellerStudio),
"vst" => Ok(Self::VideoStyleTransfer),
"comfy_ui" => Ok(Self::ComfyUi),
"vall_e_x" => Ok(Self::VallEX),
"rerender" => Ok(Self::Rerender),
_ => Err(format!("invalid value: {:?}", value)),
}
}
@@ -96,17 +114,20 @@ impl MediaFileOriginModelType {
// NB: BTreeSet is sorted
// NB: BTreeSet::from() isn't const, but not worth using LazyStatic, etc.
BTreeSet::from([
Self::LivePortrait,
Self::RvcV2,
Self::SadTalker,
Self::SoVitsSvc,
Self::Tacotron2,
Self::VallEX,
Self::Rerender,
Self::MocapNet,
Self::ComfyUi,
Self::StyleTTS2,
Self::StableDiffusion15,
Self::GptSovits,
Self::StorytellerStudio,
Self::VideoStyleTransfer,
Self::ComfyUi,
Self::VallEX,
Self::Rerender,
])
}
}
@@ -126,50 +147,59 @@ mod tests {
#[test]
fn test_to_str() {
assert_eq!(MediaFileOriginModelType::LivePortrait.to_str(), "live_portrait");
assert_eq!(MediaFileOriginModelType::RvcV2.to_str(), "rvc_v2");
assert_eq!(MediaFileOriginModelType::SadTalker.to_str(), "sad_talker");
assert_eq!(MediaFileOriginModelType::SoVitsSvc.to_str(), "so_vits_svc");
assert_eq!(MediaFileOriginModelType::Tacotron2.to_str(), "tacotron2");
assert_eq!(MediaFileOriginModelType::VallEX.to_str(), "vall_e_x");
assert_eq!(MediaFileOriginModelType::Rerender.to_str(), "rerender");
assert_eq!(MediaFileOriginModelType::MocapNet.to_str(), "mocap_net");
assert_eq!(MediaFileOriginModelType::ComfyUi.to_str(), "comfy_ui");
assert_eq!(MediaFileOriginModelType::StyleTTS2.to_str(), "styletts2");
assert_eq!(MediaFileOriginModelType::StableDiffusion15.to_str(), "stable_diffusion_1_5");
assert_eq!(MediaFileOriginModelType::GptSovits.to_str(), "gpt_sovits");
assert_eq!(MediaFileOriginModelType::StorytellerStudio.to_str(), "studio");
assert_eq!(MediaFileOriginModelType::VideoStyleTransfer.to_str(), "vst");
assert_eq!(MediaFileOriginModelType::ComfyUi.to_str(), "comfy_ui");
assert_eq!(MediaFileOriginModelType::VallEX.to_str(), "vall_e_x");
assert_eq!(MediaFileOriginModelType::Rerender.to_str(), "rerender");
}
#[test]
fn test_from_str() {
assert_eq!(MediaFileOriginModelType::from_str("live_portrait").unwrap(), MediaFileOriginModelType::LivePortrait);
assert_eq!(MediaFileOriginModelType::from_str("rvc_v2").unwrap(), MediaFileOriginModelType::RvcV2);
assert_eq!(MediaFileOriginModelType::from_str("sad_talker").unwrap(), MediaFileOriginModelType::SadTalker);
assert_eq!(MediaFileOriginModelType::from_str("so_vits_svc").unwrap(), MediaFileOriginModelType::SoVitsSvc);
assert_eq!(MediaFileOriginModelType::from_str("tacotron2").unwrap(), MediaFileOriginModelType::Tacotron2);
assert_eq!(MediaFileOriginModelType::from_str("vall_e_x").unwrap(), MediaFileOriginModelType::VallEX);
assert_eq!(MediaFileOriginModelType::from_str("rerender").unwrap(), MediaFileOriginModelType::Rerender);
assert_eq!(MediaFileOriginModelType::from_str("mocap_net").unwrap(), MediaFileOriginModelType::MocapNet);
assert_eq!(MediaFileOriginModelType::from_str("comfy_ui").unwrap(), MediaFileOriginModelType::ComfyUi);
assert_eq!(MediaFileOriginModelType::from_str("styletts2").unwrap(), MediaFileOriginModelType::StyleTTS2);
assert_eq!(MediaFileOriginModelType::from_str("stable_diffusion_1_5").unwrap(), MediaFileOriginModelType::StableDiffusion15);
assert_eq!(MediaFileOriginModelType::from_str("gpt_sovits").unwrap(), MediaFileOriginModelType::GptSovits);
assert_eq!(MediaFileOriginModelType::from_str("studio").unwrap(), MediaFileOriginModelType::StorytellerStudio);
assert_eq!(MediaFileOriginModelType::from_str("vst").unwrap(), MediaFileOriginModelType::VideoStyleTransfer);
assert_eq!(MediaFileOriginModelType::from_str("comfy_ui").unwrap(), MediaFileOriginModelType::ComfyUi);
assert_eq!(MediaFileOriginModelType::from_str("vall_e_x").unwrap(), MediaFileOriginModelType::VallEX);
assert_eq!(MediaFileOriginModelType::from_str("rerender").unwrap(), MediaFileOriginModelType::Rerender);
assert!(MediaFileOriginModelType::from_str("foo").is_err());
}
#[test]
fn all_variants() {
let mut variants = MediaFileOriginModelType::all_variants();
assert_eq!(variants.len(), 11);
assert_eq!(variants.len(), 14);
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::LivePortrait));
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::RvcV2));
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::SadTalker));
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::SoVitsSvc));
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::Tacotron2));
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::VallEX));
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::Rerender));
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::MocapNet));
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::ComfyUi));
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::StyleTTS2));
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::StableDiffusion15));
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::GptSovits));
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::StorytellerStudio));
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::VideoStyleTransfer));
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::ComfyUi));
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::VallEX));
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::Rerender));
assert_eq!(variants.pop_first(), None);
}
}
@@ -192,5 +222,15 @@ mod tests {
assert_eq!(variant, MediaFileOriginModelType::from_str(&format!("{:?}", variant)).unwrap());
}
}
#[test]
fn serialized_length_ok_for_database() {
const MAX_LENGTH : usize = 32;
for variant in MediaFileOriginModelType::all_variants() {
let serialized = variant.to_str();
assert!(serialized.len() > 0, "variant {:?} is too short", variant);
assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant);
}
}
}
}
@@ -27,6 +27,18 @@ pub enum MediaFileOriginProductCategory {
#[serde(rename = "face_animator")]
FaceAnimator,
/// Media files created by Face Mirror (currently powered by Live Portrait)
#[serde(rename = "face_mirror")]
FaceMirror,
/// Video style transfer
#[serde(rename = "vst")]
VideoStyleTransfer,
/// Storyteller Studio
#[serde(rename = "studio")]
StorytellerStudio,
/// Text to speech (Tacotron2, not voice designer / VallE-X)
#[serde(rename = "tts")]
TextToSpeech,
@@ -39,17 +51,20 @@ pub enum MediaFileOriginProductCategory {
#[serde(rename = "zs_voice")]
ZeroShotVoice,
// Media files for video filters
#[serde(rename = "video_filter")]
VideoFilter,
// Mocap
#[serde(rename = "mocap")]
Mocap,
#[serde(rename = "image_gen")]
ImageGeneration,
// Media files for video filters
#[deprecated(note = "This isn't relevant product surface area anymore")]
#[serde(rename = "video_filter")]
VideoFilter,
// Workflow
#[deprecated(note = "Use studio and VST instead.")]
#[serde(rename = "workflow")]
Workflow,
}
@@ -65,12 +80,15 @@ impl MediaFileOriginProductCategory {
match self {
Self::Unknown => "unknown",
Self::FaceAnimator => "face_animator",
Self::FaceMirror => "face_mirror",
Self::VideoStyleTransfer => "vst",
Self::StorytellerStudio => "studio",
Self::TextToSpeech => "tts",
Self::VoiceConversion => "voice_conversion",
Self::ZeroShotVoice => "zs_voice",
Self::VideoFilter => "video_filter",
Self::Mocap => "mocap",
Self::ImageGeneration => "image_gen",
Self::VideoFilter => "video_filter",
Self::Workflow => "workflow",
}
}
@@ -79,12 +97,15 @@ impl MediaFileOriginProductCategory {
match value {
"unknown" => Ok(Self::Unknown),
"face_animator" => Ok(Self::FaceAnimator),
"face_mirror" => Ok(Self::FaceMirror),
"vst" => Ok(Self::VideoStyleTransfer),
"studio" => Ok(Self::StorytellerStudio),
"tts" => Ok(Self::TextToSpeech),
"voice_conversion" => Ok(Self::VoiceConversion),
"zs_voice" => Ok(Self::ZeroShotVoice),
"video_filter" => Ok(Self::VideoFilter),
"mocap" => Ok(Self::Mocap),
"image_gen" => Ok(Self::ImageGeneration),
"video_filter" => Ok(Self::VideoFilter),
"workflow" => Ok(Self::Workflow),
_ => Err(format!("invalid value: {:?}", value)),
}
@@ -96,12 +117,15 @@ impl MediaFileOriginProductCategory {
BTreeSet::from([
Self::Unknown,
Self::FaceAnimator,
Self::FaceMirror,
Self::VideoStyleTransfer,
Self::StorytellerStudio,
Self::TextToSpeech,
Self::VideoFilter,
Self::VoiceConversion,
Self::ZeroShotVoice,
Self::Mocap,
Self::ImageGeneration,
Self::VideoFilter,
Self::Workflow,
])
}
@@ -119,12 +143,15 @@ mod tests {
fn test_serialization() {
assert_serialization(MediaFileOriginProductCategory::Unknown, "unknown");
assert_serialization(MediaFileOriginProductCategory::FaceAnimator, "face_animator");
assert_serialization(MediaFileOriginProductCategory::FaceMirror, "face_mirror");
assert_serialization(MediaFileOriginProductCategory::VideoStyleTransfer, "vst");
assert_serialization(MediaFileOriginProductCategory::StorytellerStudio, "studio");
assert_serialization(MediaFileOriginProductCategory::TextToSpeech, "tts");
assert_serialization(MediaFileOriginProductCategory::VoiceConversion, "voice_conversion");
assert_serialization(MediaFileOriginProductCategory::ZeroShotVoice, "zs_voice");
assert_serialization(MediaFileOriginProductCategory::VideoFilter, "video_filter");
assert_serialization(MediaFileOriginProductCategory::Mocap, "mocap");
assert_serialization(MediaFileOriginProductCategory::ImageGeneration, "image_gen");
assert_serialization(MediaFileOriginProductCategory::VideoFilter, "video_filter");
assert_serialization(MediaFileOriginProductCategory::Workflow, "workflow");
}
@@ -132,12 +159,15 @@ mod tests {
fn to_str() {
assert_eq!(MediaFileOriginProductCategory::Unknown.to_str(), "unknown");
assert_eq!(MediaFileOriginProductCategory::FaceAnimator.to_str(), "face_animator");
assert_eq!(MediaFileOriginProductCategory::FaceMirror.to_str(), "face_mirror");
assert_eq!(MediaFileOriginProductCategory::VideoStyleTransfer.to_str(), "vst");
assert_eq!(MediaFileOriginProductCategory::StorytellerStudio.to_str(), "studio");
assert_eq!(MediaFileOriginProductCategory::TextToSpeech.to_str(), "tts");
assert_eq!(MediaFileOriginProductCategory::VoiceConversion.to_str(), "voice_conversion");
assert_eq!(MediaFileOriginProductCategory::ZeroShotVoice.to_str(), "zs_voice");
assert_eq!(MediaFileOriginProductCategory::VideoFilter.to_str(), "video_filter");
assert_eq!(MediaFileOriginProductCategory::Mocap.to_str(), "mocap");
assert_eq!(MediaFileOriginProductCategory::ImageGeneration.to_str(), "image_gen");
assert_eq!(MediaFileOriginProductCategory::VideoFilter.to_str(), "video_filter");
assert_eq!(MediaFileOriginProductCategory::Workflow.to_str(), "workflow");
}
@@ -145,27 +175,33 @@ mod tests {
fn from_str() {
assert_eq!(MediaFileOriginProductCategory::from_str("unknown").unwrap(), MediaFileOriginProductCategory::Unknown);
assert_eq!(MediaFileOriginProductCategory::from_str("face_animator").unwrap(), MediaFileOriginProductCategory::FaceAnimator);
assert_eq!(MediaFileOriginProductCategory::from_str("face_mirror").unwrap(), MediaFileOriginProductCategory::FaceMirror);
assert_eq!(MediaFileOriginProductCategory::from_str("vst").unwrap(), MediaFileOriginProductCategory::VideoStyleTransfer);
assert_eq!(MediaFileOriginProductCategory::from_str("studio").unwrap(), MediaFileOriginProductCategory::StorytellerStudio);
assert_eq!(MediaFileOriginProductCategory::from_str("tts").unwrap(), MediaFileOriginProductCategory::TextToSpeech);
assert_eq!(MediaFileOriginProductCategory::from_str("voice_conversion").unwrap(), MediaFileOriginProductCategory::VoiceConversion);
assert_eq!(MediaFileOriginProductCategory::from_str("zs_voice").unwrap(), MediaFileOriginProductCategory::ZeroShotVoice);
assert_eq!(MediaFileOriginProductCategory::from_str("video_filter").unwrap(), MediaFileOriginProductCategory::VideoFilter);
assert_eq!(MediaFileOriginProductCategory::from_str("mocap").unwrap(), MediaFileOriginProductCategory::Mocap);
assert_eq!(MediaFileOriginProductCategory::from_str("image_gen").unwrap(),MediaFileOriginProductCategory::ImageGeneration);
assert_eq!(MediaFileOriginProductCategory::from_str("video_filter").unwrap(), MediaFileOriginProductCategory::VideoFilter);
assert_eq!(MediaFileOriginProductCategory::from_str("workflow").unwrap(), MediaFileOriginProductCategory::Workflow);
}
#[test]
fn all_variants() {
let mut variants = MediaFileOriginProductCategory::all_variants();
assert_eq!(variants.len(), 9);
assert_eq!(variants.len(), 12);
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::Unknown));
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::FaceAnimator));
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::FaceMirror));
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::VideoStyleTransfer));
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::StorytellerStudio));
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::TextToSpeech));
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::VoiceConversion));
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::ZeroShotVoice));
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::VideoFilter));
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::Mocap));
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::ImageGeneration));
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::VideoFilter));
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::Workflow));
assert_eq!(variants.pop_first(), None);
}
@@ -188,5 +224,15 @@ mod tests {
assert_eq!(variant, MediaFileOriginProductCategory::from_str(&format!("{:?}", variant)).unwrap());
}
}
#[test]
fn serialized_length_ok_for_database() {
const MAX_LENGTH : usize = 16;
for variant in MediaFileOriginProductCategory::all_variants() {
let serialized = variant.to_str();
assert!(serialized.len() > 0, "variant {:?} is too short", variant);
assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant);
}
}
}
}
@@ -14,7 +14,12 @@ use utoipa::ToSchema;
#[cfg_attr(test, derive(EnumIter, EnumCount))]
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema)]
#[serde(rename_all = "snake_case")]
#[deprecated(note = "This was primarily for Bevy")]
pub enum MediaFileSubtype {
/// NB: MediaFileSubtype is deprecated.
/// This should signal that the field / enum is fully deprecated.
Deprecated,
// TODO(bt,2024-04-22): Deprecated (migrate)
/// Animation file from Mixamo
/// Primarily used for FBX and GLB.
@@ -65,6 +70,7 @@ impl_mysql_from_row!(MediaFileSubtype);
impl MediaFileSubtype {
pub fn to_str(&self) -> &'static str {
match self {
Self::Deprecated => "deprecated",
Self::Mixamo => "mixamo",
Self::MocapNet => "mocap_net",
Self::AnimationOnly => "animation_only",
@@ -80,6 +86,7 @@ impl MediaFileSubtype {
pub fn from_str(value: &str) -> Result<Self, String> {
match value {
"deprecated" => Ok(Self::Deprecated),
"mixamo" => Ok(Self::Mixamo),
"mocap_net" => Ok(Self::MocapNet),
"animation_only" => Ok(Self::AnimationOnly),
@@ -98,6 +105,7 @@ impl MediaFileSubtype {
// NB: BTreeSet is sorted
// NB: BTreeSet::from() isn't const, but not worth using LazyStatic, etc.
BTreeSet::from([
Self::Deprecated,
Self::Mixamo,
Self::MocapNet,
Self::AnimationOnly,
@@ -122,6 +130,7 @@ mod tests {
#[test]
fn test_serialization() {
assert_serialization(MediaFileSubtype::Deprecated, "deprecated");
assert_serialization(MediaFileSubtype::Mixamo, "mixamo");
assert_serialization(MediaFileSubtype::MocapNet, "mocap_net");
assert_serialization(MediaFileSubtype::AnimationOnly, "animation_only");
@@ -136,6 +145,7 @@ mod tests {
#[test]
fn test_to_str() {
assert_eq!(MediaFileSubtype::Deprecated.to_str(), "deprecated");
assert_eq!(MediaFileSubtype::Mixamo.to_str(), "mixamo");
assert_eq!(MediaFileSubtype::MocapNet.to_str(), "mocap_net");
assert_eq!(MediaFileSubtype::AnimationOnly.to_str(), "animation_only");
@@ -150,6 +160,7 @@ mod tests {
#[test]
fn test_from_str() {
assert_eq!(MediaFileSubtype::from_str("deprecated").unwrap(), MediaFileSubtype::Deprecated);
assert_eq!(MediaFileSubtype::from_str("mixamo").unwrap(), MediaFileSubtype::Mixamo);
assert_eq!(MediaFileSubtype::from_str("mocap_net").unwrap(), MediaFileSubtype::MocapNet);
assert_eq!(MediaFileSubtype::from_str("animation_only").unwrap(), MediaFileSubtype::AnimationOnly);
@@ -166,7 +177,8 @@ mod tests {
#[test]
fn all_variants() {
let mut variants = MediaFileSubtype::all_variants();
assert_eq!(variants.len(), 10);
assert_eq!(variants.len(), 11);
assert_eq!(variants.pop_first(), Some(MediaFileSubtype::Deprecated));
assert_eq!(variants.pop_first(), Some(MediaFileSubtype::Mixamo));
assert_eq!(variants.pop_first(), Some(MediaFileSubtype::MocapNet));
assert_eq!(variants.pop_first(), Some(MediaFileSubtype::AnimationOnly));
@@ -22,6 +22,10 @@ pub enum UserFeatureFlag {
/// Access to studio features
Studio,
/// Whether users are allowed to upload 3D models
#[serde(rename = "upload_3d")]
Upload3d,
/// Access to video style transfer
VideoStyleTransfer,
}
@@ -37,6 +41,7 @@ impl UserFeatureFlag {
match self {
Self::ExploreMedia => "explore_media",
Self::Studio => "studio",
Self::Upload3d => "upload_3d",
Self::VideoStyleTransfer => "video_style_transfer",
}
}
@@ -45,6 +50,7 @@ impl UserFeatureFlag {
match value {
"explore_media" => Ok(Self::ExploreMedia),
"studio" => Ok(Self::Studio),
"upload_3d" => Ok(Self::Upload3d),
"video_style_transfer" => Ok(Self::VideoStyleTransfer),
_ => Err(format!("invalid value: {:?}", value)),
}
@@ -56,6 +62,7 @@ impl UserFeatureFlag {
BTreeSet::from([
Self::ExploreMedia,
Self::Studio,
Self::Upload3d,
Self::VideoStyleTransfer,
])
}
@@ -73,6 +80,7 @@ mod tests {
fn test_serialization() {
assert_serialization(UserFeatureFlag::ExploreMedia, "explore_media");
assert_serialization(UserFeatureFlag::Studio, "studio");
assert_serialization(UserFeatureFlag::Upload3d, "upload_3d");
assert_serialization(UserFeatureFlag::VideoStyleTransfer, "video_style_transfer");
}
@@ -80,6 +88,7 @@ mod tests {
fn test_to_str() {
assert_eq!(UserFeatureFlag::ExploreMedia.to_str(), "explore_media");
assert_eq!(UserFeatureFlag::Studio.to_str(), "studio");
assert_eq!(UserFeatureFlag::Upload3d.to_str(), "upload_3d");
assert_eq!(UserFeatureFlag::VideoStyleTransfer.to_str(), "video_style_transfer");
}
@@ -87,6 +96,7 @@ mod tests {
fn test_from_str() {
assert_eq!(UserFeatureFlag::from_str("explore_media").unwrap(), UserFeatureFlag::ExploreMedia);
assert_eq!(UserFeatureFlag::from_str("studio").unwrap(), UserFeatureFlag::Studio);
assert_eq!(UserFeatureFlag::from_str("upload_3d").unwrap(), UserFeatureFlag::Upload3d);
assert_eq!(UserFeatureFlag::from_str("video_style_transfer").unwrap(), UserFeatureFlag::VideoStyleTransfer);
assert!(UserFeatureFlag::from_str("foo").is_err());
}
@@ -94,9 +104,10 @@ mod tests {
#[test]
fn all_variants() {
let mut variants = UserFeatureFlag::all_variants();
assert_eq!(variants.len(), 3);
assert_eq!(variants.len(), 4);
assert_eq!(variants.pop_first(), Some(UserFeatureFlag::ExploreMedia));
assert_eq!(variants.pop_first(), Some(UserFeatureFlag::Studio));
assert_eq!(variants.pop_first(), Some(UserFeatureFlag::Upload3d));
assert_eq!(variants.pop_first(), Some(UserFeatureFlag::VideoStyleTransfer));
assert_eq!(variants.pop_first(), None);
}
+2 -1
View File
@@ -1,2 +1,3 @@
pub mod premium_product;
pub mod style_transfer;
pub mod style_transfer;
pub mod video_dimensions;
@@ -0,0 +1 @@
mod video_dimensions;
@@ -0,0 +1,117 @@
use std::collections::BTreeSet;
#[cfg(test)]
use strum::EnumCount;
#[cfg(test)]
use strum::EnumIter;
use utoipa::ToSchema;
/// This enum is not backed by a particular database table.
/// This is used to determine the video generation size.
#[cfg_attr(test, derive(EnumIter, EnumCount))]
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum VideoDimensions {
Landscape,
Portrait,
Square,
}
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
impl_enum_display_and_debug_using_to_str!(VideoDimensions);
//impl_mysql_enum_coders!(VideoDimensions);
//impl_mysql_from_row!(VideoDimensions);
/// NB: Legacy API for older code.
impl VideoDimensions {
pub fn to_str(&self) -> &'static str {
match self {
Self::Landscape => "landscape",
Self::Portrait => "portrait",
Self::Square => "square",
}
}
pub fn from_str(value: &str) -> Result<Self, String> {
match value {
"landscape" => Ok(Self::Landscape),
"portrait" => Ok(Self::Portrait),
"square" => Ok(Self::Square),
_ => Err(format!("Unknown VideoDimensions: {}", value)),
}
}
pub fn all_variants() -> BTreeSet<Self> {
// NB: BTreeSet is sorted
// NB: BTreeSet::from() isn't const, but not worth using LazyStatic, etc.
BTreeSet::from([
Self::Landscape,
Self::Portrait,
Self::Square,
])
}
}
#[cfg(test)]
mod tests {
use crate::no_table::video_dimensions::video_dimensions::VideoDimensions;
use crate::test_helpers::assert_serialization;
mod serde {
use super::*;
#[test]
fn test_serialization() {
assert_serialization(VideoDimensions::Landscape, "landscape");
assert_serialization(VideoDimensions::Portrait, "portrait");
assert_serialization(VideoDimensions::Square, "square");
}
mod impl_methods {
use super::*;
#[test]
fn to_str() {
assert_eq!(VideoDimensions::Landscape.to_str(), "landscape");
assert_eq!(VideoDimensions::Portrait.to_str(), "portrait");
assert_eq!(VideoDimensions::Square.to_str(), "square");
}
#[test]
fn from_str() {
assert_eq!(VideoDimensions::from_str("landscape").unwrap(), VideoDimensions::Landscape);
assert_eq!(VideoDimensions::from_str("portrait").unwrap(), VideoDimensions::Portrait);
assert_eq!(VideoDimensions::from_str("square").unwrap(), VideoDimensions::Square);
}
}
mod manual_variant_checks {
use super::*;
#[test]
fn all_variants() {
let variants = VideoDimensions::all_variants();
assert_eq!(variants.len(), 3);
}
}
mod mechanical_checks {
use super::*;
#[test]
fn variant_length() {
use strum::IntoEnumIterator;
assert_eq!(VideoDimensions::all_variants().len(), VideoDimensions::iter().len());
}
#[test]
fn round_trip() {
for variant in VideoDimensions::all_variants() {
assert_eq!(variant, VideoDimensions::from_str(variant.to_str()).unwrap());
assert_eq!(variant, VideoDimensions::from_str(&format!("{}", variant)).unwrap());
assert_eq!(variant, VideoDimensions::from_str(&format!("{:?}", variant)).unwrap());
}
}
}
}
}
@@ -0,0 +1 @@
pub mod public_media_file_model_type;
@@ -0,0 +1,228 @@
use serde::Deserialize;
use serde::Serialize;
#[cfg(test)]
use strum::EnumCount;
#[cfg(test)]
use strum::EnumIter;
use utoipa::ToSchema;
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
/// Report certain models publicly as different from what we actually use.
/// This is so we have an edge against the competition that might try to run
/// the same models. This won't always make sense, but in some cases it will.
#[cfg_attr(test, derive(EnumIter, EnumCount))]
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, Debug)]
#[serde(rename_all = "snake_case")]
pub enum PublicMediaFileModelType {
// Renamed enum variants
/// Instead of `MediaFileOriginModelType::LivePortrait` ("live_portrait")
#[serde(rename = "face_mirror")]
FaceMirror,
/// Instead of `MediaFileOriginModelType::SadTalker` ("sad_talker")
#[serde(rename = "face_animator")]
FaceAnimator,
/// Instead of `MediaFileOriginModelType::StyleTTS2` ("styletts2")
#[serde(rename = "voice_designer")]
VoiceDesigner,
// Everything else is the same
/// RVC (v2) voice conversion models
#[serde(rename = "rvc_v2")]
RvcV2,
/// so-vits-svc voice conversion models
#[serde(rename = "so_vits_svc")]
SoVitsSvc,
#[serde(rename = "tacotron2")]
Tacotron2,
#[serde(rename = "mocap_net")]
MocapNet,
#[serde(rename = "stable_diffusion_1_5")]
StableDiffusion15,
#[serde(rename = "studio")]
StorytellerStudio,
#[serde(rename = "vst")]
VideoStyleTransfer,
#[deprecated(note = "This is not a model type!")]
#[serde(rename = "comfy_ui")]
ComfyUi,
#[deprecated(note = "We don't use this anymore")]
#[serde(rename = "vall_e_x")]
VallEX,
#[deprecated(note = "We don't use this anymore")]
#[serde(rename = "rerender")]
Rerender,
}
/// NB: Legacy API for older code.
impl PublicMediaFileModelType {
pub fn from_enum(model_type: MediaFileOriginModelType) -> Self {
match model_type {
// Renamed variants
MediaFileOriginModelType::LivePortrait => Self::FaceMirror,
MediaFileOriginModelType::SadTalker => Self::FaceAnimator,
MediaFileOriginModelType::StyleTTS2 => Self::VoiceDesigner,
// Conserved variants
MediaFileOriginModelType::RvcV2 => Self::RvcV2,
MediaFileOriginModelType::SoVitsSvc => Self::SoVitsSvc,
MediaFileOriginModelType::Tacotron2 => Self::Tacotron2,
MediaFileOriginModelType::MocapNet => Self::MocapNet,
MediaFileOriginModelType::StableDiffusion15 => Self::StableDiffusion15,
MediaFileOriginModelType::StorytellerStudio => Self::StorytellerStudio,
MediaFileOriginModelType::VideoStyleTransfer => Self::VideoStyleTransfer,
MediaFileOriginModelType::ComfyUi => Self::ComfyUi,
MediaFileOriginModelType::VallEX => Self::VallEX,
MediaFileOriginModelType::Rerender => Self::Rerender,
}
}
pub fn to_enum(&self) -> MediaFileOriginModelType {
match self {
// Renamed variants
PublicMediaFileModelType::FaceMirror => MediaFileOriginModelType::LivePortrait,
PublicMediaFileModelType::FaceAnimator => MediaFileOriginModelType::SadTalker,
PublicMediaFileModelType::VoiceDesigner => MediaFileOriginModelType::StyleTTS2,
// Conserved variants
PublicMediaFileModelType::RvcV2 => MediaFileOriginModelType::RvcV2,
PublicMediaFileModelType::SoVitsSvc => MediaFileOriginModelType::SoVitsSvc,
PublicMediaFileModelType::Tacotron2 => MediaFileOriginModelType::Tacotron2,
PublicMediaFileModelType::MocapNet => MediaFileOriginModelType::MocapNet,
PublicMediaFileModelType::StableDiffusion15 => MediaFileOriginModelType::StableDiffusion15,
PublicMediaFileModelType::StorytellerStudio => MediaFileOriginModelType::StorytellerStudio,
PublicMediaFileModelType::VideoStyleTransfer => MediaFileOriginModelType::VideoStyleTransfer,
PublicMediaFileModelType::ComfyUi => MediaFileOriginModelType::ComfyUi,
PublicMediaFileModelType::VallEX => MediaFileOriginModelType::VallEX,
PublicMediaFileModelType::Rerender => MediaFileOriginModelType::Rerender,
}
}
}
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use crate::test_helpers::to_json;
use super::*;
fn override_enums() -> &'static [PublicMediaFileModelType; 3] {
&[
PublicMediaFileModelType::FaceMirror,
PublicMediaFileModelType::FaceAnimator,
PublicMediaFileModelType::VoiceDesigner,
]
}
mod override_values {
use super::*;
#[test]
fn live_portrait() {
// Public --> Internal
assert_eq!(PublicMediaFileModelType::FaceMirror.to_enum(), MediaFileOriginModelType::LivePortrait);
assert_eq!(to_json(&PublicMediaFileModelType::FaceMirror.to_enum()), "live_portrait");
// Internal --> Public
assert_eq!(PublicMediaFileModelType::from_enum(MediaFileOriginModelType::LivePortrait), PublicMediaFileModelType::FaceMirror);
assert_eq!(to_json(&PublicMediaFileModelType::from_enum(MediaFileOriginModelType::LivePortrait)), "face_mirror");
}
#[test]
fn sad_talker() {
// Public --> Internal
assert_eq!(PublicMediaFileModelType::FaceAnimator.to_enum(), MediaFileOriginModelType::SadTalker);
assert_eq!(to_json(&PublicMediaFileModelType::FaceAnimator.to_enum()), "sad_talker");
// Internal --> Public
assert_eq!(PublicMediaFileModelType::from_enum(MediaFileOriginModelType::SadTalker), PublicMediaFileModelType::FaceAnimator);
assert_eq!(to_json(&PublicMediaFileModelType::from_enum(MediaFileOriginModelType::SadTalker)), "face_animator");
}
#[test]
fn styletts2() {
// Public --> Internal
assert_eq!(PublicMediaFileModelType::VoiceDesigner.to_enum(), MediaFileOriginModelType::StyleTTS2);
assert_eq!(to_json(&PublicMediaFileModelType::VoiceDesigner.to_enum()), "styletts2");
// Internal --> Public
assert_eq!(PublicMediaFileModelType::from_enum(MediaFileOriginModelType::StyleTTS2), PublicMediaFileModelType::VoiceDesigner);
assert_eq!(to_json(&PublicMediaFileModelType::from_enum(MediaFileOriginModelType::StyleTTS2)), "voice_designer");
}
}
mod mechanical_checks {
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
use super::*;
#[test]
fn public_to_internal() {
let mut tested_count = 0;
for public_variant in PublicMediaFileModelType::iter() {
match public_variant {
PublicMediaFileModelType::FaceMirror |
PublicMediaFileModelType::FaceAnimator |
PublicMediaFileModelType::VoiceDesigner => continue, // Can't compare.
_ => {}
}
// Round trip
assert_eq!(public_variant, PublicMediaFileModelType::from_enum(public_variant.to_enum()));
let internal_enum_variant = public_variant.to_enum();
let internal_enum_string = to_json(&internal_enum_variant);
let public_enum_string = to_json(&public_variant);
assert_eq!(internal_enum_string, public_enum_string);
tested_count += 1;
}
assert!(tested_count > 1);
assert_eq!(tested_count, PublicMediaFileModelType::iter().len() - override_enums().len());
}
#[test]
fn internal_to_public() {
let mut tested_count = 0;
for internal_variant in MediaFileOriginModelType::all_variants() {
match internal_variant {
MediaFileOriginModelType::LivePortrait |
MediaFileOriginModelType::SadTalker |
MediaFileOriginModelType::StyleTTS2 => continue, // Can't compare.
_ => {}
}
// Round trip
assert_eq!(internal_variant, PublicMediaFileModelType::from_enum(internal_variant).to_enum());
let public_enum_variant = PublicMediaFileModelType::from_enum(internal_variant);
let public_enum_string = to_json(&public_enum_variant);
let internal_enum_string = to_json(&internal_variant);
// Same serialization
assert_eq!(internal_enum_string, public_enum_string);
tested_count += 1;
}
assert!(tested_count > 1);
assert_eq!(tested_count, MediaFileOriginModelType::all_variants().len() - override_enums().len());
}
}
}
@@ -1,2 +1,3 @@
pub mod generic_inference_jobs;
pub mod media_files;
pub mod model_weights;
+30
View File
@@ -0,0 +1,30 @@
[package]
name = "dimensions"
edition = "2018"
version = "0.0.1"
authors = [
"Brandon Thomas <bt@brand.io>",
"Brandon Thomas <echelon@gmail.com>",
]
publish = false
[lib]
# NB: Public "dimensions" crate is not relevant / abandoned, so we're fine to use this internally.
name = "dimensions"
path = "src/lib.rs"
[package.metadata.cargo-udeps.ignore]
normal = ["my-workspace-hack"]
[dependencies]
# Workspace hack (faster compile times)
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
# Internal
errors = { path = "../errors" }
# External
# (None Yet)
[dev-dependencies]
# None yet
+20
View File
@@ -0,0 +1,20 @@
//! dimensions
//!
//! The purpose of this library is to specify common dimensions for video and
//! to do aspect ratio calculations in a reusable manner.
//!
// Never allow these
#![forbid(private_bounds)]
#![forbid(private_interfaces)]
#![forbid(unused_must_use)] // NB: It's unsafe to not close/check some things
// Okay to toggle
#![forbid(unreachable_patterns)]
#![forbid(unused_imports)]
#![forbid(unused_mut)]
#![forbid(unused_variables)]
// Always allow
#![allow(dead_code)]
#![allow(non_snake_case)]
@@ -0,0 +1 @@
pub mod watermark_type;
@@ -0,0 +1,16 @@
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum WatermarkType {
/// Show a FakeYou watermark
#[serde(rename = "f")] // NB: DO NOT CHANGE. It could break live jobs. Renamed to be fewer bytes.
FakeYou,
/// Show a Storyteller watermark
#[serde(rename = "s")] // NB: DO NOT CHANGE. It could break live jobs. Renamed to be fewer bytes.
Storyteller,
/// Show no watermark
/// Same as if Option<WatermarkType> is None.
#[serde(rename = "n")] // NB: DO NOT CHANGE. It could break live jobs. Renamed to be fewer bytes.
NoWatermark,
}
@@ -1,6 +1,7 @@
use enums::common::visibility::Visibility;
use tokens::tokens::media_files::MediaFileToken;
use crate::payloads::generic_inference_args::common::watermark_type::WatermarkType;
// **DO NOT CHANGE THE NAMES OF FIELDS WITHOUT A MIGRATION STRATEGY**
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
pub struct LivePortraitPayload {
/// Either an image or video.
@@ -13,12 +14,30 @@ pub struct LivePortraitPayload {
#[serde(skip_serializing_if = "Option::is_none")]
pub driver_media_file_token: Option<MediaFileToken>,
#[serde(rename = "c")]
#[serde(skip_serializing_if = "Option::is_none")]
pub crop: Option<CropDimensions>,
#[serde(rename = "rm")]
#[serde(skip_serializing_if = "Option::is_none")]
pub remove_watermark: Option<bool>,
#[serde(rename = "w")]
#[serde(skip_serializing_if = "Option::is_none")]
pub watermark_type: Option<WatermarkType>,
/// This is a debugging flag.
#[serde(rename = "sp")]
#[serde(skip_serializing_if = "Option::is_none")]
pub sleep_millis: Option<u64>,
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
pub struct CropDimensions {
pub x: u32,
pub y: u32,
#[serde(rename = "h")]
pub height: u32,
#[serde(rename = "w")]
pub width: u32,
}
@@ -1,3 +1,4 @@
pub mod common;
pub mod generic_inference_args;
pub mod image_generation_payload;
pub mod lipsync_payload;
@@ -4,6 +4,7 @@ use enums::common::visibility::Visibility;
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
use tokens::tokens::media_files::MediaFileToken;
use tokens::tokens::model_weights::ModelWeightToken;
use crate::payloads::generic_inference_args::common::watermark_type::WatermarkType;
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(untagged)]
@@ -40,8 +41,23 @@ impl NewValue {
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum WorkflowType {
/// For jobs that power Storyteller Studio
#[serde(rename = "s")]
StorytellerStudio,
/// For jobs that power video style transfer
#[serde(rename = "vst")]
VideoStyleTransfer,
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
pub struct WorkflowArgs {
#[serde(rename = "w")]
#[serde(skip_serializing_if = "Option::is_none")]
pub workflow_type: Option<WorkflowType>,
#[serde(rename = "lora")]
#[serde(skip_serializing_if = "Option::is_none")]
pub maybe_lora_model: Option<ModelWeightToken>,
@@ -154,6 +170,10 @@ pub struct WorkflowArgs {
#[serde(skip_serializing_if = "Option::is_none")]
pub remove_watermark: Option<bool>,
#[serde(rename = "wt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub watermark_type: Option<WatermarkType>,
// TODO(bt,2024-05-13): This is a temporary rollout flag to enable us to do Python-side mapping of job args
#[deprecated(note = "This has been rolled out and is effectively dead.")]
#[serde(rename = "pa")]
@@ -26,6 +26,10 @@ pub struct InsertArgs<'a> {
// TODO: Media duration.
//pub duration_millis: u64,
/// What product generated the result.
pub maybe_product_category: Option<MediaFileOriginProductCategory>,
pub maybe_model_type: Option<MediaFileOriginModelType>,
pub maybe_title: Option<&'a str>,
pub maybe_style_transfer_source_media_file_token: Option<&'a MediaFileToken>,
pub maybe_scene_source_media_file_token: Option<&'a MediaFileToken>,
@@ -72,8 +76,11 @@ pub async fn insert_media_file_from_comfy_ui(args: InsertArgs<'_>) -> AnyhowResu
}
const ORIGIN_CATEGORY : MediaFileOriginCategory = MediaFileOriginCategory::Inference;
const ORIGIN_PRODUCT_CATEGORY : MediaFileOriginProductCategory = MediaFileOriginProductCategory::Workflow;
const ORIGIN_MODEL_TYPE : MediaFileOriginModelType = MediaFileOriginModelType::ComfyUi;
let product = args.maybe_product_category
.unwrap_or(MediaFileOriginProductCategory::Unknown);
let maybe_model_type = args.maybe_model_type.map(|m| m.to_str());
let record_id = {
let query_result = sqlx::query!(
@@ -125,8 +132,8 @@ SET
MediaFileType::Video.to_str(), // TODO(bt,2024-04-30): This needs to become "mp4" after a frontend migration
ORIGIN_CATEGORY.to_str(),
ORIGIN_PRODUCT_CATEGORY.to_str(),
ORIGIN_MODEL_TYPE.to_str(),
product.to_str(),
maybe_model_type,
args.maybe_mime_type,
args.file_size_bytes,
@@ -63,7 +63,7 @@ pub async fn insert_media_file_from_file_upload(
let origin_category = match args.upload_type {
UploadType::Filesystem => MediaFileOriginCategory::Upload,
UploadType::DeviceCaptureApi => MediaFileOriginCategory::DeviceApi,
UploadType::StorytellerEngine => MediaFileOriginCategory::StoryEngine,
UploadType::StorytellerEngine => MediaFileOriginCategory::StorytellerStudio,
};
let mut maybe_creator_file_synthetic_id : Option<u64> = None;
@@ -69,7 +69,7 @@ pub async fn upsert_media_file_from_file_upload(
let origin_category = match args.upload_type {
UploadType::Filesystem => MediaFileOriginCategory::Upload,
UploadType::DeviceCaptureApi => MediaFileOriginCategory::DeviceApi,
UploadType::StorytellerEngine => MediaFileOriginCategory::StoryEngine,
UploadType::StorytellerEngine => MediaFileOriginCategory::StorytellerStudio,
};
let mut maybe_creator_file_synthetic_id : Option<u64> = None;
+3 -3
View File
@@ -17,12 +17,12 @@ path = "src/lib.rs"
normal = ["my-workspace-hack"]
[dependencies]
# Internal
errors = { path = "../errors" }
# Workspace hack (faster compile times)
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
# Internal
errors = { path = "../errors" }
# External
bcrypt = "0.15" # password hashes
#hmac = "0.10.0" # jwt signing
@@ -14,6 +14,8 @@ use buckets::public::media_files::bucket_file_path::MediaFileBucketPath;
use cloud_storage::remote_file_manager::remote_cloud_bucket_details::RemoteCloudBucketDetails;
use cloud_storage::remote_file_manager::remote_cloud_file_manager::RemoteCloudFileClient;
use enums::by_table::generic_inference_jobs::inference_result_type::InferenceResultType;
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
use enums::by_table::media_files::media_file_origin_product_category::MediaFileOriginProductCategory;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::by_table::prompts::prompt_type::PromptType;
use errors::AnyhowResult;
@@ -283,6 +285,8 @@ pub async fn process_live_portrait_job(
let (media_file_token, id) = insert_media_file_from_comfy_ui(InsertArgs {
pool: &deps.db.mysql_pool,
job: &job,
maybe_product_category: Some(MediaFileOriginProductCategory::FaceMirror), // Live Portrait named "Face Mirror" on the site
maybe_model_type: Some(MediaFileOriginModelType::LivePortrait),
maybe_mime_type: Some(&mimetype),
maybe_title: None,
maybe_style_transfer_source_media_file_token: Some(&portrait_media_token),
@@ -28,9 +28,11 @@ pub async fn process_single_workflow_job(
let job_success_result = match workflow_args.maybe_google_drive_link {
Some(_link) => {
// NB(bt,2024-07-25): I don't think we enqueue jobs to do this anymore. This code path might be dead.
process_upload_workflow_job(job_dependencies, job).await?
}
None => {
// This services both Storyteller Studio and "Video Style Transfer" products.
process_video_style_transfer_job(job_dependencies, job).await?
}
};
@@ -31,7 +31,6 @@ use mysql_queries::payloads::generic_inference_args::workflow_payload::NewValue;
use mysql_queries::payloads::prompt_args::encoded_style_transfer_name::EncodedStyleTransferName;
use mysql_queries::payloads::prompt_args::prompt_inner_payload::{PromptInnerPayload, PromptInnerPayloadBuilder};
use mysql_queries::queries::generic_inference::job::list_available_generic_inference_jobs::AvailableInferenceJob;
use mysql_queries::queries::media_files::create::insert_media_file_from_comfy_ui::{insert_media_file_from_comfy_ui, InsertArgs};
use mysql_queries::queries::media_files::get::get_media_file::get_media_file;
use mysql_queries::queries::model_weights::get::get_weight::get_weight_by_token;
use mysql_queries::queries::prompts::insert_prompt::{insert_prompt, InsertPromptArgs};
@@ -8,6 +8,8 @@ use tempdir::TempDir;
use buckets::public::media_files::bucket_file_path::MediaFileBucketPath;
use enums::by_table::generic_inference_jobs::inference_result_type::InferenceResultType;
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
use enums::by_table::media_files::media_file_origin_product_category::MediaFileOriginProductCategory;
use enums::by_table::prompts::prompt_type::PromptType;
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
use errors::AnyhowResult;
@@ -19,7 +21,7 @@ use filesys::safe_recursively_delete_files::safe_recursively_delete_files;
use hashing::sha256::sha256_hash_file::sha256_hash_file;
use jobs_common::job_progress_reporter::job_progress_reporter::JobProgressReporter;
use mimetypes::mimetype_for_file::get_mimetype_for_file;
use mysql_queries::payloads::generic_inference_args::workflow_payload::WorkflowArgs;
use mysql_queries::payloads::generic_inference_args::workflow_payload::{WorkflowArgs, WorkflowType};
use mysql_queries::payloads::prompt_args::prompt_inner_payload::PromptInnerPayloadBuilder;
use mysql_queries::queries::generic_inference::job::list_available_generic_inference_jobs::AvailableInferenceJob;
use mysql_queries::queries::media_files::create::insert_media_file_from_comfy_ui::{insert_media_file_from_comfy_ui, InsertArgs};
@@ -183,9 +185,23 @@ pub async fn validate_and_save_results(args: SaveResultsArgs<'_>) -> Result<Medi
let prompt_token = PromptToken::generate();
let product = match args.comfy_args.workflow_type {
Some(WorkflowType::StorytellerStudio) => Some(MediaFileOriginProductCategory::StorytellerStudio),
Some(WorkflowType::VideoStyleTransfer) => Some(MediaFileOriginProductCategory::VideoStyleTransfer),
None => None,
};
let maybe_model_type = match args.comfy_args.workflow_type {
Some(WorkflowType::StorytellerStudio) => Some(MediaFileOriginModelType::StorytellerStudio),
Some(WorkflowType::VideoStyleTransfer) => Some(MediaFileOriginModelType::VideoStyleTransfer),
None => None,
};
let (media_file_token, id) = insert_media_file_from_comfy_ui(InsertArgs {
pool: &args.deps.db.mysql_pool,
job: &args.job,
maybe_product_category: product,
maybe_model_type,
maybe_mime_type: Some(&mimetype),
maybe_title: args.videos.primary_video.record.maybe_title.as_deref(),
maybe_style_transfer_source_media_file_token: Some(&style_transfer_source_media_file_token),
@@ -12,7 +12,6 @@ use enums::by_table::media_files::media_file_animation_type::MediaFileAnimationT
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory;
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
use enums::by_table::media_files::media_file_origin_product_category::MediaFileOriginProductCategory;
use enums::by_table::media_files::media_file_subtype::MediaFileSubtype;
use enums::by_table::media_files::media_file_type::MediaFileType;
@@ -25,6 +24,7 @@ use enums::by_table::users::user_feature_flag::UserFeatureFlag;
use enums::common::job_status_plus::JobStatusPlus;
use enums::common::visibility::Visibility;
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
use enums_public::by_table::media_files::public_media_file_model_type::PublicMediaFileModelType;
use enums_public::by_table::model_weights::public_weights_types::PublicWeightsType;
use tokens::tokens::batch_generations::*;
use tokens::tokens::beta_keys::*;
@@ -71,7 +71,6 @@ use crate::http_server::endpoints::inference_job::terminate_inference_job_handle
use crate::http_server::endpoints::media_files::delete::delete_media_file_handler::*;
use crate::http_server::endpoints::media_files::edit::change_media_file_animation_type_handler::*;
use crate::http_server::endpoints::media_files::edit::change_media_file_engine_category_handler::*;
use crate::http_server::endpoints::stats::get_unified_queue_stats_handler::*;
use crate::http_server::endpoints::media_files::edit::change_media_file_visibility_handler::*;
use crate::http_server::endpoints::media_files::edit::rename_media_file_handler::*;
use crate::http_server::endpoints::media_files::edit::set_media_file_cover_image_handler::*;
@@ -102,6 +101,7 @@ use crate::http_server::endpoints::media_files::upsert_upload::write_scene_file:
use crate::http_server::endpoints::moderation::user_feature_flags::edit_user_feature_flags_handler::*;
use crate::http_server::endpoints::prompts::get_prompt_handler::*;
use crate::http_server::endpoints::service::status_alert_handler::*;
use crate::http_server::endpoints::stats::get_unified_queue_stats_handler::*;
use crate::http_server::endpoints::tts::enqueue_infer_tts_handler::enqueue_infer_tts_handler::*;
use crate::http_server::endpoints::user_bookmarks::batch_get_user_bookmarks_handler::*;
use crate::http_server::endpoints::user_bookmarks::create_user_bookmark_handler::*;
@@ -128,8 +128,6 @@ use crate::http_server::endpoints::weights::search_model_weights_handler::*;
use crate::http_server::endpoints::weights::set_model_weight_cover_image_handler::*;
use crate::http_server::endpoints::weights::update_weight_handler::*;
use crate::http_server::endpoints::workflows::enqueue::enqueue_live_portrait_workflow_handler::*;
use crate::http_server::endpoints::workflows::enqueue::enqueue_studio_workflow_handler::*;
use crate::http_server::endpoints::workflows::enqueue::enqueue_video_style_transfer_workflow_handler::*;
use crate::http_server::endpoints::workflows::enqueue::vst_common::vst_error::*;
use crate::http_server::endpoints::workflows::enqueue::vst_common::vst_request::*;
use crate::http_server::endpoints::workflows::enqueue::vst_common::vst_response::*;
@@ -247,11 +245,11 @@ use crate::http_server::web_utils::response_success_helpers::*;
MediaFileClass,
MediaFileEngineCategory,
MediaFileOriginCategory,
MediaFileOriginModelType,
MediaFileOriginProductCategory,
MediaFileSubtype,
MediaFileType,
PromptType,
PublicMediaFileModelType,
PublicWeightsType,
StyleTransferName,
UserFeatureFlag,
@@ -329,9 +327,6 @@ use crate::http_server::web_utils::response_success_helpers::*;
CreateUserBookmarkSuccessResponse,
DeleteCommentError,
DeleteCommentPathInfo,
VstError,
VstRequest,
VstSuccessResponse,
DeleteCommentRequest,
DeleteFeaturedItemError,
DeleteFeaturedItemRequest,
@@ -361,6 +356,7 @@ use crate::http_server::web_utils::response_success_helpers::*;
EnqueueFbxToGltfRequest,
EnqueueFbxToGltfRequestError,
EnqueueFbxToGltfRequestSuccessResponse,
EnqueueLivePortraitCropDimensions,
EnqueueLivePortraitWorkflowError,
EnqueueLivePortraitWorkflowRequest,
EnqueueLivePortraitWorkflowSuccessResponse,
@@ -399,11 +395,11 @@ use crate::http_server::web_utils::response_success_helpers::*;
GetWeightError,
GetWeightPathInfo,
GetWeightResponse,
InferenceJobStatusResponsePayload,
InferenceJobTokenType,
InferTtsError,
InferTtsRequest,
InferTtsSuccessResponse,
InferenceJobStatusResponsePayload,
InferenceJobTokenType,
LegacyQueueDetails,
ListActiveUserSubscriptionsError,
ListActiveUserSubscriptionsResponse,
@@ -469,8 +465,8 @@ use crate::http_server::web_utils::response_success_helpers::*;
MediaFileForUserListItem,
MediaFileInfo,
MediaFileListItem,
MediaFilesByBatchListItem,
MediaFileUploadError,
MediaFilesByBatchListItem,
ModelWeightForList,
ModelWeightSearchResult,
ModernInferenceQueueStats,
@@ -551,6 +547,9 @@ use crate::http_server::web_utils::response_success_helpers::*;
UserProfileUserBadge,
UserRatingEntityType,
UserRatingValue,
VstError,
VstRequest,
VstSuccessResponse,
Weight,
WeightsData,
WriteEngineAssetMediaSuccessResponse,
@@ -3,6 +3,7 @@ use utoipa::ToSchema;
use enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory;
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
use enums::by_table::media_files::media_file_origin_product_category::MediaFileOriginProductCategory;
use enums_public::by_table::media_files::public_media_file_model_type::PublicMediaFileModelType;
use tokens::tokens::model_weights::ModelWeightToken;
/// Fields useful for enriching media file listings
@@ -27,13 +28,13 @@ pub enum MediaFileModelDetails {
/// eg. SadTalker, Wav2Lip, MocapNet, etc.
SystemModel {
/// The type of model weight
model_type: MediaFileOriginModelType,
model_type: PublicMediaFileModelType,
},
/// A model weight is typically a user-submitted model.
/// We store lots of these.
ModelWeight {
/// The type of model weight
model_type: MediaFileOriginModelType,
model_type: PublicMediaFileModelType,
/// The model token
token: ModelWeightToken,
/// The model title (typically only populated for `model_weights` models, not legacy tables such as `tts_models`.)
@@ -52,14 +53,14 @@ impl MediaFileOriginDetails {
let maybe_model = match (maybe_model_type, maybe_model_token, maybe_model_title) {
(Some(model_type), Some(model_token), Some(model_title)) => {
Some(MediaFileModelDetails::ModelWeight {
model_type,
model_type: PublicMediaFileModelType::from_enum(model_type),
token: model_token,
title: model_title,
})
},
(Some(model_type), None, None) => {
Some(MediaFileModelDetails::SystemModel {
model_type,
model_type: PublicMediaFileModelType::from_enum(model_type),
})
},
_ => None,
@@ -14,7 +14,6 @@ use enums::by_table::generic_inference_jobs::inference_category::InferenceCatego
use enums::by_table::generic_inference_jobs::inference_job_type::InferenceJobType;
use enums::by_table::generic_inference_jobs::inference_model_type::InferenceModelType;
use enums::common::visibility::Visibility;
use http_server_common::request::get_request_header_optional::get_request_header_optional;
use http_server_common::request::get_request_ip::get_request_ip;
use mysql_queries::payloads::generic_inference_args::generic_inference_args::{GenericInferenceArgs, InferenceCategoryAbbreviated, PolymorphicInferenceArgs};
use mysql_queries::payloads::generic_inference_args::lipsync_payload::{FaceEnhancer, LipsyncAnimationAudioSource, LipsyncAnimationImageSource, LipsyncArgs};
@@ -24,20 +23,14 @@ use tokens::tokens::media_files::MediaFileToken;
use tokens::tokens::media_uploads::MediaUploadToken;
use tokens::tokens::users::UserToken;
use tokens::tokens::voice_conversion_results::VoiceConversionResultToken;
use crate::http_server::session::lookup::user_session_extended::UserSessionExtended;
use crate::configs::plans::get_correct_plan_for_session::get_correct_plan_for_session;
use crate::http_server::headers::get_routing_tag_header::get_routing_tag_header;
use crate::http_server::headers::has_debug_header::has_debug_header;
use crate::http_server::session::lookup::user_session_extended::UserSessionExtended;
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
use crate::state::server_state::ServerState;
/// Debug requests can get routed to special "debug-only" workers, which can
/// be used to trial new code, run debugging, etc.
const DEBUG_HEADER_NAME : &str = "enable-debug-mode";
/// The routing tag header can send workloads to particular k8s hosts.
/// This is useful for catching the live logs or intercepting the job.
const ROUTING_TAG_HEADER_NAME : &str = "routing-tag";
#[derive(Deserialize)]
pub struct EnqueueFaceAnimationRequest {
uuid_idempotency_token: String,
@@ -203,13 +196,8 @@ pub async fn enqueue_face_animation_handler(
// ==================== DEBUG MODE + ROUTING TAG ==================== //
let is_debug_request =
get_request_header_optional(&http_request, DEBUG_HEADER_NAME)
.is_some();
let maybe_routing_tag=
get_request_header_optional(&http_request, ROUTING_TAG_HEADER_NAME)
.map(|routing_tag| routing_tag.trim().to_string());
let is_debug_request = has_debug_header(&http_request);
let maybe_routing_tag = get_routing_tag_header(&http_request);
// ==================== BANNED USERS ==================== //
@@ -12,27 +12,18 @@ use utoipa::{IntoParams, ToSchema};
use buckets::public::media_files::bucket_file_path::MediaFileBucketPath;
use enums::by_table::beta_keys::beta_key_product::BetaKeyProduct;
use enums::by_table::media_files::media_file_animation_type::MediaFileAnimationType;
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory;
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
use enums::by_table::media_files::media_file_origin_product_category::MediaFileOriginProductCategory;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::common::view_as::ViewAs;
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
use markdown::markdown_with_socials_to_html::markdown_with_socials_to_html;
use mysql_queries::queries::beta_keys::list_beta_keys::{FilterToKeys, list_beta_keys, ListBetaKeysArgs};
use mysql_queries::queries::users::user_profiles::get_user_profile_by_username::get_user_profile_by_username;
use tokens::tokens::beta_keys::BetaKeyToken;
use tokens::tokens::media_files::MediaFileToken;
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
use crate::http_server::common_responses::media_file_cover_image_details::{MediaFileCoverImageDetails, MediaFileDefaultCover};
use crate::http_server::common_responses::media_file_origin_details::MediaFileOriginDetails;
use crate::http_server::common_responses::pagination_cursors::PaginationCursors;
use crate::http_server::common_responses::pagination_page::PaginationPage;
use crate::http_server::common_responses::simple_entity_stats::SimpleEntityStats;
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
use crate::http_server::endpoints::beta_keys::create_beta_keys_handler::CreateBetaKeysError;
use crate::http_server::endpoints::events::list_events::ListEventsError;
use crate::http_server::web_utils::require_moderator::{require_moderator, RequireModeratorError};
@@ -11,7 +11,6 @@ use utoipa::ToSchema;
use buckets::public::media_files::bucket_file_path::MediaFileBucketPath;
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_subtype::MediaFileSubtype;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::common::visibility::Visibility;
use hashing::sha256::sha256_hash_bytes::sha256_hash_bytes;
@@ -23,8 +22,8 @@ use mysql_queries::queries::media_files::create::insert_media_file_from_file_upl
use tokens::tokens::media_files::MediaFileToken;
use crate::http_server::endpoints::engine::drain_multipart_request::drain_multipart_request;
use crate::state::server_state::ServerState;
use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format;
use crate::state::server_state::ServerState;
#[derive(Debug, Serialize, ToSchema)]
pub enum CreateSceneError {
@@ -79,6 +79,8 @@ pub struct MediaFileInfo {
/// If the file was generated as part of a batch, this is the token for the batch.
pub maybe_batch_token: Option<BatchGenerationToken>,
/// If this media file was generated by a scene from the engine, this is a
/// link to that file.
pub maybe_scene_source_media_file_token: Option<MediaFileToken>,
/// URL to the media file
@@ -339,7 +341,8 @@ async fn modern_media_file_lookup(
media_type: result.media_type,
maybe_engine_category: result.maybe_engine_category,
maybe_animation_type: result.maybe_animation_type,
maybe_media_subtype: result.maybe_media_subtype,
// maybe_media_subtype: result.maybe_media_subtype,
maybe_media_subtype: None, // NB(bt,2024-07-25): Stop populating field for consumers.
maybe_engine_extension,
maybe_batch_token: result.maybe_batch_token,
maybe_scene_source_media_file_token: result.maybe_scene_source_media_file_token,
@@ -14,11 +14,11 @@ use enums::by_table::media_files::media_file_animation_type::MediaFileAnimationT
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory;
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
use enums::by_table::media_files::media_file_origin_product_category::MediaFileOriginProductCategory;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::common::view_as::ViewAs;
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
use enums_public::by_table::media_files::public_media_file_model_type::PublicMediaFileModelType;
use mysql_queries::queries::media_files::get::batch_get_media_files_by_tokens::batch_get_media_files_by_tokens;
use mysql_queries::queries::media_files::list::list_featured_media_files::{FeaturedMediaFileListPage, list_featured_media_files, ListFeaturedMediaFilesArgs};
use tokens::tokens::media_files::MediaFileToken;
@@ -113,7 +113,7 @@ pub struct FeaturedMediaFile {
pub origin_product_category: MediaFileOriginProductCategory,
#[deprecated(note="Use MediaFileOriginDetails instead")]
pub maybe_origin_model_type: Option<MediaFileOriginModelType>,
pub maybe_origin_model_type: Option<PublicMediaFileModelType>,
#[deprecated(note="Use MediaFileOriginDetails instead")]
pub maybe_origin_model_token: Option<String>,
@@ -256,7 +256,8 @@ pub async fn list_featured_media_files_handler(
m.maybe_origin_model_title.as_deref()),
origin_category: m.origin_category,
origin_product_category: m.origin_product_category,
maybe_origin_model_type: m.maybe_origin_model_type,
maybe_origin_model_type: m.maybe_origin_model_type
.map(|t| PublicMediaFileModelType::from_enum(t)),
maybe_origin_model_token: m.maybe_origin_model_token,
maybe_creator: UserDetailsLight::from_optional_db_fields_owned(
m.maybe_creator_user_token,
@@ -13,12 +13,12 @@ use enums::by_table::media_files::media_file_animation_type::MediaFileAnimationT
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory;
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
use enums::by_table::media_files::media_file_origin_product_category::MediaFileOriginProductCategory;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::common::view_as::ViewAs;
use enums::common::visibility::Visibility;
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
use enums_public::by_table::media_files::public_media_file_model_type::PublicMediaFileModelType;
use mysql_queries::queries::media_files::list::list_media_files_by_batch_token::{list_media_files_by_batch_token, ListMediaFileByBatchArgs};
use mysql_queries::queries::media_files::list::list_media_files_for_user::{list_media_files_for_user, ListMediaFileForUserArgs};
use tokens::tokens::batch_generations::BatchGenerationToken;
@@ -84,7 +84,7 @@ pub struct MediaFilesByBatchListItem {
pub origin_product_category: MediaFileOriginProductCategory,
#[deprecated(note="Use MediaFileOriginDetails instead")]
pub maybe_origin_model_type: Option<MediaFileOriginModelType>,
pub maybe_origin_model_type: Option<PublicMediaFileModelType>,
#[deprecated(note="Use MediaFileOriginDetails instead")]
pub maybe_origin_model_token: Option<String>,
@@ -246,7 +246,8 @@ pub async fn list_media_files_by_batch_token_handler(
record.maybe_origin_model_title.as_deref()),
origin_category: record.origin_category,
origin_product_category: record.origin_product_category,
maybe_origin_model_type: record.maybe_origin_model_type,
maybe_origin_model_type: record.maybe_origin_model_type
.map(|t| PublicMediaFileModelType::from_enum(t)),
maybe_origin_model_token: record.maybe_origin_model_token,
public_bucket_path: MediaFileBucketPath::from_object_hash(
&record.public_bucket_directory_hash,
@@ -14,12 +14,12 @@ use enums::by_table::media_files::media_file_animation_type::MediaFileAnimationT
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory;
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
use enums::by_table::media_files::media_file_origin_product_category::MediaFileOriginProductCategory;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::common::view_as::ViewAs;
use enums::common::visibility::Visibility;
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
use enums_public::by_table::media_files::public_media_file_model_type::PublicMediaFileModelType;
use mysql_queries::queries::media_files::list::list_media_files_for_user::{list_media_files_for_user, ListMediaFileForUserArgs};
use tokens::tokens::media_files::MediaFileToken;
@@ -112,7 +112,7 @@ pub struct MediaFileForUserListItem {
pub origin_product_category: MediaFileOriginProductCategory,
#[deprecated(note="Use MediaFileOriginDetails instead")]
pub maybe_origin_model_type: Option<MediaFileOriginModelType>,
pub maybe_origin_model_type: Option<PublicMediaFileModelType>,
#[deprecated(note="Use MediaFileOriginDetails instead")]
pub maybe_origin_model_token: Option<String>,
@@ -300,7 +300,8 @@ pub async fn list_media_files_for_user_handler(
record.maybe_origin_model_title.as_deref()),
origin_category: record.origin_category,
origin_product_category: record.origin_product_category,
maybe_origin_model_type: record.maybe_origin_model_type,
maybe_origin_model_type: record.maybe_origin_model_type
.map(|t| PublicMediaFileModelType::from_enum(t)),
maybe_origin_model_token: record.maybe_origin_model_token,
public_bucket_path: MediaFileBucketPath::from_object_hash(
&record.public_bucket_directory_hash,
@@ -13,20 +13,20 @@ use enums::by_table::media_files::media_file_animation_type::MediaFileAnimationT
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory;
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
use enums::by_table::media_files::media_file_origin_product_category::MediaFileOriginProductCategory;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::common::view_as::ViewAs;
use enums::common::visibility::Visibility;
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
use enums_public::by_table::media_files::public_media_file_model_type::PublicMediaFileModelType;
use mysql_queries::queries::media_files::list::list_media_files::{list_media_files, ListMediaFilesArgs};
use tokens::tokens::media_files::MediaFileToken;
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
use crate::http_server::common_responses::media_file_cover_image_details::{MediaFileCoverImageDetails, MediaFileDefaultCover};
use crate::http_server::common_responses::media_file_origin_details::MediaFileOriginDetails;
use crate::http_server::common_responses::pagination_cursors::PaginationCursors;
use crate::http_server::common_responses::simple_entity_stats::SimpleEntityStats;
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
use crate::http_server::endpoints::media_files::helpers::get_scoped_engine_categories::get_scoped_engine_categories;
use crate::http_server::endpoints::media_files::helpers::get_scoped_media_classes::get_scoped_media_classes;
use crate::http_server::endpoints::media_files::helpers::get_scoped_media_types::get_scoped_media_types;
@@ -106,7 +106,7 @@ pub struct MediaFileListItem {
pub origin_product_category: MediaFileOriginProductCategory,
#[deprecated(note="Use MediaFileOriginDetails instead")]
pub maybe_origin_model_type: Option<MediaFileOriginModelType>,
pub maybe_origin_model_type: Option<PublicMediaFileModelType>,
#[deprecated(note="Use MediaFileOriginDetails instead")]
pub maybe_origin_model_token: Option<String>,
@@ -306,7 +306,8 @@ pub async fn list_media_files_handler(
record.maybe_origin_model_title.as_deref()),
origin_category: record.origin_category,
origin_product_category: record.origin_product_category,
maybe_origin_model_type: record.maybe_origin_model_type,
maybe_origin_model_type: record.maybe_origin_model_type
.map(|m| PublicMediaFileModelType::from_enum(m)),
maybe_origin_model_token: record.maybe_origin_model_token,
public_bucket_path: MediaFileBucketPath::from_object_hash(
&record.public_bucket_directory_hash,
@@ -13,17 +13,17 @@ use enums::by_table::media_files::media_file_animation_type::MediaFileAnimationT
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory;
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
use enums::by_table::media_files::media_file_origin_product_category::MediaFileOriginProductCategory;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
use enums_public::by_table::media_files::public_media_file_model_type::PublicMediaFileModelType;
use mysql_queries::queries::media_files::get::batch_get_media_files_by_tokens::batch_get_media_files_by_tokens;
use tokens::tokens::media_files::MediaFileToken;
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
use crate::http_server::common_responses::media_file_cover_image_details::{MediaFileCoverImageDetails, MediaFileDefaultCover};
use crate::http_server::common_responses::media_file_origin_details::MediaFileOriginDetails;
use crate::http_server::common_responses::simple_entity_stats::SimpleEntityStats;
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
use crate::state::server_state::ServerState;
#[derive(Serialize, ToSchema)]
@@ -69,7 +69,7 @@ pub struct PinnedMediaFile {
pub origin_product_category: MediaFileOriginProductCategory,
#[deprecated(note="Use MediaFileOriginDetails instead")]
pub maybe_origin_model_type: Option<MediaFileOriginModelType>,
pub maybe_origin_model_type: Option<PublicMediaFileModelType>,
#[deprecated(note="Use MediaFileOriginDetails instead")]
pub maybe_origin_model_token: Option<String>,
@@ -210,7 +210,8 @@ pub async fn list_pinned_media_files_handler(
m.maybe_origin_model_title.as_deref()),
origin_category: m.origin_category,
origin_product_category: m.origin_product_category,
maybe_origin_model_type: m.maybe_origin_model_type,
maybe_origin_model_type: m.maybe_origin_model_type
.map(|m| PublicMediaFileModelType::from_enum(m)),
maybe_origin_model_token: m.maybe_origin_model_token,
maybe_creator: UserDetailsLight::from_optional_db_fields_owned(
m.maybe_creator_user_token,
@@ -13,20 +13,17 @@ use elasticsearch_schema::searches::search_media_files::{search_media_files, Sea
use enums::by_table::media_files::media_file_animation_type::MediaFileAnimationType;
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory;
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
use enums::by_table::media_files::media_file_origin_product_category::MediaFileOriginProductCategory;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::common::view_as::ViewAs;
use enums::common::visibility::Visibility;
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
use tokens::tokens::media_files::MediaFileToken;
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
use crate::http_server::common_responses::media_file_cover_image_details::{MediaFileCoverImageDetails, MediaFileDefaultCover};
use crate::http_server::common_responses::media_file_origin_details::MediaFileOriginDetails;
use crate::http_server::common_responses::pagination_cursors::PaginationCursors;
use crate::http_server::common_responses::simple_entity_stats::SimpleEntityStats;
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
use crate::http_server::endpoints::media_files::helpers::get_scoped_engine_categories::get_scoped_engine_categories;
use crate::http_server::endpoints::media_files::helpers::get_scoped_media_classes::get_scoped_media_classes;
use crate::http_server::endpoints::media_files::helpers::get_scoped_media_types::get_scoped_media_types;
@@ -98,21 +95,6 @@ pub struct SearchFeaturedMediaFileListItem {
/// this describes the animation regime used or supported.
pub maybe_animation_type: Option<MediaFileAnimationType>,
// #[deprecated(note="Use MediaFileOriginDetails instead")]
// pub origin_category: MediaFileOriginCategory,
// #[deprecated(note="Use MediaFileOriginDetails instead")]
// pub origin_product_category: MediaFileOriginProductCategory,
// #[deprecated(note="Use MediaFileOriginDetails instead")]
// pub maybe_origin_model_type: Option<MediaFileOriginModelType>,
// #[deprecated(note="Use MediaFileOriginDetails instead")]
// pub maybe_origin_model_token: Option<String>,
// /// Details where the media file came from.
// pub origin: MediaFileOriginDetails,
/// URL to the media file.
pub public_bucket_path: String,
@@ -13,21 +13,18 @@ use elasticsearch_schema::searches::search_media_files::{search_media_files, Sea
use enums::by_table::media_files::media_file_animation_type::MediaFileAnimationType;
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory;
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
use enums::by_table::media_files::media_file_origin_product_category::MediaFileOriginProductCategory;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::common::view_as::ViewAs;
use enums::common::visibility::Visibility;
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
use tokens::tokens::media_files::MediaFileToken;
use tokens::tokens::users::UserToken;
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
use crate::http_server::common_responses::media_file_cover_image_details::{MediaFileCoverImageDetails, MediaFileDefaultCover};
use crate::http_server::common_responses::media_file_origin_details::MediaFileOriginDetails;
use crate::http_server::common_responses::pagination_cursors::PaginationCursors;
use crate::http_server::common_responses::simple_entity_stats::SimpleEntityStats;
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
use crate::http_server::endpoints::media_files::helpers::get_scoped_engine_categories::get_scoped_engine_categories;
use crate::http_server::endpoints::media_files::helpers::get_scoped_media_classes::get_scoped_media_classes;
use crate::http_server::endpoints::media_files::helpers::get_scoped_media_types::get_scoped_media_types;
@@ -99,21 +96,6 @@ pub struct SearchMediaFileListItem {
/// this describes the animation regime used or supported.
pub maybe_animation_type: Option<MediaFileAnimationType>,
// #[deprecated(note="Use MediaFileOriginDetails instead")]
// pub origin_category: MediaFileOriginCategory,
// #[deprecated(note="Use MediaFileOriginDetails instead")]
// pub origin_product_category: MediaFileOriginProductCategory,
// #[deprecated(note="Use MediaFileOriginDetails instead")]
// pub maybe_origin_model_type: Option<MediaFileOriginModelType>,
// #[deprecated(note="Use MediaFileOriginDetails instead")]
// pub maybe_origin_model_token: Option<String>,
// /// Details where the media file came from.
// pub origin: MediaFileOriginDetails,
/// URL to the media file.
pub public_bucket_path: String,
@@ -16,7 +16,6 @@ use utoipa::ToSchema;
use buckets::public::media_files::bucket_file_path::MediaFileBucketPath;
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_subtype::MediaFileSubtype;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::common::visibility::Visibility;
use hashing::sha256::sha256_hash_bytes::sha256_hash_bytes;
@@ -31,9 +30,9 @@ use tokens::tokens::media_files::MediaFileToken;
use videos::get_mp4_info::{get_mp4_info, get_mp4_info_for_bytes, get_mp4_info_for_bytes_and_len};
use crate::http_server::endpoints::media_files::upload::upload_error::MediaFileUploadError;
use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format;
use crate::state::server_state::ServerState;
use crate::util::check_creator_tokens::{check_creator_tokens, CheckCreatorTokenArgs, CheckCreatorTokenResult};
use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format;
/// Form-multipart request fields.
///
@@ -7,7 +7,6 @@ use log::warn;
use enums::by_table::media_files::media_file_animation_type::MediaFileAnimationType;
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_subtype::MediaFileSubtype;
use errors::AnyhowResult;
use tokens::tokens::zs_voice_datasets::ZsVoiceDatasetToken;
@@ -68,19 +67,6 @@ pub async fn drain_multipart_request(mut multipart_payload: Multipart) -> Anyhow
err
})?;
},
//Some("media_file_subtype") => {
// media_file_subtype = read_multipart_field_as_text(&mut field).await
// .map_err(|err| {
// warn!("Error reading source: {:?}", &err);
// err
// })?
// .map(|field| MediaFileSubtype::from_str(&field))
// .transpose()
// .map_err(|err| {
// warn!("Wrong MediaFileSubtype: {:?}", &err);
// anyhow!("Wrong MediaFileSubtype: {:?}", &err)
// })?;
//},
Some("engine_category") => {
maybe_engine_category = read_multipart_field_as_text(&mut field).await
.map_err(|err| {
@@ -16,7 +16,6 @@ use utoipa::ToSchema;
use buckets::public::media_files::bucket_file_path::MediaFileBucketPath;
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_subtype::MediaFileSubtype;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::common::visibility::Visibility;
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
@@ -31,9 +30,9 @@ use mysql_queries::queries::media_files::get::get_media_file::get_media_file;
use tokens::tokens::media_files::MediaFileToken;
use crate::http_server::endpoints::media_files::upload::upload_error::MediaFileUploadError;
use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format;
use crate::state::server_state::ServerState;
use crate::util::check_creator_tokens::{check_creator_tokens, CheckCreatorTokenArgs, CheckCreatorTokenResult};
use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format;
/// Form-multipart request fields.
///
@@ -16,7 +16,6 @@ use utoipa::ToSchema;
use buckets::public::media_files::bucket_file_path::MediaFileBucketPath;
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_subtype::MediaFileSubtype;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::common::visibility::Visibility;
use hashing::sha256::sha256_hash_bytes::sha256_hash_bytes;
@@ -30,9 +29,9 @@ use tokens::tokens::media_files::MediaFileToken;
use videos::get_mp4_info::{get_mp4_info, get_mp4_info_for_bytes, get_mp4_info_for_bytes_and_len};
use crate::http_server::endpoints::media_files::upload::upload_error::MediaFileUploadError;
use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format;
use crate::state::server_state::ServerState;
use crate::util::check_creator_tokens::{check_creator_tokens, CheckCreatorTokenArgs, CheckCreatorTokenResult};
use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format;
/// Form-multipart request fields.
///
@@ -16,7 +16,6 @@ use utoipa::ToSchema;
use buckets::public::media_files::bucket_file_path::MediaFileBucketPath;
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_subtype::MediaFileSubtype;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::common::visibility::Visibility;
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
@@ -29,14 +28,14 @@ use mimetypes::mimetype_to_extension::mimetype_to_extension;
use mysql_queries::queries::idepotency_tokens::insert_idempotency_token::insert_idempotency_token;
use mysql_queries::queries::media_files::create::insert_media_file_from_file_upload::{insert_media_file_from_file_upload, InsertMediaFileFromUploadArgs, UploadType};
use mysql_queries::queries::media_files::get::get_media_file::get_media_file;
use thumbnail_generator::task_client::thumbnail_task::{ThumbnailTaskBuilder, ThumbnailTaskInputMimeType};
use tokens::tokens::media_files::MediaFileToken;
use videos::get_mp4_info::{get_mp4_info, get_mp4_info_for_bytes, get_mp4_info_for_bytes_and_len};
use thumbnail_generator::task_client::thumbnail_task::{ThumbnailTaskBuilder, ThumbnailTaskInputMimeType};
use crate::http_server::endpoints::media_files::upload::upload_error::MediaFileUploadError;
use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format;
use crate::state::server_state::ServerState;
use crate::util::check_creator_tokens::{check_creator_tokens, CheckCreatorTokenArgs, CheckCreatorTokenResult};
use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format;
/// Form-multipart request fields.
///
@@ -17,7 +17,6 @@ use utoipa::ToSchema;
use buckets::public::media_files::bucket_file_path::MediaFileBucketPath;
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_subtype::MediaFileSubtype;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::common::visibility::Visibility;
use hashing::sha256::sha256_hash_bytes::sha256_hash_bytes;
@@ -34,9 +33,9 @@ use videos::get_mp4_info::{get_mp4_info, get_mp4_info_for_bytes, get_mp4_info_fo
use crate::http_server::endpoints::media_files::get::get_media_file_handler::GetMediaFilePathInfo;
use crate::http_server::endpoints::media_files::upload::upload_error::MediaFileUploadError;
use crate::http_server::endpoints::media_files::upsert_upload::write_error::MediaFileWriteError;
use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format;
use crate::state::server_state::ServerState;
use crate::util::check_creator_tokens::{check_creator_tokens, CheckCreatorTokenArgs, CheckCreatorTokenResult};
use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format;
/// For the URL PathInfo
#[derive(Deserialize, ToSchema)]
@@ -16,7 +16,6 @@ use utoipa::ToSchema;
use buckets::public::media_files::bucket_file_path::MediaFileBucketPath;
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_subtype::MediaFileSubtype;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::common::visibility::Visibility;
use hashing::sha256::sha256_hash_bytes::sha256_hash_bytes;
@@ -30,9 +29,9 @@ use tokens::tokens::media_files::MediaFileToken;
use videos::get_mp4_info::{get_mp4_info, get_mp4_info_for_bytes, get_mp4_info_for_bytes_and_len};
use crate::http_server::endpoints::media_files::upload::upload_error::MediaFileUploadError;
use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format;
use crate::state::server_state::ServerState;
use crate::util::check_creator_tokens::{check_creator_tokens, CheckCreatorTokenArgs, CheckCreatorTokenResult};
use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format;
/// Form-multipart request fields.
///
@@ -3,16 +3,14 @@ use actix_web::web::BytesMut;
use anyhow::anyhow;
use futures::TryStreamExt;
use log::{info, warn};
use enums::by_table::media_files::media_file_animation_type::MediaFileAnimationType;
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_subtype::MediaFileSubtype;
use enums::by_table::media_files::media_file_animation_type::MediaFileAnimationType;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use errors::AnyhowResult;
use tokens::tokens::media_files::MediaFileToken;
use tokens::tokens::zs_voice_datasets::ZsVoiceDatasetToken;
use crate::http_server::endpoints::media_files::upsert_upload::write_error::MediaFileWriteError;
use crate::http_server::endpoints::media_files::upsert_upload::write_error::MediaFileWriteError;
use crate::http_server::web_utils::read_multipart_field_bytes::{checked_read_multipart_bytes, read_multipart_field_as_text};
pub struct MediaFileUploadData {
@@ -81,32 +79,6 @@ pub async fn drain_multipart_request(mut multipart_payload: Multipart) -> Result
})?
.map(|field| MediaFileToken::new_from_str(&field));
},
//Some("media_file_subtype") => {
// media_file_subtype = read_multipart_field_as_text(&mut field).await
// .map_err(|err| {
// warn!("Error reading source: {:?}", &err);
// MediaFileWriteError::BadInput("Error reading media_file_subtype".to_string())
// })?
// .map(|field| MediaFileSubtype::from_str(&field))
// .transpose()
// .map_err(|err| {
// warn!("Wrong MediaFileSubtype: {:?}", &err);
// MediaFileWriteError::BadInput("Wrong MediaFileSubtype variant".to_string())
// })?;
//},
//Some("media_file_class") => {
// media_file_class = read_multipart_field_as_text(&mut field).await
// .map_err(|err| {
// warn!("Error reading source: {:?}", &err);
// MediaFileWriteError::BadInput("Error reading media_file_class".to_string())
// })?
// .map(|field| MediaFileClass::from_str(&field))
// .transpose()
// .map_err(|err| {
// warn!("Wrong MediaFileClass: {:?}", &err);
// MediaFileWriteError::BadInput("Wrong MediaFileClass variant".to_string())
// })?;
//},
Some("engine_category") => {
maybe_engine_category = read_multipart_field_as_text(&mut field).await
.map_err(|err| {
@@ -7,7 +7,6 @@ use log::warn;
use enums::by_table::media_files::media_file_animation_type::MediaFileAnimationType;
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_subtype::MediaFileSubtype;
use errors::AnyhowResult;
use tokens::tokens::media_files::MediaFileToken;
use tokens::tokens::zs_voice_datasets::ZsVoiceDatasetToken;
@@ -17,10 +17,10 @@ use enums::by_table::generic_inference_jobs::inference_job_type::InferenceJobTyp
use enums::by_table::generic_inference_jobs::inference_model_type::InferenceModelType;
use enums::common::visibility::Visibility;
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
use http_server_common::request::get_request_header_optional::get_request_header_optional;
use http_server_common::request::get_request_ip::get_request_ip;
use mysql_queries::payloads::generic_inference_args::common::watermark_type::WatermarkType;
use mysql_queries::payloads::generic_inference_args::generic_inference_args::{GenericInferenceArgs, InferenceCategoryAbbreviated, PolymorphicInferenceArgs};
use mysql_queries::payloads::generic_inference_args::live_portrait_payload::LivePortraitPayload;
use mysql_queries::payloads::generic_inference_args::live_portrait_payload::{CropDimensions, LivePortraitPayload};
use mysql_queries::queries::generic_inference::web::insert_generic_inference_job::{insert_generic_inference_job, InsertGenericInferenceArgs};
use mysql_queries::queries::idepotency_tokens::insert_idempotency_token::insert_idempotency_token;
use primitives::traits::trim_or_emptyable::TrimOrEmptyable;
@@ -32,6 +32,7 @@ use crate::configs::plans::get_correct_plan_for_session::get_correct_plan_for_se
use crate::configs::plans::plan_category::PlanCategory;
use crate::http_server::headers::get_routing_tag_header::get_routing_tag_header;
use crate::http_server::headers::has_debug_header::has_debug_header;
use crate::http_server::requests::get_request_domain_branding::{DomainBranding, get_request_domain_branding};
use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format;
use crate::http_server::web_utils::require_user_session::RequireUserSessionError;
use crate::http_server::web_utils::require_user_session_using_connection::require_user_session_using_connection;
@@ -63,6 +64,22 @@ pub struct EnqueueLivePortraitWorkflowRequest {
/// Optional visibility setting override.
creator_set_visibility: Option<Visibility>,
/// Optional crop dimensions from the top left corner.
maybe_crop: Option<EnqueueLivePortraitCropDimensions>,
}
// Top left corner, height + width of crop area
#[derive(Deserialize, ToSchema)]
pub struct EnqueueLivePortraitCropDimensions {
/// X coordinate of the top left corner of the cropped area
x: u32,
/// Y coordinate of the top left corner of the cropped area
y: u32,
/// Width in pixels of the cropped area
width: u32,
/// Height in pixels of the cropped area
height: u32,
}
#[derive(Serialize, ToSchema)]
@@ -108,13 +125,13 @@ impl std::fmt::Display for EnqueueLivePortraitWorkflowError {
}
}
/// Enqueue "live portrait" video workflows.
/// Enqueue "face mirror" (Live Portrait) video workflows.
///
/// We've renamed this as to not give away what we're doing to users.
#[utoipa::path(
post,
tag = "Workflows",
path = "/v1/workflows/enqueue_acting_face",
path = "/v1/workflows/enqueue_face_mirror",
responses(
(status = 200, description = "Success", body = EnqueueLivePortraitWorkflowSuccessResponse),
(status = 400, description = "Bad input", body = EnqueueLivePortraitWorkflowError),
@@ -189,7 +206,7 @@ pub async fn enqueue_live_portrait_workflow_handler(
EnqueueLivePortraitWorkflowError::BadInput("invalid idempotency token".to_string())
})?;
// ==================== LOOK UP MODEL INFO ==================== //
// ==================== HANDLE REQUEST ==================== //
// TODO(bt): CHECK DATABASE FOR TOKENS!
@@ -201,10 +218,35 @@ pub async fn enqueue_live_portrait_workflow_handler(
let has_paid_plan = plan.plan_slug() == "fakeyou_contributor" || plan.plan_category() == PlanCategory::Paid;
let _is_allowed_expensive_generation = is_staff || has_paid_plan;
let is_allowed_no_watermark = is_staff || has_paid_plan;
let maybe_crop = request.maybe_crop.as_ref()
.map(|crop| {
CropDimensions {
x: crop.x,
y: crop.y,
width: crop.width,
height: crop.height,
}
});
let branding = get_request_domain_branding(&http_request);
let mut watermark_type = match branding {
Some(DomainBranding::FakeYou) => Some(WatermarkType::FakeYou),
Some(DomainBranding::Storyteller) => Some(WatermarkType::Storyteller),
None => Some(WatermarkType::Storyteller),
};
if request.remove_watermark.unwrap_or(false) && is_allowed_no_watermark {
watermark_type = None;
}
let payload = LivePortraitPayload {
portrait_media_file_token: empty_media_file_token_to_null(Some(&request.source_media_file_token)),
driver_media_file_token: empty_media_file_token_to_null(Some(&request.face_driver_media_file_token)),
crop: maybe_crop,
watermark_type,
remove_watermark: None,
sleep_millis: None,
};
@@ -20,7 +20,7 @@ use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
use http_server_common::request::get_request_header_optional::get_request_header_optional;
use http_server_common::request::get_request_ip::get_request_ip;
use mysql_queries::payloads::generic_inference_args::generic_inference_args::{GenericInferenceArgs, InferenceCategoryAbbreviated, PolymorphicInferenceArgs};
use mysql_queries::payloads::generic_inference_args::workflow_payload::WorkflowArgs;
use mysql_queries::payloads::generic_inference_args::workflow_payload::{WorkflowArgs, WorkflowType};
use mysql_queries::queries::generic_inference::web::insert_generic_inference_job::{insert_generic_inference_job, InsertGenericInferenceArgs};
use mysql_queries::queries::idepotency_tokens::insert_idempotency_token::insert_idempotency_token;
use primitives::lazy_any_option_true::lazy_any_option_true;
@@ -245,6 +245,9 @@ pub async fn enqueue_studio_workflow_handler(
let coordinated_args = coordinate_workflow_args(coordinated_args, is_allowed_expensive_generation);
let inference_args = WorkflowArgs {
// Type of workflow
workflow_type: Some(WorkflowType::StorytellerStudio),
// Main text prompts
positive_prompt: coordinated_args.prompt.new_string_trim_or_empty(),
negative_prompt: request.negative_prompt.new_string_trim_or_empty(),
@@ -270,9 +273,10 @@ pub async fn enqueue_studio_workflow_handler(
use_cinematic: coordinated_args.use_cinematic,
use_face_detailer: coordinated_args.use_face_detailer,
use_upscaler: coordinated_args.use_upscaler,
remove_watermark: coordinated_args.remove_watermark,
lipsync_enabled: coordinated_args.use_lipsync,
enable_lipsync: coordinated_args.use_lipsync, // TODO(bt): We can stop writing this flag after we re-deploy the job.
remove_watermark: coordinated_args.remove_watermark,
watermark_type: None,
// TODO: Get rid of the temporary flags.
rollout_python_workflow_args: None,
@@ -19,8 +19,9 @@ use enums::common::visibility::Visibility;
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
use http_server_common::request::get_request_header_optional::get_request_header_optional;
use http_server_common::request::get_request_ip::get_request_ip;
use mysql_queries::payloads::generic_inference_args::common::watermark_type::WatermarkType;
use mysql_queries::payloads::generic_inference_args::generic_inference_args::{GenericInferenceArgs, InferenceCategoryAbbreviated, PolymorphicInferenceArgs};
use mysql_queries::payloads::generic_inference_args::workflow_payload::WorkflowArgs;
use mysql_queries::payloads::generic_inference_args::workflow_payload::{WorkflowArgs, WorkflowType};
use mysql_queries::queries::generic_inference::web::insert_generic_inference_job::{insert_generic_inference_job, InsertGenericInferenceArgs};
use mysql_queries::queries::idepotency_tokens::insert_idempotency_token::insert_idempotency_token;
use primitives::lazy_any_option_true::lazy_any_option_true;
@@ -38,6 +39,7 @@ use crate::http_server::endpoints::workflows::enqueue::vst_common::vst_request::
use crate::http_server::endpoints::workflows::enqueue::vst_common::vst_response::VstSuccessResponse;
use crate::http_server::headers::get_routing_tag_header::get_routing_tag_header;
use crate::http_server::headers::has_debug_header::has_debug_header;
use crate::http_server::requests::get_request_domain_branding::{DomainBranding, get_request_domain_branding};
use crate::http_server::session::lookup::user_session_extended::UserSessionExtended;
use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format;
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
@@ -241,10 +243,26 @@ pub async fn enqueue_video_style_transfer_workflow_handler(
};
let is_allowed_expensive_generation = is_staff || has_paid_plan;
let is_allowed_no_watermark = is_staff || has_paid_plan;
let coordinated_args = coordinate_workflow_args(coordinated_args, is_allowed_expensive_generation);
let branding = get_request_domain_branding(&http_request);
let mut watermark_type = match branding {
Some(DomainBranding::FakeYou) => Some(WatermarkType::FakeYou),
Some(DomainBranding::Storyteller) => Some(WatermarkType::Storyteller),
None => Some(WatermarkType::Storyteller),
};
if request.remove_watermark.unwrap_or(false) && is_allowed_no_watermark {
watermark_type = None;
}
let inference_args = WorkflowArgs {
// Type of workflow
workflow_type: Some(WorkflowType::VideoStyleTransfer),
// Main text prompts
positive_prompt: coordinated_args.prompt.new_string_trim_or_empty(),
negative_prompt: request.negative_prompt.new_string_trim_or_empty(),
@@ -270,9 +288,10 @@ pub async fn enqueue_video_style_transfer_workflow_handler(
use_cinematic: coordinated_args.use_cinematic,
use_face_detailer: coordinated_args.use_face_detailer,
use_upscaler: coordinated_args.use_upscaler,
remove_watermark: coordinated_args.remove_watermark,
lipsync_enabled: coordinated_args.use_lipsync,
enable_lipsync: coordinated_args.use_lipsync, // TODO(bt): We can stop writing this flag after we re-deploy the job.
remove_watermark: coordinated_args.remove_watermark,
watermark_type,
// TODO: Get rid of the temporary flags.
rollout_python_workflow_args: None,
@@ -245,6 +245,7 @@ pub async fn enqueue_comfy_ui_handler(
}
let inference_args = WorkflowArgs {
workflow_type: None, // Is this endpoint even used anymore?
maybe_lora_model: request.maybe_lora_model.clone(),
maybe_json_modifications: request.maybe_json_modifications.clone(),
maybe_workflow_config: request.maybe_workflow_config.clone(),
@@ -286,6 +287,7 @@ pub async fn enqueue_comfy_ui_handler(
use_cinematic: None,
strength: None,
frame_skip: None,
watermark_type: None,
};
info!("Creating ComfyUI job record...");
@@ -204,16 +204,14 @@ impl std::fmt::Display for EnqueueVideoStyleTransferError {
}
}
/// DEPRECATED. Use /v1/workflows/enqueue_studio or /v1/workflows/enqueue_vst
#[deprecated(note = "Use /v1/workflows/enqueue_studio")]
#[utoipa::path(
post,
tag = "Video Style Transfer",
path = "/v1/video/enqueue_vst",
responses(
(
status = 200,
description = "Enqueue Video Style Transfer",
body = EnqueueVideoStyleTransferSuccessResponse,
),
(status = 200, description = "Success", body = EnqueueVideoStyleTransferSuccessResponse),
(status = 400, description = "Bad input", body = EnqueueVideoStyleTransferError),
(status = 401, description = "Not authorized", body = EnqueueVideoStyleTransferError),
(status = 429, description = "Rate limited", body = EnqueueVideoStyleTransferError),
@@ -391,6 +389,9 @@ pub async fn enqueue_video_style_transfer_handler(
let coordinated_args = coordinate_workflow_args(coordinated_args, is_allowed_expensive_generation);
let inference_args = WorkflowArgs {
// Type of workflow left blank since this is a legacy endpoint.
workflow_type: None,
// Main text prompts
positive_prompt: coordinated_args.prompt.new_string_trim_or_empty(),
negative_prompt: request.negative_prompt.new_string_trim_or_empty(),
@@ -439,6 +440,7 @@ pub async fn enqueue_video_style_transfer_handler(
trim_start_seconds: None,
trim_end_seconds: None,
target_fps: None,
watermark_type: None,
};
info!("Creating ComfyUI job record...");
@@ -217,6 +217,7 @@ pub async fn enqueue_workflow_upload_request(
let commit_hash = request.commit_hash.clone();
let inference_args = WorkflowArgs {
workflow_type: None, // Is this endpoint even used anymore?
maybe_google_drive_link: Some(google_drive_link),
maybe_title: Some(title),
maybe_description: Some(description),
@@ -256,6 +257,7 @@ pub async fn enqueue_workflow_upload_request(
use_cinematic: None,
strength: None,
frame_skip: None,
watermark_type: None,
};
// create the inference args here
@@ -4,6 +4,7 @@ pub mod cookies;
pub mod endpoints;
pub mod headers;
pub mod middleware;
pub mod requests;
pub mod routes;
pub mod session;
pub mod validations;
@@ -0,0 +1,55 @@
use actix_web::HttpRequest;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum DomainBranding {
FakeYou,
Storyteller,
}
pub fn get_request_domain_branding(http_request: &HttpRequest) -> Option<DomainBranding> {
http_request.uri()
.host()
.and_then(|host| match host {
host if host.contains("fakeyou") => Some(DomainBranding::FakeYou),
host if host.contains("storyteller") => Some(DomainBranding::Storyteller),
_ => None,
})
}
#[cfg(test)]
mod tests {
use actix_web::test::TestRequest;
use crate::http_server::requests::get_request_domain_branding::{DomainBranding, get_request_domain_branding};
#[test]
fn fakeyou_dot_com() {
let request = TestRequest::get()
.uri("https://fakeyou.com")
.to_http_request();
assert_eq!(get_request_domain_branding(&request), Some(DomainBranding::FakeYou));
}
#[test]
fn api_dot_fakeyou_dot_com() {
let request = TestRequest::get()
.uri("https://api.fakeyou.com")
.to_http_request();
assert_eq!(get_request_domain_branding(&request), Some(DomainBranding::FakeYou));
}
#[test]
fn storyteller_dot_ai() {
let request = TestRequest::get()
.uri("https://storyteller.ai")
.to_http_request();
assert_eq!(get_request_domain_branding(&request), Some(DomainBranding::Storyteller));
}
#[test]
fn api_dot_storyteller_dot_ai() {
let request = TestRequest::get()
.uri("https://api.storyteller.ai")
.to_http_request();
assert_eq!(get_request_domain_branding(&request), Some(DomainBranding::Storyteller));
}
}
@@ -0,0 +1 @@
pub mod get_request_domain_branding;
@@ -22,7 +22,11 @@ where
>,
{
let app = app.service(web::scope("/v1/workflows")
.service(web::resource("/enqueue_acting_face")
//.service(web::resource("/enqueue_acting_face")
// .route(web::post().to(enqueue_live_portrait_workflow_handler)) // TODO: Rename to below
// .route(web::head().to(|| HttpResponse::Ok()))
//)
.service(web::resource("/enqueue_face_mirror")
.route(web::post().to(enqueue_live_portrait_workflow_handler))
.route(web::head().to(|| HttpResponse::Ok()))
)
@@ -50,15 +54,16 @@ where
InitError = (),
>,
{
//app.service(
// // NB: We don't want this to live alongside the older endpoints for comfy and workflows -
// // We don't want to give away that we're using Comfy or ComfyUI workflows as a technique.
// web::scope("/v1/video")
// .service(web::resource("/enqueue_vst")
// .route(web::post().to(enqueue_video_style_transfer_handler))
// .route(web::head().to(|| HttpResponse::Ok()))
// )
//)
app.service(
// NB: We don't want this to live alongside the older endpoints for comfy and workflows -
// We don't want to give away that we're using Comfy or ComfyUI workflows as a technique.
web::scope("/v1/video")
.service(web::resource("/enqueue_vst")
.route(web::post().to(enqueue_video_style_transfer_handler))
.route(web::head().to(|| HttpResponse::Ok()))
)
).service(
web::scope("/v1/workflow")
.service(
web::scope("/upload")