diff --git a/Cargo.lock b/Cargo.lock index f4f800f219..09bd1e309c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/Cargo.toml b/Cargo.toml index 5606bde5d2..5f4feb8c32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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", diff --git a/_sql/actions_and_analytics/storyteller_studio/list_videos_from_studio_users.sql b/_sql/actions_and_analytics/storyteller_studio/list_videos_from_studio_users.sql index f98ca2c60e..864af6a7e8 100644 --- a/_sql/actions_and_analytics/storyteller_studio/list_videos_from_studio_users.sql +++ b/_sql/actions_and_analytics/storyteller_studio/list_videos_from_studio_users.sql @@ -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; diff --git a/_sql/migrations_squashed/media_files.sql b/_sql/migrations_squashed/media_files.sql index 1af1e5245d..f4af64e8da 100644 --- a/_sql/migrations_squashed/media_files.sql +++ b/_sql/migrations_squashed/media_files.sql @@ -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. diff --git a/crates/_types/enums/src/by_table/media_files/media_file_origin_category.rs b/crates/_types/enums/src/by_table/media_files/media_file_origin_category.rs index 743fcd2510..66b24a7c05 100644 --- a/crates/_types/enums/src/by_table/media_files/media_file_origin_category.rs +++ b/crates/_types/enums/src/by_table/media_files/media_file_origin_category.rs @@ -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); } diff --git a/crates/_types/enums/src/by_table/media_files/media_file_origin_model_type.rs b/crates/_types/enums/src/by_table/media_files/media_file_origin_model_type.rs index 542385bf17..26fcfe88ae 100644 --- a/crates/_types/enums/src/by_table/media_files/media_file_origin_model_type.rs +++ b/crates/_types/enums/src/by_table/media_files/media_file_origin_model_type.rs @@ -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 { 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); + } + } } } diff --git a/crates/_types/enums/src/by_table/media_files/media_file_origin_product_category.rs b/crates/_types/enums/src/by_table/media_files/media_file_origin_product_category.rs index 5e279aa745..2fb7b37dc2 100644 --- a/crates/_types/enums/src/by_table/media_files/media_file_origin_product_category.rs +++ b/crates/_types/enums/src/by_table/media_files/media_file_origin_product_category.rs @@ -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); + } + } } } diff --git a/crates/_types/enums/src/by_table/media_files/media_file_subtype.rs b/crates/_types/enums/src/by_table/media_files/media_file_subtype.rs index 243f848c2f..c7507ac74e 100644 --- a/crates/_types/enums/src/by_table/media_files/media_file_subtype.rs +++ b/crates/_types/enums/src/by_table/media_files/media_file_subtype.rs @@ -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 { 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)); diff --git a/crates/_types/enums/src/by_table/users/user_feature_flag.rs b/crates/_types/enums/src/by_table/users/user_feature_flag.rs index b1552cd9ec..25554ba274 100644 --- a/crates/_types/enums/src/by_table/users/user_feature_flag.rs +++ b/crates/_types/enums/src/by_table/users/user_feature_flag.rs @@ -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); } diff --git a/crates/_types/enums/src/no_table/mod.rs b/crates/_types/enums/src/no_table/mod.rs index 7bb3fd4399..977ace7de9 100644 --- a/crates/_types/enums/src/no_table/mod.rs +++ b/crates/_types/enums/src/no_table/mod.rs @@ -1,2 +1,3 @@ pub mod premium_product; -pub mod style_transfer; \ No newline at end of file +pub mod style_transfer; +pub mod video_dimensions; \ No newline at end of file diff --git a/crates/_types/enums/src/no_table/video_dimensions/mod.rs b/crates/_types/enums/src/no_table/video_dimensions/mod.rs new file mode 100644 index 0000000000..6f8ed8967c --- /dev/null +++ b/crates/_types/enums/src/no_table/video_dimensions/mod.rs @@ -0,0 +1 @@ +mod video_dimensions; \ No newline at end of file diff --git a/crates/_types/enums/src/no_table/video_dimensions/video_dimensions.rs b/crates/_types/enums/src/no_table/video_dimensions/video_dimensions.rs new file mode 100644 index 0000000000..6b96ee47fc --- /dev/null +++ b/crates/_types/enums/src/no_table/video_dimensions/video_dimensions.rs @@ -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 { + match value { + "landscape" => Ok(Self::Landscape), + "portrait" => Ok(Self::Portrait), + "square" => Ok(Self::Square), + _ => Err(format!("Unknown VideoDimensions: {}", value)), + } + } + + pub fn all_variants() -> BTreeSet { + // 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()); + } + } + } + } +} diff --git a/crates/_types/enums_public/src/by_table/media_files/mod.rs b/crates/_types/enums_public/src/by_table/media_files/mod.rs new file mode 100644 index 0000000000..8e824496ab --- /dev/null +++ b/crates/_types/enums_public/src/by_table/media_files/mod.rs @@ -0,0 +1 @@ +pub mod public_media_file_model_type; \ No newline at end of file diff --git a/crates/_types/enums_public/src/by_table/media_files/public_media_file_model_type.rs b/crates/_types/enums_public/src/by_table/media_files/public_media_file_model_type.rs new file mode 100644 index 0000000000..1c9368b9c3 --- /dev/null +++ b/crates/_types/enums_public/src/by_table/media_files/public_media_file_model_type.rs @@ -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()); + } + } +} diff --git a/crates/_types/enums_public/src/by_table/mod.rs b/crates/_types/enums_public/src/by_table/mod.rs index 2ef88db4e6..5995cb6a4f 100644 --- a/crates/_types/enums_public/src/by_table/mod.rs +++ b/crates/_types/enums_public/src/by_table/mod.rs @@ -1,2 +1,3 @@ pub mod generic_inference_jobs; +pub mod media_files; pub mod model_weights; \ No newline at end of file diff --git a/crates/lib/dimensions/Cargo.toml b/crates/lib/dimensions/Cargo.toml new file mode 100644 index 0000000000..2f3903d10c --- /dev/null +++ b/crates/lib/dimensions/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "dimensions" +edition = "2018" +version = "0.0.1" +authors = [ + "Brandon Thomas ", + "Brandon Thomas ", +] +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 diff --git a/crates/lib/dimensions/src/lib.rs b/crates/lib/dimensions/src/lib.rs new file mode 100644 index 0000000000..1b83d9f365 --- /dev/null +++ b/crates/lib/dimensions/src/lib.rs @@ -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)] diff --git a/crates/lib/mysql_queries/src/payloads/generic_inference_args/common/mod.rs b/crates/lib/mysql_queries/src/payloads/generic_inference_args/common/mod.rs new file mode 100644 index 0000000000..7713b3d99c --- /dev/null +++ b/crates/lib/mysql_queries/src/payloads/generic_inference_args/common/mod.rs @@ -0,0 +1 @@ +pub mod watermark_type; \ No newline at end of file diff --git a/crates/lib/mysql_queries/src/payloads/generic_inference_args/common/watermark_type.rs b/crates/lib/mysql_queries/src/payloads/generic_inference_args/common/watermark_type.rs new file mode 100644 index 0000000000..ed1dd8a121 --- /dev/null +++ b/crates/lib/mysql_queries/src/payloads/generic_inference_args/common/watermark_type.rs @@ -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 is None. + #[serde(rename = "n")] // NB: DO NOT CHANGE. It could break live jobs. Renamed to be fewer bytes. + NoWatermark, +} diff --git a/crates/lib/mysql_queries/src/payloads/generic_inference_args/live_portrait_payload.rs b/crates/lib/mysql_queries/src/payloads/generic_inference_args/live_portrait_payload.rs index 2a75fbb394..40f19358d7 100644 --- a/crates/lib/mysql_queries/src/payloads/generic_inference_args/live_portrait_payload.rs +++ b/crates/lib/mysql_queries/src/payloads/generic_inference_args/live_portrait_payload.rs @@ -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, + #[serde(rename = "c")] + #[serde(skip_serializing_if = "Option::is_none")] + pub crop: Option, + #[serde(rename = "rm")] #[serde(skip_serializing_if = "Option::is_none")] pub remove_watermark: Option, + #[serde(rename = "w")] + #[serde(skip_serializing_if = "Option::is_none")] + pub watermark_type: Option, + /// This is a debugging flag. #[serde(rename = "sp")] #[serde(skip_serializing_if = "Option::is_none")] pub sleep_millis: Option, } + +#[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, +} diff --git a/crates/lib/mysql_queries/src/payloads/generic_inference_args/mod.rs b/crates/lib/mysql_queries/src/payloads/generic_inference_args/mod.rs index fccaeb96e6..548c874ec4 100644 --- a/crates/lib/mysql_queries/src/payloads/generic_inference_args/mod.rs +++ b/crates/lib/mysql_queries/src/payloads/generic_inference_args/mod.rs @@ -1,3 +1,4 @@ +pub mod common; pub mod generic_inference_args; pub mod image_generation_payload; pub mod lipsync_payload; diff --git a/crates/lib/mysql_queries/src/payloads/generic_inference_args/workflow_payload.rs b/crates/lib/mysql_queries/src/payloads/generic_inference_args/workflow_payload.rs index d168c7b8ad..e4da0372ed 100644 --- a/crates/lib/mysql_queries/src/payloads/generic_inference_args/workflow_payload.rs +++ b/crates/lib/mysql_queries/src/payloads/generic_inference_args/workflow_payload.rs @@ -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, + #[serde(rename = "lora")] #[serde(skip_serializing_if = "Option::is_none")] pub maybe_lora_model: Option, @@ -154,6 +170,10 @@ pub struct WorkflowArgs { #[serde(skip_serializing_if = "Option::is_none")] pub remove_watermark: Option, + #[serde(rename = "wt")] + #[serde(skip_serializing_if = "Option::is_none")] + pub watermark_type: Option, + // 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")] diff --git a/crates/lib/mysql_queries/src/queries/media_files/create/insert_media_file_from_comfy_ui.rs b/crates/lib/mysql_queries/src/queries/media_files/create/insert_media_file_from_comfy_ui.rs index 07f95431da..7e5313608f 100644 --- a/crates/lib/mysql_queries/src/queries/media_files/create/insert_media_file_from_comfy_ui.rs +++ b/crates/lib/mysql_queries/src/queries/media_files/create/insert_media_file_from_comfy_ui.rs @@ -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, + pub maybe_model_type: Option, + 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, diff --git a/crates/lib/mysql_queries/src/queries/media_files/create/insert_media_file_from_file_upload.rs b/crates/lib/mysql_queries/src/queries/media_files/create/insert_media_file_from_file_upload.rs index 348152e8a5..0285b3d242 100644 --- a/crates/lib/mysql_queries/src/queries/media_files/create/insert_media_file_from_file_upload.rs +++ b/crates/lib/mysql_queries/src/queries/media_files/create/insert_media_file_from_file_upload.rs @@ -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 = None; diff --git a/crates/lib/mysql_queries/src/queries/media_files/upsert/upsert_media_file_from_file_upload.rs b/crates/lib/mysql_queries/src/queries/media_files/upsert/upsert_media_file_from_file_upload.rs index a9955faa92..d074a9198e 100644 --- a/crates/lib/mysql_queries/src/queries/media_files/upsert/upsert_media_file_from_file_upload.rs +++ b/crates/lib/mysql_queries/src/queries/media_files/upsert/upsert_media_file_from_file_upload.rs @@ -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 = None; diff --git a/crates/lib/password/Cargo.toml b/crates/lib/password/Cargo.toml index d24c3cb5c4..d152ef798f 100644 --- a/crates/lib/password/Cargo.toml +++ b/crates/lib/password/Cargo.toml @@ -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 diff --git a/crates/service/job/inference_job/src/job/job_types/workflow/live_portrait/process_live_portrait_job.rs b/crates/service/job/inference_job/src/job/job_types/workflow/live_portrait/process_live_portrait_job.rs index 0dd10616a9..5ba6d12515 100644 --- a/crates/service/job/inference_job/src/job/job_types/workflow/live_portrait/process_live_portrait_job.rs +++ b/crates/service/job/inference_job/src/job/job_types/workflow/live_portrait/process_live_portrait_job.rs @@ -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), diff --git a/crates/service/job/inference_job/src/job/job_types/workflow/process_single_workflow_job.rs b/crates/service/job/inference_job/src/job/job_types/workflow/process_single_workflow_job.rs index 4376b6f0a5..aa8a98b871 100644 --- a/crates/service/job/inference_job/src/job/job_types/workflow/process_single_workflow_job.rs +++ b/crates/service/job/inference_job/src/job/job_types/workflow/process_single_workflow_job.rs @@ -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? } }; diff --git a/crates/service/job/inference_job/src/job/job_types/workflow/video_style_transfer/process_video_style_transfer_job.rs b/crates/service/job/inference_job/src/job/job_types/workflow/video_style_transfer/process_video_style_transfer_job.rs index 23a62eba78..db2db30bf9 100644 --- a/crates/service/job/inference_job/src/job/job_types/workflow/video_style_transfer/process_video_style_transfer_job.rs +++ b/crates/service/job/inference_job/src/job/job_types/workflow/video_style_transfer/process_video_style_transfer_job.rs @@ -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}; diff --git a/crates/service/job/inference_job/src/job/job_types/workflow/video_style_transfer/steps/validate_and_save_results.rs b/crates/service/job/inference_job/src/job/job_types/workflow/video_style_transfer/steps/validate_and_save_results.rs index 4aea27478a..314de55d52 100644 --- a/crates/service/job/inference_job/src/job/job_types/workflow/video_style_transfer/steps/validate_and_save_results.rs +++ b/crates/service/job/inference_job/src/job/job_types/workflow/video_style_transfer/steps/validate_and_save_results.rs @@ -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 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), diff --git a/crates/service/web/storyteller_web/src/docs/api_doc.rs b/crates/service/web/storyteller_web/src/docs/api_doc.rs index 27f37aa638..f75f02b5b3 100644 --- a/crates/service/web/storyteller_web/src/docs/api_doc.rs +++ b/crates/service/web/storyteller_web/src/docs/api_doc.rs @@ -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, diff --git a/crates/service/web/storyteller_web/src/http_server/common_responses/media_file_origin_details.rs b/crates/service/web/storyteller_web/src/http_server/common_responses/media_file_origin_details.rs index 11aaaccbe1..f32433ed9a 100644 --- a/crates/service/web/storyteller_web/src/http_server/common_responses/media_file_origin_details.rs +++ b/crates/service/web/storyteller_web/src/http_server/common_responses/media_file_origin_details.rs @@ -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, diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/animation/enqueue_face_animation.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/animation/enqueue_face_animation.rs index b6844f737c..106031fd94 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/animation/enqueue_face_animation.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/animation/enqueue_face_animation.rs @@ -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 ==================== // diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/beta_keys/list_beta_keys_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/beta_keys/list_beta_keys_handler.rs index eecbe12f12..72507e7f69 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/beta_keys/list_beta_keys_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/beta_keys/list_beta_keys_handler.rs @@ -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}; diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/engine/create_scene_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/engine/create_scene_handler.rs index 13792cfcfa..69565fa61a 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/engine/create_scene_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/engine/create_scene_handler.rs @@ -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 { diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/get/get_media_file_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/get/get_media_file_handler.rs index 55814c7445..897d2d1812 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/get/get_media_file_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/get/get_media_file_handler.rs @@ -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, + /// 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, /// 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, diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_featured_media_files_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_featured_media_files_handler.rs index 60ad04dede..bea41230e7 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_featured_media_files_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_featured_media_files_handler.rs @@ -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, + pub maybe_origin_model_type: Option, #[deprecated(note="Use MediaFileOriginDetails instead")] pub maybe_origin_model_token: Option, @@ -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, diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_media_files_by_batch_token_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_media_files_by_batch_token_handler.rs index 4d7dd7c98c..e34b0c1bdf 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_media_files_by_batch_token_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_media_files_by_batch_token_handler.rs @@ -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, + pub maybe_origin_model_type: Option, #[deprecated(note="Use MediaFileOriginDetails instead")] pub maybe_origin_model_token: Option, @@ -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, diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_media_files_for_user_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_media_files_for_user_handler.rs index 15d2c56f31..7a913bfb94 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_media_files_for_user_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_media_files_for_user_handler.rs @@ -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, + pub maybe_origin_model_type: Option, #[deprecated(note="Use MediaFileOriginDetails instead")] pub maybe_origin_model_token: Option, @@ -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, diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_media_files_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_media_files_handler.rs index 947aa392a6..98f77c87d3 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_media_files_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_media_files_handler.rs @@ -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, + pub maybe_origin_model_type: Option, #[deprecated(note="Use MediaFileOriginDetails instead")] pub maybe_origin_model_token: Option, @@ -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, diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_pinned_media_files_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_pinned_media_files_handler.rs index c183e9168e..5f0cae07b5 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_pinned_media_files_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/list/list_pinned_media_files_handler.rs @@ -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, + pub maybe_origin_model_type: Option, #[deprecated(note="Use MediaFileOriginDetails instead")] pub maybe_origin_model_token: Option, @@ -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, diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/search/search_featured_media_files_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/search/search_featured_media_files_handler.rs index b952db2b59..26a2b32f26 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/search/search_featured_media_files_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/search/search_featured_media_files_handler.rs @@ -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, - // #[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, - - // #[deprecated(note="Use MediaFileOriginDetails instead")] - // pub maybe_origin_model_token: Option, - - // /// Details where the media file came from. - // pub origin: MediaFileOriginDetails, - /// URL to the media file. pub public_bucket_path: String, diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/search/search_session_media_files_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/search/search_session_media_files_handler.rs index 725c7ed540..8a462ff97c 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/search/search_session_media_files_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/search/search_session_media_files_handler.rs @@ -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, - // #[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, - - // #[deprecated(note="Use MediaFileOriginDetails instead")] - // pub maybe_origin_model_token: Option, - - // /// Details where the media file came from. - // pub origin: MediaFileOriginDetails, - /// URL to the media file. pub public_bucket_path: String, diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_audio_media_file_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_audio_media_file_handler.rs index 6e12fa5452..05e7819a6c 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_audio_media_file_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_audio_media_file_handler.rs @@ -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. /// diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_engine_asset/drain_multipart_request.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_engine_asset/drain_multipart_request.rs index 3b62340d9d..3d372084b0 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_engine_asset/drain_multipart_request.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_engine_asset/drain_multipart_request.rs @@ -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| { diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_image_media_file_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_image_media_file_handler.rs index d3807566a9..ae06e2151e 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_image_media_file_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_image_media_file_handler.rs @@ -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. /// diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_new_scene_media_file_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_new_scene_media_file_handler.rs index 87b9ebd2de..9e3eb48fe3 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_new_scene_media_file_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_new_scene_media_file_handler.rs @@ -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. /// diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_new_video_media_file_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_new_video_media_file_handler.rs index fc71c81f18..c37f8f1e6e 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_new_video_media_file_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_new_video_media_file_handler.rs @@ -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. /// diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_saved_scene_media_file_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_saved_scene_media_file_handler.rs index 8996f45723..eb71c6d425 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_saved_scene_media_file_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_saved_scene_media_file_handler.rs @@ -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)] diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_scene_snapshot_media_file_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_scene_snapshot_media_file_handler.rs index 9aec26d785..ff90ebc603 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_scene_snapshot_media_file_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upload/upload_scene_snapshot_media_file_handler.rs @@ -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. /// diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upsert_upload/write_engine_asset/drain_multipart_request.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upsert_upload/write_engine_asset/drain_multipart_request.rs index f6fb4b90e0..76c07da2b8 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upsert_upload/write_engine_asset/drain_multipart_request.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upsert_upload/write_engine_asset/drain_multipart_request.rs @@ -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| { diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upsert_upload/write_scene_file/drain_multipart_request.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upsert_upload/write_scene_file/drain_multipart_request.rs index 2fccd6d1af..0de10520b8 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upsert_upload/write_scene_file/drain_multipart_request.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/upsert_upload/write_scene_file/drain_multipart_request.rs @@ -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; diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue/enqueue_live_portrait_workflow_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue/enqueue_live_portrait_workflow_handler.rs index 2056c24e2c..69a8b0798f 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue/enqueue_live_portrait_workflow_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue/enqueue_live_portrait_workflow_handler.rs @@ -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, + + /// Optional crop dimensions from the top left corner. + maybe_crop: Option, +} + +// 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, }; diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue/enqueue_studio_workflow_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue/enqueue_studio_workflow_handler.rs index 23ee29889b..133fdc55fc 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue/enqueue_studio_workflow_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue/enqueue_studio_workflow_handler.rs @@ -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, diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue/enqueue_video_style_transfer_workflow_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue/enqueue_video_style_transfer_workflow_handler.rs index 0d69bc3724..18df2dcee7 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue/enqueue_video_style_transfer_workflow_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue/enqueue_video_style_transfer_workflow_handler.rs @@ -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, diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue_comfy_ui_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue_comfy_ui_handler.rs index f09a549404..14061a8d7a 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue_comfy_ui_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue_comfy_ui_handler.rs @@ -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..."); diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue_video_style_transfer_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue_video_style_transfer_handler.rs index 148df172b9..4598fff45c 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue_video_style_transfer_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue_video_style_transfer_handler.rs @@ -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..."); diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue_workflow_upload_request.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue_workflow_upload_request.rs index 416631d7e7..d34276b280 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue_workflow_upload_request.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/workflows/enqueue_workflow_upload_request.rs @@ -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 diff --git a/crates/service/web/storyteller_web/src/http_server/mod.rs b/crates/service/web/storyteller_web/src/http_server/mod.rs index a23a3a22be..612daf5d06 100644 --- a/crates/service/web/storyteller_web/src/http_server/mod.rs +++ b/crates/service/web/storyteller_web/src/http_server/mod.rs @@ -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; diff --git a/crates/service/web/storyteller_web/src/http_server/requests/get_request_domain_branding.rs b/crates/service/web/storyteller_web/src/http_server/requests/get_request_domain_branding.rs new file mode 100644 index 0000000000..c6f72ece52 --- /dev/null +++ b/crates/service/web/storyteller_web/src/http_server/requests/get_request_domain_branding.rs @@ -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 { + 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)); + } +} diff --git a/crates/service/web/storyteller_web/src/http_server/requests/mod.rs b/crates/service/web/storyteller_web/src/http_server/requests/mod.rs new file mode 100644 index 0000000000..3fa9521ab5 --- /dev/null +++ b/crates/service/web/storyteller_web/src/http_server/requests/mod.rs @@ -0,0 +1 @@ +pub mod get_request_domain_branding; \ No newline at end of file diff --git a/crates/service/web/storyteller_web/src/http_server/routes/workflow_routes.rs b/crates/service/web/storyteller_web/src/http_server/routes/workflow_routes.rs index f86837e74a..1836ebe4f4 100644 --- a/crates/service/web/storyteller_web/src/http_server/routes/workflow_routes.rs +++ b/crates/service/web/storyteller_web/src/http_server/routes/workflow_routes.rs @@ -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")