mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-31 15:55:54 -04:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
acc16c15fb | ||
|
|
1d5d63fda1 | ||
|
|
6af5cc7d0b | ||
|
|
a7cd9f3b2f |
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\n INSERT INTO media_files\n SET\n token = ?,\n\n media_class = ?,\n media_type = ?,\n\n is_user_upload = ?,\n is_intermediate_system_file = ?,\n\n origin_category = ?, \n origin_product_category = ?, \n maybe_origin_model_type = ?, \n maybe_origin_model_token = ?, \n maybe_origin_filename = ?,\n\n maybe_batch_token = ?,\n\n maybe_mime_type = ?,\n file_size_bytes = ?,\n maybe_duration_millis = ?,\n maybe_audio_encoding = ?, \n maybe_video_encoding = ?, \n maybe_frame_width = ?, \n maybe_frame_height = ?,\n maybe_prompt_token = ?,\n checksum_sha2 = ?,\n \n maybe_engine_category = ?,\n\n maybe_title = ?,\n maybe_text_transcript = ?,\n\n maybe_scene_source_media_file_token = ?,\n\n public_bucket_directory_hash = ?, \n maybe_public_bucket_prefix = ?, \n maybe_public_bucket_extension = ?, \n\n maybe_creator_user_token = ?, \n maybe_creator_anonymous_visitor_token = ?, \n\n creator_ip_address = ?, \n creator_set_visibility = ?, \n\n maybe_creator_file_synthetic_id = ?, \n maybe_creator_category_synthetic_id = ?,\n\n extra_file_modification_info = ?,\n\n maybe_generation_provider = ?,\n\n platform_type = ?,\n\n maybe_cover_image_media_file_token = ?,\n\n maybe_mod_user_token = ?,\n is_generated_on_prem = ?,\n generated_by_worker = ?,\n generated_by_cluster = ?\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 41
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "1c74e9c2dcc9205e2c9fe60a6de0828208e497e68560246e588092bafd03eb59"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO media_files\nSET\n token = ?,\n\n media_class = ?,\n media_type = ?,\n\n origin_category = ?,\n origin_product_category = ?,\n\n maybe_engine_category = ?,\n maybe_animation_type = ?,\n\n maybe_mime_type = ?,\n file_size_bytes = ?,\n\n checksum_sha2 = ?,\n\n public_bucket_directory_hash = ?,\n maybe_public_bucket_prefix = ?,\n maybe_public_bucket_extension = ?,\n\n maybe_creator_user_token = ?,\n maybe_creator_anonymous_visitor_token = ?,\n creator_ip_address = ?,\n\n creator_set_visibility = ?,\n\n maybe_creator_file_synthetic_id = ?,\n maybe_creator_category_synthetic_id = ?,\n\n is_user_upload = TRUE,\n\n maybe_origin_model_type = NULL,\n maybe_origin_model_token = NULL\n\nON DUPLICATE KEY UPDATE\n\n media_class = ?,\n media_type = ?,\n\n origin_category = ?,\n origin_product_category = ?,\n\n maybe_engine_category = ?,\n maybe_animation_type = ?,\n\n maybe_mime_type = ?,\n file_size_bytes = ?,\n\n checksum_sha2 = ?,\n\n public_bucket_directory_hash = ?,\n maybe_public_bucket_prefix = ?,\n maybe_public_bucket_extension = ?,\n\n maybe_creator_user_token = ?,\n maybe_creator_anonymous_visitor_token = ?,\n creator_ip_address = ?,\n\n creator_set_visibility = ?,\n\n maybe_creator_file_synthetic_id = ?,\n maybe_creator_category_synthetic_id = ?,\n\n is_user_upload = TRUE,\n\n maybe_origin_model_type = NULL,\n maybe_origin_model_token = NULL\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 37
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "3af0a10ab0ed65daba9363605db4ddae9a60a2177369c58046abdee9ad1e91ee"
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO media_files\nSET\n token = ?,\n\n media_class = ?,\n media_type = ?,\n\n origin_category = ?,\n origin_product_category = ?,\n\n maybe_engine_category = ?,\n maybe_animation_type = ?,\n\n maybe_media_subtype = ?,\n maybe_mime_type = ?,\n file_size_bytes = ?,\n\n checksum_sha2 = ?,\n\n public_bucket_directory_hash = ?,\n maybe_public_bucket_prefix = ?,\n maybe_public_bucket_extension = ?,\n\n maybe_creator_user_token = ?,\n maybe_creator_anonymous_visitor_token = ?,\n creator_ip_address = ?,\n\n creator_set_visibility = ?,\n\n maybe_creator_file_synthetic_id = ?,\n maybe_creator_category_synthetic_id = ?,\n\n is_user_upload = TRUE,\n\n maybe_origin_model_type = NULL,\n maybe_origin_model_token = NULL\n\nON DUPLICATE KEY UPDATE\n\n media_class = ?,\n media_type = ?,\n\n origin_category = ?,\n origin_product_category = ?,\n\n maybe_engine_category = ?,\n maybe_animation_type = ?,\n\n maybe_media_subtype = ?,\n maybe_mime_type = ?,\n file_size_bytes = ?,\n\n checksum_sha2 = ?,\n\n public_bucket_directory_hash = ?,\n maybe_public_bucket_prefix = ?,\n maybe_public_bucket_extension = ?,\n\n maybe_creator_user_token = ?,\n maybe_creator_anonymous_visitor_token = ?,\n creator_ip_address = ?,\n\n creator_set_visibility = ?,\n\n maybe_creator_file_synthetic_id = ?,\n maybe_creator_category_synthetic_id = ?,\n\n is_user_upload = TRUE,\n\n maybe_origin_model_type = NULL,\n maybe_origin_model_token = NULL\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 39
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "55706e6ac35be221b9d9c6e8b247812944c61941964bb53815d31dc30d506be8"
|
||||
}
|
||||
+43
-54
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n m.token as `token: tokens::tokens::media_files::MediaFileToken`,\n\n m.media_class as `media_class: enums::by_table::media_files::media_file_class::MediaFileClass`,\n m.media_type as `media_type: enums::by_table::media_files::media_file_type::MediaFileType`,\n\n m.maybe_engine_category as `maybe_engine_category: enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory`,\n m.maybe_animation_type as `maybe_animation_type: enums::by_table::media_files::media_file_animation_type::MediaFileAnimationType`,\n\n m.maybe_media_subtype as `maybe_media_subtype: enums::by_table::media_files::media_file_subtype::MediaFileSubtype`,\n\n m.maybe_mime_type,\n\n users.token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n users.username as maybe_creator_username,\n users.display_name as maybe_creator_display_name,\n users.email_gravatar_hash as maybe_creator_gravatar_hash,\n\n m.maybe_creator_anonymous_visitor_token as `maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken`,\n\n m.maybe_batch_token as `maybe_batch_token: tokens::tokens::batch_generations::BatchGenerationToken`,\n\n m.maybe_style_transfer_source_media_file_token as `maybe_style_transfer_source_media_file_token: tokens::tokens::media_files::MediaFileToken`,\n m.maybe_scene_source_media_file_token as `maybe_scene_source_media_file_token: tokens::tokens::media_files::MediaFileToken`,\n\n m.maybe_title,\n m.maybe_text_transcript,\n\n m.maybe_origin_filename,\n\n m.maybe_duration_millis,\n\n m.maybe_prompt_token as `maybe_prompt_token: tokens::tokens::prompts::PromptToken`,\n prompts.maybe_other_args as maybe_other_prompt_args,\n\n media_file_cover_image.public_bucket_directory_hash as maybe_file_cover_image_public_bucket_hash,\n media_file_cover_image.maybe_public_bucket_prefix as maybe_file_cover_image_public_bucket_prefix,\n media_file_cover_image.maybe_public_bucket_extension as maybe_file_cover_image_public_bucket_extension,\n\n m.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,\n\n m.is_user_upload,\n m.is_intermediate_system_file,\n\n model_weights.token as `maybe_model_weights_token: tokens::tokens::model_weights::ModelWeightToken`,\n model_weights.title as maybe_model_weights_title,\n model_weights.weights_type as `maybe_model_weights_type: enums::by_table::model_weights::weights_types::WeightsType`,\n model_weights.weights_category as `maybe_model_weights_category: enums::by_table::model_weights::weights_category::WeightsCategory`,\n\n model_weight_cover_image.public_bucket_directory_hash as maybe_model_cover_image_public_bucket_hash,\n model_weight_cover_image.maybe_public_bucket_prefix as maybe_model_cover_image_public_bucket_prefix,\n model_weight_cover_image.maybe_public_bucket_extension as maybe_model_cover_image_public_bucket_extension,\n\n model_weight_creator.token as `maybe_model_weight_creator_user_token: tokens::tokens::users::UserToken`,\n model_weight_creator.username as maybe_model_weight_creator_username,\n model_weight_creator.display_name as maybe_model_weight_creator_display_name,\n model_weight_creator.email_gravatar_hash as maybe_model_weight_creator_gravatar_hash,\n\n m.extra_file_modification_info,\n\n m.public_bucket_directory_hash,\n m.maybe_public_bucket_prefix,\n m.maybe_public_bucket_extension,\n\n entity_stats.ratings_positive_count as maybe_ratings_positive_count,\n entity_stats.ratings_negative_count as maybe_ratings_negative_count,\n entity_stats.bookmark_count as maybe_bookmark_count,\n\n featured_items.entity_token IS NOT NULL AS is_featured,\n\n m.created_at,\n m.updated_at\n\nFROM media_files AS m\nLEFT OUTER JOIN users\n ON m.maybe_creator_user_token = users.token\nLEFT OUTER JOIN model_weights\n ON m.maybe_origin_model_token = model_weights.token\nLEFT OUTER JOIN media_files as media_file_cover_image\n ON media_file_cover_image.token = m.maybe_cover_image_media_file_token\nLEFT OUTER JOIN media_files as model_weight_cover_image\n ON model_weight_cover_image.token = model_weights.maybe_cover_image_media_file_token\nLEFT OUTER JOIN users as model_weight_creator\n ON model_weight_creator.token = model_weights.creator_user_token\nLEFT OUTER JOIN entity_stats\n ON entity_stats.entity_type = \"media_file\"\n AND entity_stats.entity_token = m.token\nLEFT OUTER JOIN prompts\n ON prompts.token = m.maybe_prompt_token\nLEFT OUTER JOIN featured_items\n ON featured_items.entity_type = 'media_file'\n AND featured_items.entity_token = m.token\n AND featured_items.deleted_at IS NULL\nWHERE\n m.token = ?\n ",
|
||||
"query": "\nSELECT\n m.token as `token: tokens::tokens::media_files::MediaFileToken`,\n\n m.media_class as `media_class: enums::by_table::media_files::media_file_class::MediaFileClass`,\n m.media_type as `media_type: enums::by_table::media_files::media_file_type::MediaFileType`,\n\n m.maybe_engine_category as `maybe_engine_category: enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory`,\n m.maybe_animation_type as `maybe_animation_type: enums::by_table::media_files::media_file_animation_type::MediaFileAnimationType`,\n\n m.maybe_mime_type,\n\n users.token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n users.username as maybe_creator_username,\n users.display_name as maybe_creator_display_name,\n users.email_gravatar_hash as maybe_creator_gravatar_hash,\n\n m.maybe_creator_anonymous_visitor_token as `maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken`,\n\n m.maybe_batch_token as `maybe_batch_token: tokens::tokens::batch_generations::BatchGenerationToken`,\n\n m.maybe_style_transfer_source_media_file_token as `maybe_style_transfer_source_media_file_token: tokens::tokens::media_files::MediaFileToken`,\n m.maybe_scene_source_media_file_token as `maybe_scene_source_media_file_token: tokens::tokens::media_files::MediaFileToken`,\n\n m.maybe_title,\n m.maybe_text_transcript,\n\n m.maybe_origin_filename,\n\n m.maybe_duration_millis,\n\n m.maybe_prompt_token as `maybe_prompt_token: tokens::tokens::prompts::PromptToken`,\n prompts.maybe_other_args as maybe_other_prompt_args,\n\n media_file_cover_image.public_bucket_directory_hash as maybe_file_cover_image_public_bucket_hash,\n media_file_cover_image.maybe_public_bucket_prefix as maybe_file_cover_image_public_bucket_prefix,\n media_file_cover_image.maybe_public_bucket_extension as maybe_file_cover_image_public_bucket_extension,\n\n m.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,\n\n m.is_user_upload,\n m.is_intermediate_system_file,\n\n model_weights.token as `maybe_model_weights_token: tokens::tokens::model_weights::ModelWeightToken`,\n model_weights.title as maybe_model_weights_title,\n model_weights.weights_type as `maybe_model_weights_type: enums::by_table::model_weights::weights_types::WeightsType`,\n model_weights.weights_category as `maybe_model_weights_category: enums::by_table::model_weights::weights_category::WeightsCategory`,\n\n model_weight_cover_image.public_bucket_directory_hash as maybe_model_cover_image_public_bucket_hash,\n model_weight_cover_image.maybe_public_bucket_prefix as maybe_model_cover_image_public_bucket_prefix,\n model_weight_cover_image.maybe_public_bucket_extension as maybe_model_cover_image_public_bucket_extension,\n\n model_weight_creator.token as `maybe_model_weight_creator_user_token: tokens::tokens::users::UserToken`,\n model_weight_creator.username as maybe_model_weight_creator_username,\n model_weight_creator.display_name as maybe_model_weight_creator_display_name,\n model_weight_creator.email_gravatar_hash as maybe_model_weight_creator_gravatar_hash,\n\n m.extra_file_modification_info,\n\n m.public_bucket_directory_hash,\n m.maybe_public_bucket_prefix,\n m.maybe_public_bucket_extension,\n\n entity_stats.ratings_positive_count as maybe_ratings_positive_count,\n entity_stats.ratings_negative_count as maybe_ratings_negative_count,\n entity_stats.bookmark_count as maybe_bookmark_count,\n\n featured_items.entity_token IS NOT NULL AS is_featured,\n\n m.created_at,\n m.updated_at\n\nFROM media_files AS m\nLEFT OUTER JOIN users\n ON m.maybe_creator_user_token = users.token\nLEFT OUTER JOIN model_weights\n ON m.maybe_origin_model_token = model_weights.token\nLEFT OUTER JOIN media_files as media_file_cover_image\n ON media_file_cover_image.token = m.maybe_cover_image_media_file_token\nLEFT OUTER JOIN media_files as model_weight_cover_image\n ON model_weight_cover_image.token = model_weights.maybe_cover_image_media_file_token\nLEFT OUTER JOIN users as model_weight_creator\n ON model_weight_creator.token = model_weights.creator_user_token\nLEFT OUTER JOIN entity_stats\n ON entity_stats.entity_type = \"media_file\"\n AND entity_stats.entity_token = m.token\nLEFT OUTER JOIN prompts\n ON prompts.token = m.maybe_prompt_token\nLEFT OUTER JOIN featured_items\n ON featured_items.entity_type = 'media_file'\n AND featured_items.entity_token = m.token\n AND featured_items.deleted_at IS NULL\nWHERE\n m.token = ?\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -55,16 +55,6 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "maybe_media_subtype: enums::by_table::media_files::media_file_subtype::MediaFileSubtype",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "maybe_mime_type",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -74,7 +64,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"ordinal": 6,
|
||||
"name": "maybe_creator_user_token: tokens::tokens::users::UserToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -84,7 +74,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"ordinal": 7,
|
||||
"name": "maybe_creator_username",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -94,7 +84,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"ordinal": 8,
|
||||
"name": "maybe_creator_display_name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -104,7 +94,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 10,
|
||||
"ordinal": 9,
|
||||
"name": "maybe_creator_gravatar_hash",
|
||||
"type_info": {
|
||||
"type": "String",
|
||||
@@ -114,7 +104,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 11,
|
||||
"ordinal": 10,
|
||||
"name": "maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -124,7 +114,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 12,
|
||||
"ordinal": 11,
|
||||
"name": "maybe_batch_token: tokens::tokens::batch_generations::BatchGenerationToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -134,7 +124,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 13,
|
||||
"ordinal": 12,
|
||||
"name": "maybe_style_transfer_source_media_file_token: tokens::tokens::media_files::MediaFileToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -144,7 +134,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 14,
|
||||
"ordinal": 13,
|
||||
"name": "maybe_scene_source_media_file_token: tokens::tokens::media_files::MediaFileToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -154,7 +144,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 15,
|
||||
"ordinal": 14,
|
||||
"name": "maybe_title",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -164,7 +154,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 16,
|
||||
"ordinal": 15,
|
||||
"name": "maybe_text_transcript",
|
||||
"type_info": {
|
||||
"type": "Blob",
|
||||
@@ -174,7 +164,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 17,
|
||||
"ordinal": 16,
|
||||
"name": "maybe_origin_filename",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -184,7 +174,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 18,
|
||||
"ordinal": 17,
|
||||
"name": "maybe_duration_millis",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
@@ -194,7 +184,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 19,
|
||||
"ordinal": 18,
|
||||
"name": "maybe_prompt_token: tokens::tokens::prompts::PromptToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -204,7 +194,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 20,
|
||||
"ordinal": 19,
|
||||
"name": "maybe_other_prompt_args",
|
||||
"type_info": {
|
||||
"type": "Blob",
|
||||
@@ -214,7 +204,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 21,
|
||||
"ordinal": 20,
|
||||
"name": "maybe_file_cover_image_public_bucket_hash",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -224,7 +214,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 22,
|
||||
"ordinal": 21,
|
||||
"name": "maybe_file_cover_image_public_bucket_prefix",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -234,7 +224,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 23,
|
||||
"ordinal": 22,
|
||||
"name": "maybe_file_cover_image_public_bucket_extension",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -244,7 +234,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 24,
|
||||
"ordinal": 23,
|
||||
"name": "creator_set_visibility: enums::common::visibility::Visibility",
|
||||
"type_info": {
|
||||
"type": "String",
|
||||
@@ -254,7 +244,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 25,
|
||||
"ordinal": 24,
|
||||
"name": "is_user_upload",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
@@ -264,7 +254,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 26,
|
||||
"ordinal": 25,
|
||||
"name": "is_intermediate_system_file",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
@@ -274,7 +264,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 27,
|
||||
"ordinal": 26,
|
||||
"name": "maybe_model_weights_token: tokens::tokens::model_weights::ModelWeightToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -284,7 +274,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 28,
|
||||
"ordinal": 27,
|
||||
"name": "maybe_model_weights_title",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -294,7 +284,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 29,
|
||||
"ordinal": 28,
|
||||
"name": "maybe_model_weights_type: enums::by_table::model_weights::weights_types::WeightsType",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -304,7 +294,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 30,
|
||||
"ordinal": 29,
|
||||
"name": "maybe_model_weights_category: enums::by_table::model_weights::weights_category::WeightsCategory",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -314,7 +304,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 31,
|
||||
"ordinal": 30,
|
||||
"name": "maybe_model_cover_image_public_bucket_hash",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -324,7 +314,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 32,
|
||||
"ordinal": 31,
|
||||
"name": "maybe_model_cover_image_public_bucket_prefix",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -334,7 +324,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 33,
|
||||
"ordinal": 32,
|
||||
"name": "maybe_model_cover_image_public_bucket_extension",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -344,7 +334,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 34,
|
||||
"ordinal": 33,
|
||||
"name": "maybe_model_weight_creator_user_token: tokens::tokens::users::UserToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -354,7 +344,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 35,
|
||||
"ordinal": 34,
|
||||
"name": "maybe_model_weight_creator_username",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -364,7 +354,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 36,
|
||||
"ordinal": 35,
|
||||
"name": "maybe_model_weight_creator_display_name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -374,7 +364,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 37,
|
||||
"ordinal": 36,
|
||||
"name": "maybe_model_weight_creator_gravatar_hash",
|
||||
"type_info": {
|
||||
"type": "String",
|
||||
@@ -384,7 +374,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 38,
|
||||
"ordinal": 37,
|
||||
"name": "extra_file_modification_info",
|
||||
"type_info": {
|
||||
"type": "Blob",
|
||||
@@ -394,7 +384,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 39,
|
||||
"ordinal": 38,
|
||||
"name": "public_bucket_directory_hash",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -404,7 +394,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 40,
|
||||
"ordinal": 39,
|
||||
"name": "maybe_public_bucket_prefix",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -414,7 +404,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 41,
|
||||
"ordinal": 40,
|
||||
"name": "maybe_public_bucket_extension",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -424,7 +414,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 42,
|
||||
"ordinal": 41,
|
||||
"name": "maybe_ratings_positive_count",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
@@ -434,7 +424,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 43,
|
||||
"ordinal": 42,
|
||||
"name": "maybe_ratings_negative_count",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
@@ -444,7 +434,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 44,
|
||||
"ordinal": 43,
|
||||
"name": "maybe_bookmark_count",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
@@ -454,7 +444,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 45,
|
||||
"ordinal": 44,
|
||||
"name": "is_featured",
|
||||
"type_info": {
|
||||
"type": "LongLong",
|
||||
@@ -464,7 +454,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 46,
|
||||
"ordinal": 45,
|
||||
"name": "created_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
@@ -474,7 +464,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 47,
|
||||
"ordinal": 46,
|
||||
"name": "updated_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
@@ -511,7 +501,6 @@
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
@@ -538,5 +527,5 @@
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "f6c37066ab3e508050e81cf3bea38cc708b05c5c59ba1c322dcfb775e4b9e7a6"
|
||||
"hash": "784ca68c6cb61d481b605bfe6ee3248a5b44499038c71b57fc9ea6c4722d170f"
|
||||
}
|
||||
+43
-54
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n m.token as `token: tokens::tokens::media_files::MediaFileToken`,\n\n m.media_class as `media_class: enums::by_table::media_files::media_file_class::MediaFileClass`,\n m.media_type as `media_type: enums::by_table::media_files::media_file_type::MediaFileType`,\n\n m.maybe_engine_category as `maybe_engine_category: enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory`,\n m.maybe_animation_type as `maybe_animation_type: enums::by_table::media_files::media_file_animation_type::MediaFileAnimationType`,\n\n m.maybe_media_subtype as `maybe_media_subtype: enums::by_table::media_files::media_file_subtype::MediaFileSubtype`,\n\n m.maybe_mime_type,\n\n users.token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n users.username as maybe_creator_username,\n users.display_name as maybe_creator_display_name,\n users.email_gravatar_hash as maybe_creator_gravatar_hash,\n\n m.maybe_creator_anonymous_visitor_token as `maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken`,\n\n m.maybe_batch_token as `maybe_batch_token: tokens::tokens::batch_generations::BatchGenerationToken`,\n\n m.maybe_style_transfer_source_media_file_token as `maybe_style_transfer_source_media_file_token: tokens::tokens::media_files::MediaFileToken`,\n m.maybe_scene_source_media_file_token as `maybe_scene_source_media_file_token: tokens::tokens::media_files::MediaFileToken`,\n\n\n m.maybe_title,\n m.maybe_text_transcript,\n\n m.maybe_origin_filename,\n\n m.maybe_duration_millis,\n\n m.maybe_prompt_token as `maybe_prompt_token: tokens::tokens::prompts::PromptToken`,\n prompts.maybe_other_args as maybe_other_prompt_args,\n\n media_file_cover_image.public_bucket_directory_hash as maybe_file_cover_image_public_bucket_hash,\n media_file_cover_image.maybe_public_bucket_prefix as maybe_file_cover_image_public_bucket_prefix,\n media_file_cover_image.maybe_public_bucket_extension as maybe_file_cover_image_public_bucket_extension,\n\n m.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,\n\n m.is_user_upload,\n m.is_intermediate_system_file,\n\n model_weights.token as `maybe_model_weights_token: tokens::tokens::model_weights::ModelWeightToken`,\n model_weights.title as maybe_model_weights_title,\n model_weights.weights_type as `maybe_model_weights_type: enums::by_table::model_weights::weights_types::WeightsType`,\n model_weights.weights_category as `maybe_model_weights_category: enums::by_table::model_weights::weights_category::WeightsCategory`,\n\n model_weight_cover_image.public_bucket_directory_hash as maybe_model_cover_image_public_bucket_hash,\n model_weight_cover_image.maybe_public_bucket_prefix as maybe_model_cover_image_public_bucket_prefix,\n model_weight_cover_image.maybe_public_bucket_extension as maybe_model_cover_image_public_bucket_extension,\n\n model_weight_creator.token as `maybe_model_weight_creator_user_token: tokens::tokens::users::UserToken`,\n model_weight_creator.username as maybe_model_weight_creator_username,\n model_weight_creator.display_name as maybe_model_weight_creator_display_name,\n model_weight_creator.email_gravatar_hash as maybe_model_weight_creator_gravatar_hash,\n\n m.extra_file_modification_info,\n\n m.public_bucket_directory_hash,\n m.maybe_public_bucket_prefix,\n m.maybe_public_bucket_extension,\n\n entity_stats.ratings_positive_count as maybe_ratings_positive_count,\n entity_stats.ratings_negative_count as maybe_ratings_negative_count,\n entity_stats.bookmark_count as maybe_bookmark_count,\n\n featured_items.entity_token IS NOT NULL AS is_featured,\n\n m.created_at,\n m.updated_at\n\nFROM media_files AS m\nLEFT OUTER JOIN users\n ON m.maybe_creator_user_token = users.token\nLEFT OUTER JOIN model_weights\n ON m.maybe_origin_model_token = model_weights.token\nLEFT OUTER JOIN media_files as media_file_cover_image\n ON media_file_cover_image.token = m.maybe_cover_image_media_file_token\nLEFT OUTER JOIN media_files as model_weight_cover_image\n ON model_weight_cover_image.token = model_weights.maybe_cover_image_media_file_token\nLEFT OUTER JOIN users as model_weight_creator\n ON model_weight_creator.token = model_weights.creator_user_token\nLEFT OUTER JOIN entity_stats\n ON entity_stats.entity_type = \"media_file\"\n AND entity_stats.entity_token = m.token\nLEFT OUTER JOIN prompts\n ON prompts.token = m.maybe_prompt_token\nLEFT OUTER JOIN featured_items\n ON featured_items.entity_type = 'media_file'\n AND featured_items.entity_token = m.token\n AND featured_items.deleted_at IS NULL\nWHERE\n m.token = ?\n AND m.user_deleted_at IS NULL\n AND m.mod_deleted_at IS NULL\n ",
|
||||
"query": "\nSELECT\n m.token as `token: tokens::tokens::media_files::MediaFileToken`,\n\n m.media_class as `media_class: enums::by_table::media_files::media_file_class::MediaFileClass`,\n m.media_type as `media_type: enums::by_table::media_files::media_file_type::MediaFileType`,\n\n m.maybe_engine_category as `maybe_engine_category: enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory`,\n m.maybe_animation_type as `maybe_animation_type: enums::by_table::media_files::media_file_animation_type::MediaFileAnimationType`,\n\n m.maybe_mime_type,\n\n users.token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n users.username as maybe_creator_username,\n users.display_name as maybe_creator_display_name,\n users.email_gravatar_hash as maybe_creator_gravatar_hash,\n\n m.maybe_creator_anonymous_visitor_token as `maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken`,\n\n m.maybe_batch_token as `maybe_batch_token: tokens::tokens::batch_generations::BatchGenerationToken`,\n\n m.maybe_style_transfer_source_media_file_token as `maybe_style_transfer_source_media_file_token: tokens::tokens::media_files::MediaFileToken`,\n m.maybe_scene_source_media_file_token as `maybe_scene_source_media_file_token: tokens::tokens::media_files::MediaFileToken`,\n\n\n m.maybe_title,\n m.maybe_text_transcript,\n\n m.maybe_origin_filename,\n\n m.maybe_duration_millis,\n\n m.maybe_prompt_token as `maybe_prompt_token: tokens::tokens::prompts::PromptToken`,\n prompts.maybe_other_args as maybe_other_prompt_args,\n\n media_file_cover_image.public_bucket_directory_hash as maybe_file_cover_image_public_bucket_hash,\n media_file_cover_image.maybe_public_bucket_prefix as maybe_file_cover_image_public_bucket_prefix,\n media_file_cover_image.maybe_public_bucket_extension as maybe_file_cover_image_public_bucket_extension,\n\n m.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,\n\n m.is_user_upload,\n m.is_intermediate_system_file,\n\n model_weights.token as `maybe_model_weights_token: tokens::tokens::model_weights::ModelWeightToken`,\n model_weights.title as maybe_model_weights_title,\n model_weights.weights_type as `maybe_model_weights_type: enums::by_table::model_weights::weights_types::WeightsType`,\n model_weights.weights_category as `maybe_model_weights_category: enums::by_table::model_weights::weights_category::WeightsCategory`,\n\n model_weight_cover_image.public_bucket_directory_hash as maybe_model_cover_image_public_bucket_hash,\n model_weight_cover_image.maybe_public_bucket_prefix as maybe_model_cover_image_public_bucket_prefix,\n model_weight_cover_image.maybe_public_bucket_extension as maybe_model_cover_image_public_bucket_extension,\n\n model_weight_creator.token as `maybe_model_weight_creator_user_token: tokens::tokens::users::UserToken`,\n model_weight_creator.username as maybe_model_weight_creator_username,\n model_weight_creator.display_name as maybe_model_weight_creator_display_name,\n model_weight_creator.email_gravatar_hash as maybe_model_weight_creator_gravatar_hash,\n\n m.extra_file_modification_info,\n\n m.public_bucket_directory_hash,\n m.maybe_public_bucket_prefix,\n m.maybe_public_bucket_extension,\n\n entity_stats.ratings_positive_count as maybe_ratings_positive_count,\n entity_stats.ratings_negative_count as maybe_ratings_negative_count,\n entity_stats.bookmark_count as maybe_bookmark_count,\n\n featured_items.entity_token IS NOT NULL AS is_featured,\n\n m.created_at,\n m.updated_at\n\nFROM media_files AS m\nLEFT OUTER JOIN users\n ON m.maybe_creator_user_token = users.token\nLEFT OUTER JOIN model_weights\n ON m.maybe_origin_model_token = model_weights.token\nLEFT OUTER JOIN media_files as media_file_cover_image\n ON media_file_cover_image.token = m.maybe_cover_image_media_file_token\nLEFT OUTER JOIN media_files as model_weight_cover_image\n ON model_weight_cover_image.token = model_weights.maybe_cover_image_media_file_token\nLEFT OUTER JOIN users as model_weight_creator\n ON model_weight_creator.token = model_weights.creator_user_token\nLEFT OUTER JOIN entity_stats\n ON entity_stats.entity_type = \"media_file\"\n AND entity_stats.entity_token = m.token\nLEFT OUTER JOIN prompts\n ON prompts.token = m.maybe_prompt_token\nLEFT OUTER JOIN featured_items\n ON featured_items.entity_type = 'media_file'\n AND featured_items.entity_token = m.token\n AND featured_items.deleted_at IS NULL\nWHERE\n m.token = ?\n AND m.user_deleted_at IS NULL\n AND m.mod_deleted_at IS NULL\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -55,16 +55,6 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "maybe_media_subtype: enums::by_table::media_files::media_file_subtype::MediaFileSubtype",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "maybe_mime_type",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -74,7 +64,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"ordinal": 6,
|
||||
"name": "maybe_creator_user_token: tokens::tokens::users::UserToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -84,7 +74,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"ordinal": 7,
|
||||
"name": "maybe_creator_username",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -94,7 +84,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"ordinal": 8,
|
||||
"name": "maybe_creator_display_name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -104,7 +94,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 10,
|
||||
"ordinal": 9,
|
||||
"name": "maybe_creator_gravatar_hash",
|
||||
"type_info": {
|
||||
"type": "String",
|
||||
@@ -114,7 +104,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 11,
|
||||
"ordinal": 10,
|
||||
"name": "maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -124,7 +114,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 12,
|
||||
"ordinal": 11,
|
||||
"name": "maybe_batch_token: tokens::tokens::batch_generations::BatchGenerationToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -134,7 +124,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 13,
|
||||
"ordinal": 12,
|
||||
"name": "maybe_style_transfer_source_media_file_token: tokens::tokens::media_files::MediaFileToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -144,7 +134,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 14,
|
||||
"ordinal": 13,
|
||||
"name": "maybe_scene_source_media_file_token: tokens::tokens::media_files::MediaFileToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -154,7 +144,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 15,
|
||||
"ordinal": 14,
|
||||
"name": "maybe_title",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -164,7 +154,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 16,
|
||||
"ordinal": 15,
|
||||
"name": "maybe_text_transcript",
|
||||
"type_info": {
|
||||
"type": "Blob",
|
||||
@@ -174,7 +164,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 17,
|
||||
"ordinal": 16,
|
||||
"name": "maybe_origin_filename",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -184,7 +174,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 18,
|
||||
"ordinal": 17,
|
||||
"name": "maybe_duration_millis",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
@@ -194,7 +184,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 19,
|
||||
"ordinal": 18,
|
||||
"name": "maybe_prompt_token: tokens::tokens::prompts::PromptToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -204,7 +194,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 20,
|
||||
"ordinal": 19,
|
||||
"name": "maybe_other_prompt_args",
|
||||
"type_info": {
|
||||
"type": "Blob",
|
||||
@@ -214,7 +204,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 21,
|
||||
"ordinal": 20,
|
||||
"name": "maybe_file_cover_image_public_bucket_hash",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -224,7 +214,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 22,
|
||||
"ordinal": 21,
|
||||
"name": "maybe_file_cover_image_public_bucket_prefix",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -234,7 +224,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 23,
|
||||
"ordinal": 22,
|
||||
"name": "maybe_file_cover_image_public_bucket_extension",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -244,7 +234,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 24,
|
||||
"ordinal": 23,
|
||||
"name": "creator_set_visibility: enums::common::visibility::Visibility",
|
||||
"type_info": {
|
||||
"type": "String",
|
||||
@@ -254,7 +244,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 25,
|
||||
"ordinal": 24,
|
||||
"name": "is_user_upload",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
@@ -264,7 +254,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 26,
|
||||
"ordinal": 25,
|
||||
"name": "is_intermediate_system_file",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
@@ -274,7 +264,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 27,
|
||||
"ordinal": 26,
|
||||
"name": "maybe_model_weights_token: tokens::tokens::model_weights::ModelWeightToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -284,7 +274,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 28,
|
||||
"ordinal": 27,
|
||||
"name": "maybe_model_weights_title",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -294,7 +284,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 29,
|
||||
"ordinal": 28,
|
||||
"name": "maybe_model_weights_type: enums::by_table::model_weights::weights_types::WeightsType",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -304,7 +294,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 30,
|
||||
"ordinal": 29,
|
||||
"name": "maybe_model_weights_category: enums::by_table::model_weights::weights_category::WeightsCategory",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -314,7 +304,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 31,
|
||||
"ordinal": 30,
|
||||
"name": "maybe_model_cover_image_public_bucket_hash",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -324,7 +314,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 32,
|
||||
"ordinal": 31,
|
||||
"name": "maybe_model_cover_image_public_bucket_prefix",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -334,7 +324,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 33,
|
||||
"ordinal": 32,
|
||||
"name": "maybe_model_cover_image_public_bucket_extension",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -344,7 +334,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 34,
|
||||
"ordinal": 33,
|
||||
"name": "maybe_model_weight_creator_user_token: tokens::tokens::users::UserToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -354,7 +344,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 35,
|
||||
"ordinal": 34,
|
||||
"name": "maybe_model_weight_creator_username",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -364,7 +354,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 36,
|
||||
"ordinal": 35,
|
||||
"name": "maybe_model_weight_creator_display_name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -374,7 +364,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 37,
|
||||
"ordinal": 36,
|
||||
"name": "maybe_model_weight_creator_gravatar_hash",
|
||||
"type_info": {
|
||||
"type": "String",
|
||||
@@ -384,7 +374,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 38,
|
||||
"ordinal": 37,
|
||||
"name": "extra_file_modification_info",
|
||||
"type_info": {
|
||||
"type": "Blob",
|
||||
@@ -394,7 +384,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 39,
|
||||
"ordinal": 38,
|
||||
"name": "public_bucket_directory_hash",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -404,7 +394,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 40,
|
||||
"ordinal": 39,
|
||||
"name": "maybe_public_bucket_prefix",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -414,7 +404,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 41,
|
||||
"ordinal": 40,
|
||||
"name": "maybe_public_bucket_extension",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -424,7 +414,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 42,
|
||||
"ordinal": 41,
|
||||
"name": "maybe_ratings_positive_count",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
@@ -434,7 +424,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 43,
|
||||
"ordinal": 42,
|
||||
"name": "maybe_ratings_negative_count",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
@@ -444,7 +434,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 44,
|
||||
"ordinal": 43,
|
||||
"name": "maybe_bookmark_count",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
@@ -454,7 +444,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 45,
|
||||
"ordinal": 44,
|
||||
"name": "is_featured",
|
||||
"type_info": {
|
||||
"type": "LongLong",
|
||||
@@ -464,7 +454,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 46,
|
||||
"ordinal": 45,
|
||||
"name": "created_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
@@ -474,7 +464,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 47,
|
||||
"ordinal": 46,
|
||||
"name": "updated_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
@@ -511,7 +501,6 @@
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
@@ -538,5 +527,5 @@
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "57fa22e6cd4e82b801605c96eac21babd78df3df361b3be566993b78a46efef2"
|
||||
"hash": "ad217c26087b2ebed6f2c9f79b16ead63727107dfce3366f3c1d12bc9d565c2c"
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\n INSERT INTO media_files\n SET\n token = ?,\n\n media_class = ?,\n media_type = ?,\n\n is_user_upload = ?,\n is_intermediate_system_file = ?,\n\n origin_category = ?, \n origin_product_category = ?, \n maybe_origin_model_type = ?, \n maybe_origin_model_token = ?, \n maybe_origin_filename = ?,\n\n is_batch_generated = ?,\n maybe_batch_token = ?,\n\n maybe_mime_type = ?,\n file_size_bytes = ?,\n maybe_duration_millis = ?,\n maybe_audio_encoding = ?, \n maybe_video_encoding = ?, \n maybe_frame_width = ?, \n maybe_frame_height = ?,\n maybe_prompt_token = ?,\n checksum_sha2 = ?,\n \n maybe_engine_category = ?,\n\n maybe_title = ?,\n maybe_text_transcript = ?,\n\n maybe_scene_source_media_file_token = ?,\n\n public_bucket_directory_hash = ?, \n maybe_public_bucket_prefix = ?, \n maybe_public_bucket_extension = ?, \n\n maybe_creator_user_token = ?, \n maybe_creator_anonymous_visitor_token = ?, \n\n creator_ip_address = ?, \n creator_set_visibility = ?, \n\n maybe_creator_file_synthetic_id = ?, \n maybe_creator_category_synthetic_id = ?,\n\n extra_file_modification_info = ?,\n\n maybe_generation_provider = ?,\n\n platform_type = ?,\n\n maybe_cover_image_media_file_token = ?,\n\n maybe_mod_user_token = ?,\n is_generated_on_prem = ?,\n generated_by_worker = ?,\n generated_by_cluster = ?\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 42
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "ad2ffbd9f48e52678a5c61817bec043bf1df4033463e5c5a18468c04af391e6a"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_files
|
||||
ADD COLUMN has_watermark BOOLEAN NOT NULL DEFAULT FALSE
|
||||
AFTER checksum_sha2;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- NB: MySQL 8.0.29+ performs DROP COLUMN with ALGORITHM=INSTANT (metadata-only).
|
||||
-- On older versions this is an INPLACE table rebuild that still permits
|
||||
-- concurrent reads and writes. No ALGORITHM clause so the server picks the
|
||||
-- best available.
|
||||
ALTER TABLE media_files
|
||||
DROP COLUMN has_watermark;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_files
|
||||
ADD COLUMN is_in_aws BOOLEAN NOT NULL DEFAULT FALSE
|
||||
AFTER maybe_public_bucket_extension;
|
||||
|
||||
ALTER TABLE media_files
|
||||
ADD INDEX index_is_in_aws (is_in_aws);
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_files
|
||||
DROP INDEX index_is_in_aws,
|
||||
DROP COLUMN is_in_aws;
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- NB: anchored to maybe_public_bucket_extension (not is_in_aws) so this works
|
||||
-- whether or not the is_in_aws drop migration has been reverted yet.
|
||||
ALTER TABLE media_files
|
||||
ADD COLUMN is_not_in_gcp BOOLEAN NOT NULL DEFAULT FALSE
|
||||
AFTER maybe_public_bucket_extension;
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_files
|
||||
DROP COLUMN is_not_in_gcp;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_files
|
||||
ADD COLUMN nsfw_status VARCHAR(32) NOT NULL DEFAULT 'unknown'
|
||||
AFTER maybe_scene_source_media_file_token;
|
||||
|
||||
ALTER TABLE media_files
|
||||
ADD INDEX index_nsfw_status (nsfw_status);
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_files
|
||||
DROP INDEX index_nsfw_status,
|
||||
DROP COLUMN nsfw_status;
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_files
|
||||
ADD COLUMN is_batch_generated BOOLEAN NOT NULL DEFAULT FALSE
|
||||
AFTER maybe_origin_filename;
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_files
|
||||
DROP COLUMN is_batch_generated;
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_files
|
||||
ADD COLUMN maybe_media_subtype VARCHAR(32) DEFAULT NULL
|
||||
AFTER media_class;
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_files
|
||||
DROP COLUMN maybe_media_subtype;
|
||||
@@ -99,12 +99,6 @@ CREATE TABLE media_files (
|
||||
-- The original filename of the media (if uploaded by a user)
|
||||
maybe_origin_filename VARCHAR(255) DEFAULT NULL,
|
||||
|
||||
-- TODO: Remove after `maybe_batch_token` gains use.
|
||||
-- Whether this media file was generated as part of a batch
|
||||
-- If so, we can look up the batch in a separate query/call to the `batch_generations` table.
|
||||
-- We won't hold the batch token in this table since it'll be very sparsely populated.
|
||||
is_batch_generated BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- If the media file is generated as part of a batch, this designates the batch.
|
||||
maybe_batch_token VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
@@ -138,9 +132,6 @@ CREATE TABLE media_files (
|
||||
-- The token is a media file token.
|
||||
maybe_scene_source_media_file_token VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- A flag for NSFW status.
|
||||
nsfw_status VARCHAR(32) NOT NULL DEFAULT "unknown",
|
||||
|
||||
-- ========== MEDIA DETAILS ==========
|
||||
|
||||
-- Type of media file:
|
||||
@@ -171,16 +162,6 @@ 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.
|
||||
maybe_mime_type VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
@@ -227,10 +208,6 @@ CREATE TABLE media_files (
|
||||
-- and produces different lengths output depending on the choice of algorithm.
|
||||
checksum_sha2 CHAR(64) NOT NULL,
|
||||
|
||||
-- Whether the image or video has a visible watermark.
|
||||
-- If so, we may not need to add a watermark downstream in further processing steps.
|
||||
has_watermark BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Tracks the thumbnail algorithm/type used for this media file.
|
||||
-- NULL = no thumbnail generated yet.
|
||||
-- 1 = video thumbnail.
|
||||
@@ -259,13 +236,6 @@ CREATE TABLE media_files (
|
||||
-- `[{maybe_public_bucket_prefix}]{public_bucket_directory_hash}[{maybe_public_bucket_extension}]`
|
||||
maybe_public_bucket_extension VARCHAR(16) DEFAULT NULL,
|
||||
|
||||
-- This is a migration flag that denotes whether this media file is stored in AWS.
|
||||
-- If not, it's stored in GCP.
|
||||
is_in_aws BOOLEAN NOT NULL DEFAULT false,
|
||||
|
||||
-- This is a migration flag that denotes that weight is not stored in GCP.
|
||||
is_not_in_gcp BOOLEAN NOT NULL DEFAULT false,
|
||||
|
||||
-- NB: Removed, since this can be derived.
|
||||
-- The directory this media is uploaded to will be exclusive for this file.
|
||||
-- Only this given record will live in this bucket, but the directory may include
|
||||
@@ -351,13 +321,11 @@ CREATE TABLE media_files (
|
||||
KEY index_is_user_upload (is_user_upload),
|
||||
KEY index_is_intermediate_system_file (is_intermediate_system_file),
|
||||
KEY index_maybe_scene_source_media_file_token (maybe_scene_source_media_file_token),
|
||||
KEY index_nsfw_status (nsfw_status),
|
||||
KEY index_media_type (media_type),
|
||||
KEY index_media_class (media_class),
|
||||
KEY index_maybe_engine_category (maybe_engine_category),
|
||||
KEY fk_maybe_prompt_token (maybe_prompt_token),
|
||||
KEY index_checksum_sha2 (checksum_sha2),
|
||||
KEY index_is_in_aws (is_in_aws),
|
||||
KEY fk_maybe_creator_user_token (maybe_creator_user_token),
|
||||
KEY fk_maybe_mod_user_token (maybe_mod_user_token),
|
||||
KEY index_creator_ip_address (creator_ip_address),
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ use serde_derive::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// Response body for the omni-gen video cost estimate endpoint.
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
#[derive(Debug, Serialize, Deserialize, ToSchema)]
|
||||
pub struct OmniGenVideoCostResponse {
|
||||
pub success: bool,
|
||||
|
||||
|
||||
-5
@@ -76,11 +76,6 @@ pub struct MediaFileInfo {
|
||||
/// this describes the animation regime used or supported.
|
||||
pub maybe_animation_type: Option<MediaFileAnimationType>,
|
||||
|
||||
// /// If the media file has a subtype, we'll report it.
|
||||
// /// This is mostly used for Bevy engine files.
|
||||
// #[deprecated(note="This was for the Bevy engine. Do not use.")]
|
||||
// pub maybe_media_subtype: Option<MediaFileSubtype>,
|
||||
|
||||
// /// Extension for the engine to load over remote:// URLs.
|
||||
// #[deprecated(note="This was for the Bevy engine. Do not use.")]
|
||||
// pub maybe_engine_extension: Option<String>,
|
||||
|
||||
+13
-18
@@ -1,7 +1,6 @@
|
||||
use enums::common::generation::common_video_model::CommonVideoModel as CommonVideoModelEnum;
|
||||
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_video::generate_video_request_builder::GenerateVideoRequestBuilder;
|
||||
use crate::generate::generate_video::providers::artcraft::build_common::{
|
||||
build_artcraft_omni_video_request, SupportedResolutions, UltraWideSupport,
|
||||
@@ -27,17 +26,10 @@ pub fn build_artcraft_grok_imagine_video_1p5(
|
||||
UltraWideSupport::Unsupported,
|
||||
)?;
|
||||
|
||||
// xAI's v1.5 model rejects text-to-video at the server. Bounce here rather
|
||||
// than spending an upstream call to learn the same thing.
|
||||
if request.start_frame_image_media_token.is_none()
|
||||
&& request.reference_image_media_tokens.as_ref().map_or(true, |v| v.is_empty())
|
||||
{
|
||||
return Err(ArtcraftRouterError::Client(ClientError::ModelDoesNotSupportOption {
|
||||
field: "image_inputs",
|
||||
value: "text-to-video isn't supported by grok-imagine-video-1.5; supply a start_frame or at least one reference image".to_string(),
|
||||
}));
|
||||
}
|
||||
|
||||
// NB: xAI's v1.5 model rejects text-to-video at the server, but that is
|
||||
// NOT enforced here — the cost path builds image-less requests to price
|
||||
// them while the user is still composing. The generate endpoints reject
|
||||
// image-less v1.5 requests at the handler layer (validate_when_image_required).
|
||||
let state = ArtcraftGrokImagineVideo1p5RequestState { request };
|
||||
|
||||
Ok(VideoGenerationDraftOrRequest::Request(
|
||||
@@ -129,6 +121,15 @@ mod tests {
|
||||
mod media_token_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn builds_without_any_image_inputs() {
|
||||
// The cost path prices image-less requests while the user is still
|
||||
// composing; the generate endpoints enforce the image requirement.
|
||||
let req = unwrap_request(make_builder(|_| {}));
|
||||
assert!(req.request.start_frame_image_media_token.is_none());
|
||||
assert!(req.request.reference_image_media_tokens.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn start_frame_token_passed_through() {
|
||||
let token = MediaFileToken::new("mf_start".to_string());
|
||||
@@ -180,12 +181,6 @@ mod tests {
|
||||
fn make_builder(f: impl FnOnce(&mut GenerateVideoRequestBuilder)) -> GenerateVideoRequestBuilder {
|
||||
let mut builder = base_builder();
|
||||
f(&mut builder);
|
||||
// v1.5 requires an input image; tests that don't explicitly exercise the
|
||||
// image-handling paths get a default MediaFileToken start_frame so they
|
||||
// sail past the no-image guard in `build()`.
|
||||
if builder.start_frame.is_none() && builder.reference_images.is_none() {
|
||||
builder.start_frame = Some(ImageRef::MediaFileToken(MediaFileToken::new("mf_default".to_string())));
|
||||
}
|
||||
builder
|
||||
}
|
||||
|
||||
|
||||
+37
-24
@@ -9,7 +9,6 @@ use grok_api_client::api::types::video_types::video_model::VideoModel as GrokVid
|
||||
use grok_api_client::api::types::video_types::video_resolution::VideoResolution as GrokResolution;
|
||||
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_video::video_generation_cost_estimate::VideoGenerationCostEstimate;
|
||||
use crate::generate::generate_video::providers::artcraft::grok_imagine_video_1p5::request::ArtcraftGrokImagineVideo1p5RequestState;
|
||||
|
||||
@@ -65,16 +64,10 @@ impl ArtcraftGrokImagineVideo1p5CostState {
|
||||
}
|
||||
|
||||
pub fn estimate_cost(&self) -> Result<VideoGenerationCostEstimate, ArtcraftRouterError> {
|
||||
// Defense in depth: `build()` already enforces this, but a state
|
||||
// constructed by hand must not get a quote for an operation xAI will
|
||||
// reject.
|
||||
if self.input_image_count == 0 {
|
||||
return Err(ArtcraftRouterError::Client(ClientError::ModelDoesNotSupportOption {
|
||||
field: "image_inputs",
|
||||
value: "text-to-video isn't supported by grok-imagine-video-1.5; supply a start_frame or at least one reference image".to_string(),
|
||||
}));
|
||||
}
|
||||
|
||||
// NB: Image-less requests DO get a quote even though xAI's v1.5 rejects
|
||||
// text-to-video — the cost path prices requests the user is still
|
||||
// composing. The image requirement is enforced at send time (request.rs)
|
||||
// and by the generate endpoints.
|
||||
let base = self.base_cost_in_cents_for_batch();
|
||||
// 5% markup, ceil so the user is always charged enough to cover the
|
||||
// upstream grok cost regardless of rounding.
|
||||
@@ -204,24 +197,23 @@ mod tests {
|
||||
assert_eq!(state.estimate_cost().expect("estimate_cost").cost_in_usd_cents.unwrap(), 150);
|
||||
}
|
||||
|
||||
/// v1.5 doesn't support text-to-video. The cost calculator must refuse
|
||||
/// to quote an image-less request even if a state is constructed
|
||||
/// directly.
|
||||
/// v1.5 doesn't support text-to-video at generation time, but the cost
|
||||
/// calculator still quotes an image-less request — the cost UI prices
|
||||
/// requests before the user has attached an image. The requirement is
|
||||
/// enforced at send time and by the generate endpoints.
|
||||
#[test]
|
||||
fn estimate_cost_rejects_text_only_request() {
|
||||
fn estimate_cost_quotes_text_only_request() {
|
||||
let state = ArtcraftGrokImagineVideo1p5CostState {
|
||||
resolution: CommonResolution::SevenTwentyP,
|
||||
duration_seconds: 5,
|
||||
batch_count: 1,
|
||||
input_image_count: 0,
|
||||
};
|
||||
let err = state.estimate_cost().expect_err("text-only should be rejected");
|
||||
match err {
|
||||
ArtcraftRouterError::Client(ClientError::ModelDoesNotSupportOption { field, .. }) => {
|
||||
assert_eq!(field, "image_inputs");
|
||||
}
|
||||
other => panic!("expected Client(ModelDoesNotSupportOption), got {:?}", other),
|
||||
}
|
||||
let base = state.base_cost_in_cents_for_batch();
|
||||
let want = base.saturating_mul(MARKUP_NUMERATOR).div_ceil(MARKUP_DENOMINATOR);
|
||||
let got = state.estimate_cost().expect("estimate_cost").cost_in_usd_cents.unwrap();
|
||||
assert_eq!(got, want);
|
||||
assert!(got > 0);
|
||||
}
|
||||
|
||||
// (resolution, duration, image_count, batch) — every case has at least
|
||||
@@ -326,6 +318,28 @@ mod tests {
|
||||
.cost_in_usd_cents.unwrap();
|
||||
assert!(p1080 > p720, "1080p ({p1080}) should cost more than 720p ({p720})");
|
||||
}
|
||||
|
||||
/// Regression: an image-less v1.5 request must get a quote through the
|
||||
/// full public builder path (build2 → estimate_cost). The cost UI polls
|
||||
/// for a price before the user has attached an image; the image
|
||||
/// requirement is enforced at send time and by the generate endpoints,
|
||||
/// NOT here.
|
||||
#[test]
|
||||
fn image_less_request_gets_a_quote_through_the_builder() {
|
||||
let builder = GenerateVideoRequestBuilder {
|
||||
model: RouterVideoModel::GrokImagineVideo1p5,
|
||||
provider: RouterProvider::Artcraft,
|
||||
duration_seconds: Some(5),
|
||||
video_batch_count: Some(1),
|
||||
..Default::default()
|
||||
};
|
||||
let cost = builder.build2()
|
||||
.expect("build2 should succeed without an image")
|
||||
.estimate_cost()
|
||||
.expect("estimate_cost should succeed without an image");
|
||||
assert!(cost.cost_in_usd_cents.unwrap() > 0);
|
||||
assert_eq!(cost.cost_in_credits, cost.cost_in_usd_cents);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Helpers ────────────────────────────────────────────────────────────
|
||||
@@ -390,8 +404,7 @@ mod tests {
|
||||
resolution,
|
||||
duration_seconds: Some(duration_seconds),
|
||||
video_batch_count: Some(video_batch_count),
|
||||
// v1.5 requires an input image — the no-image guard in build()
|
||||
// rejects T2V.
|
||||
// These cases price the image-to-video tier (one input image).
|
||||
start_frame: Some(ImageRef::MediaFileToken(MediaFileToken::new("mf_default".to_string()))),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
+57
-2
@@ -13,8 +13,11 @@ pub struct ArtcraftGrokImagineVideo1p5RequestState {
|
||||
|
||||
impl ArtcraftGrokImagineVideo1p5RequestState {
|
||||
pub async fn send(&self, client: &RouterArtcraftClient) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
|
||||
// Defense in depth: `build()` already enforces this. Bouncing here costs
|
||||
// nothing and avoids an upstream call we know will fail.
|
||||
// xAI's v1.5 model rejects text-to-video at the server. This is the
|
||||
// GENERATION-time guard — `build()` and `estimate_cost()` deliberately
|
||||
// allow image-less states so the cost path can quote a request the user
|
||||
// is still composing. Bouncing here costs nothing and avoids an upstream
|
||||
// call we know will fail.
|
||||
if self.request.start_frame_image_media_token.is_none()
|
||||
&& self.request.reference_image_media_tokens.as_ref().map_or(true, |v| v.is_empty())
|
||||
{
|
||||
@@ -27,3 +30,55 @@ impl ArtcraftGrokImagineVideo1p5RequestState {
|
||||
send_artcraft_omni_video_request(&self.request, client).await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use artcraft_client::credentials::storyteller_credential_set::StorytellerCredentialSet;
|
||||
use artcraft_client::utils::api_host::ApiHost;
|
||||
use enums::common::generation::common_video_model::CommonVideoModel as CommonVideoModelEnum;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Generation must never reach xAI with an image-less v1.5 request. The
|
||||
/// build/cost layers allow that state (the cost path quotes it), so the
|
||||
/// send-time guard is the router's last line of defense.
|
||||
#[tokio::test]
|
||||
async fn send_rejects_image_less_request_before_any_network_call() {
|
||||
let state = ArtcraftGrokImagineVideo1p5RequestState {
|
||||
request: OmniGenVideoCostAndGenerateRequest {
|
||||
idempotency_token: Some("a1b2c3d4-e5f6-7890-abcd-ef1234567890".to_string()),
|
||||
model: Some(CommonVideoModelEnum::GrokImagineVideo1p5),
|
||||
prompt: Some("a corgi running through a field".to_string()),
|
||||
negative_prompt: None,
|
||||
start_frame_image_media_token: None,
|
||||
end_frame_image_media_token: None,
|
||||
reference_image_media_tokens: None,
|
||||
reference_video_media_tokens: None,
|
||||
reference_audio_media_tokens: None,
|
||||
reference_character_tokens: None,
|
||||
resolution: None,
|
||||
aspect_ratio: None,
|
||||
bitrate: None,
|
||||
quality: None,
|
||||
duration_seconds: Some(5),
|
||||
video_batch_count: Some(1),
|
||||
generate_audio: None,
|
||||
},
|
||||
};
|
||||
|
||||
// The guard fires before the client is used, so an unroutable localhost
|
||||
// client with empty credentials proves no network call happens.
|
||||
let client = RouterArtcraftClient::new(
|
||||
ApiHost::Localhost { port: 1 },
|
||||
StorytellerCredentialSet::empty(),
|
||||
);
|
||||
|
||||
let err = state.send(&client).await.expect_err("image-less send should be rejected");
|
||||
match err {
|
||||
ArtcraftRouterError::Client(ClientError::ModelDoesNotSupportOption { field, .. }) => {
|
||||
assert_eq!(field, "image_inputs");
|
||||
}
|
||||
other => panic!("expected Client(ModelDoesNotSupportOption), got {:?}", other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ pub async fn seed_test_videos(mysql_pool: &Pool<MySql>, user_token: UserToken) -
|
||||
let media1 = InsertArgs {
|
||||
pool: &mysql_pool,
|
||||
maybe_use_apriori_media_token: Some(&model_weight_token1),
|
||||
media_file_type: MediaFileType::Video,
|
||||
media_file_type: MediaFileType::Mp4,
|
||||
maybe_mime_type: Some(&*metadata1.mimetype),
|
||||
file_size_bytes: metadata1.file_size_bytes,
|
||||
sha256_checksum: &metadata1.sha256_checksum,
|
||||
|
||||
@@ -29,16 +29,16 @@ pub async fn seed_media_files(mysql_pool: &Pool<MySql>, maybe_bucket_clients: Op
|
||||
// Delete the records if you want to re-seed.
|
||||
let media_files = [
|
||||
// Audio
|
||||
(HANASHI_USER_TOKEN, "m_21jxt406aattq2cna1xtgf5m4mjyyr", MediaFileType::Audio, "media/audio/voice-samples/biden.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_cxzabpxf88h10rshqraksxbqmhs41h", MediaFileType::Audio, "media/audio/voice-samples/brandon1.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_sq2vhrrmmbr079afk21543aa2jg53g", MediaFileType::Audio, "media/audio/voice-samples/brandon2.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_s61a8g3jnddr3xdg3gctsjxxk9jwja", MediaFileType::Audio, "media/audio/voice-samples/elon.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_e59fh75g76pvebx4qe4r4aymd93q30", MediaFileType::Audio, "media/audio/voice-samples/goku.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_ttq0ym8ht4v0z87zqz27fhadp0743c", MediaFileType::Audio, "media/audio/voice-samples/hillary.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_300bv6f141hv553fjf287p5gb76k37", MediaFileType::Audio, "media/audio/voice-samples/mario_impersonator.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_rd1ey2jem8a37r3vna2h9mht6zevs5", MediaFileType::Audio, "media/audio/voice-samples/rick.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_8n5epqfvs2vh60khap0s3ezem4epkc", MediaFileType::Audio, "media/audio/voice-samples/trump.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_g6dpwcpq51e6kvmpbbkdvgxfan9k1k", MediaFileType::Audio, "media/audio/voice-samples/trump_tts.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_21jxt406aattq2cna1xtgf5m4mjyyr", MediaFileType::Wav, "media/audio/voice-samples/biden.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_cxzabpxf88h10rshqraksxbqmhs41h", MediaFileType::Wav, "media/audio/voice-samples/brandon1.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_sq2vhrrmmbr079afk21543aa2jg53g", MediaFileType::Wav, "media/audio/voice-samples/brandon2.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_s61a8g3jnddr3xdg3gctsjxxk9jwja", MediaFileType::Wav, "media/audio/voice-samples/elon.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_e59fh75g76pvebx4qe4r4aymd93q30", MediaFileType::Wav, "media/audio/voice-samples/goku.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_ttq0ym8ht4v0z87zqz27fhadp0743c", MediaFileType::Wav, "media/audio/voice-samples/hillary.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_300bv6f141hv553fjf287p5gb76k37", MediaFileType::Wav, "media/audio/voice-samples/mario_impersonator.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_rd1ey2jem8a37r3vna2h9mht6zevs5", MediaFileType::Wav, "media/audio/voice-samples/rick.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_8n5epqfvs2vh60khap0s3ezem4epkc", MediaFileType::Wav, "media/audio/voice-samples/trump.wav"),
|
||||
(HANASHI_USER_TOKEN, "m_g6dpwcpq51e6kvmpbbkdvgxfan9k1k", MediaFileType::Wav, "media/audio/voice-samples/trump_tts.wav"),
|
||||
// Images
|
||||
(HANASHI_USER_TOKEN, "m_cn5t6ywm9k1ge9qzzxst5krc5tm08m", MediaFileType::Jpg, "media/image/face-animator-inputs/bill.jpg"),
|
||||
(HANASHI_USER_TOKEN, "m_nf9xebrr8hd1bxkfy7src5k8nv2dzy", MediaFileType::Jpg, "media/image/face-animator-inputs/elon.jpg"),
|
||||
@@ -48,18 +48,18 @@ pub async fn seed_media_files(mysql_pool: &Pool<MySql>, maybe_bucket_clients: Op
|
||||
(HANASHI_USER_TOKEN, "m_we7mnzbd76g4yn19dm6m53er0pjvew", MediaFileType::Png, "media/image/face-animator-inputs/san.png"),
|
||||
(HANASHI_USER_TOKEN, "m_wahwz92nxxfg0x42dw9fdrhwq30yk0", MediaFileType::Jpg, "media/image/face-animator-inputs/zelda.jpg"),
|
||||
// Video
|
||||
(HANASHI_USER_TOKEN, "m_gedarcfdkxx3zv8zz2wmwsnc1r8jbp", MediaFileType::Video, "media/video/storyteller-studio-renders/girl-rotating-room.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_3s74yyd4jwrjdp17yx1694n29jv5gr", MediaFileType::Video, "media/video/storyteller-studio-renders/hanashi-run.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_p6d64gm1wawz25bmdahfded3366b9f", MediaFileType::Video, "media/video/storyteller-studio-renders/mocap-kiss.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_szp2c77z6je965k44vc22xn9432a88", MediaFileType::Video, "media/video/storyteller-studio-renders/rotating-mocap-girl.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_mdwspz81zymw9hvmb1d3jm830t25xe", MediaFileType::Video, "media/video/storyteller-studio-renders/rotating-mocap-m.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_prcs6xkm8phs5y4a2dfwemwjy6n6z3", MediaFileType::Video, "media/video/storyteller-studio-renders/rotating-run-girl.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_5j889dzw08vn9pbrscx1sncff43ekp", MediaFileType::Video, "media/video/storyteller-studio-renders/rotating-run-jww.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_fwm2w6wbssez274ayz6x8ta0h1a9qp", MediaFileType::Video, "media/video/storyteller-studio-renders/rotating-run-pascal.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_yqqkrt2srep6a35xg78114jn9epwg1", MediaFileType::Video, "media/video/storyteller-studio-renders/rotating-run-pop.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_m4r043kez14pm6vaamsecpz8fafh7g", MediaFileType::Video, "media/video/video-style-transfer/man-explaining.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_81gq3hygqvrahg6ncxbtcpjap4f9nv", MediaFileType::Video, "media/video/video-style-transfer/woman-gradient-background.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_dp9ykj3yasjx69g2fx2bpd26wwjz0f", MediaFileType::Video, "media/video/video-style-transfer/woman-red-hair.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_gedarcfdkxx3zv8zz2wmwsnc1r8jbp", MediaFileType::Mp4, "media/video/storyteller-studio-renders/girl-rotating-room.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_3s74yyd4jwrjdp17yx1694n29jv5gr", MediaFileType::Mp4, "media/video/storyteller-studio-renders/hanashi-run.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_p6d64gm1wawz25bmdahfded3366b9f", MediaFileType::Mp4, "media/video/storyteller-studio-renders/mocap-kiss.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_szp2c77z6je965k44vc22xn9432a88", MediaFileType::Mp4, "media/video/storyteller-studio-renders/rotating-mocap-girl.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_mdwspz81zymw9hvmb1d3jm830t25xe", MediaFileType::Mp4, "media/video/storyteller-studio-renders/rotating-mocap-m.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_prcs6xkm8phs5y4a2dfwemwjy6n6z3", MediaFileType::Mp4, "media/video/storyteller-studio-renders/rotating-run-girl.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_5j889dzw08vn9pbrscx1sncff43ekp", MediaFileType::Mp4, "media/video/storyteller-studio-renders/rotating-run-jww.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_fwm2w6wbssez274ayz6x8ta0h1a9qp", MediaFileType::Mp4, "media/video/storyteller-studio-renders/rotating-run-pascal.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_yqqkrt2srep6a35xg78114jn9epwg1", MediaFileType::Mp4, "media/video/storyteller-studio-renders/rotating-run-pop.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_m4r043kez14pm6vaamsecpz8fafh7g", MediaFileType::Mp4, "media/video/video-style-transfer/man-explaining.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_81gq3hygqvrahg6ncxbtcpjap4f9nv", MediaFileType::Mp4, "media/video/video-style-transfer/woman-gradient-background.mp4"),
|
||||
(HANASHI_USER_TOKEN, "m_dp9ykj3yasjx69g2fx2bpd26wwjz0f", MediaFileType::Mp4, "media/video/video-style-transfer/woman-red-hair.mp4"),
|
||||
];
|
||||
|
||||
let seed_tool_data_root = get_seed_tool_data_root();
|
||||
|
||||
@@ -73,14 +73,14 @@ pub async fn main() -> AnyhowResult<()> {
|
||||
match mimetype {
|
||||
Some("audio/wav") |
|
||||
Some("audio/x-wav") => {
|
||||
media_file_type = MediaFileType::Video;
|
||||
media_file_type = MediaFileType::Wav;
|
||||
maybe_mime_type = Some("audio/wav");
|
||||
maybe_public_bucket_prefix = Some("dev_upload_");
|
||||
maybe_public_bucket_extension = Some(".wav");
|
||||
|
||||
}
|
||||
Some("video/mp4") => {
|
||||
media_file_type = MediaFileType::Video;
|
||||
media_file_type = MediaFileType::Mp4;
|
||||
maybe_mime_type = mimetype;
|
||||
maybe_public_bucket_prefix = Some("dev_upload_");
|
||||
maybe_public_bucket_extension = Some(".mp4");
|
||||
|
||||
-1
@@ -105,7 +105,6 @@ async fn create_document_from_record(elasticsearch: &Elasticsearch, record: Medi
|
||||
|
||||
media_class: record.media_class,
|
||||
media_type: record.media_type,
|
||||
maybe_media_subtype: record.maybe_media_subtype,
|
||||
maybe_engine_category: record.maybe_engine_category,
|
||||
maybe_animation_type: record.maybe_animation_type,
|
||||
|
||||
|
||||
-1
@@ -264,7 +264,6 @@ async fn upload_grok_video(
|
||||
// TODO: media_files.maybe_generation_provider
|
||||
// TODO: media_files.maybe_origin_model_type
|
||||
// TODO: media_files.maybe_origin_model_token (sref?)
|
||||
// TODO: media_files.is_batch_generated
|
||||
// TODO: media_files.maybe_batch_token
|
||||
// TODO: media_files.is_user_upload
|
||||
|
||||
|
||||
-1
@@ -294,7 +294,6 @@ async fn upload_midjourney_batch(
|
||||
// TODO: media_files.maybe_generation_provider
|
||||
// TODO: media_files.maybe_origin_model_type
|
||||
// TODO: media_files.maybe_origin_model_token (sref?)
|
||||
// TODO: media_files.is_batch_generated
|
||||
// TODO: media_files.maybe_batch_token
|
||||
// TODO: media_files.is_user_upload
|
||||
|
||||
|
||||
-1
@@ -254,7 +254,6 @@ async fn upload_spz_splat(
|
||||
// TODO: media_files.maybe_generation_provider
|
||||
// TODO: media_files.maybe_origin_model_type
|
||||
// TODO: media_files.maybe_origin_model_token (sref?)
|
||||
// TODO: media_files.is_batch_generated
|
||||
// TODO: media_files.maybe_batch_token
|
||||
// TODO: media_files.is_user_upload
|
||||
|
||||
|
||||
@@ -59,6 +59,9 @@ mod init;
|
||||
mod logging;
|
||||
pub (crate) mod types;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests_common;
|
||||
|
||||
/// Re-export of env_logger
|
||||
pub mod env_logger {
|
||||
pub use env_logger::Builder;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
//! Test utilities shared across easyenv test modules.
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use std::env;
|
||||
|
||||
pub(crate) struct EnvVarGuard {
|
||||
name: &'static str,
|
||||
}
|
||||
|
||||
impl EnvVarGuard {
|
||||
pub(crate) fn set(name: &'static str, value: &str) -> Self {
|
||||
env::remove_var(name);
|
||||
env::set_var(name, value);
|
||||
Self { name }
|
||||
}
|
||||
|
||||
pub(crate) fn unset(name: &'static str) -> Self {
|
||||
env::remove_var(name);
|
||||
Self { name }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for EnvVarGuard {
|
||||
fn drop(&mut self) {
|
||||
env::remove_var(self.name);
|
||||
}
|
||||
}
|
||||
@@ -75,3 +75,87 @@ fn get_env_bool_internal(env_name: &str) -> Result<Option<bool>, EnvError> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::tests_common::EnvVarGuard;
|
||||
|
||||
#[test]
|
||||
fn literals_round_trip_through_optional_required_and_or_default() {
|
||||
let _g = EnvVarGuard::set("BOOLEAN_TEST_TRUE_LOWER", "true");
|
||||
assert_eq!(get_env_bool_optional("BOOLEAN_TEST_TRUE_LOWER"), Some(true));
|
||||
assert_eq!(get_env_bool_required("BOOLEAN_TEST_TRUE_LOWER").unwrap(), true);
|
||||
assert_eq!(get_env_bool_or_default("BOOLEAN_TEST_TRUE_LOWER", false), true);
|
||||
|
||||
let _g = EnvVarGuard::set("BOOLEAN_TEST_TRUE_UPPER", "TRUE");
|
||||
assert_eq!(get_env_bool_optional("BOOLEAN_TEST_TRUE_UPPER"), Some(true));
|
||||
assert_eq!(get_env_bool_required("BOOLEAN_TEST_TRUE_UPPER").unwrap(), true);
|
||||
assert_eq!(get_env_bool_or_default("BOOLEAN_TEST_TRUE_UPPER", false), true);
|
||||
|
||||
let _g = EnvVarGuard::set("BOOLEAN_TEST_FALSE_LOWER", "false");
|
||||
assert_eq!(get_env_bool_optional("BOOLEAN_TEST_FALSE_LOWER"), Some(false));
|
||||
assert_eq!(get_env_bool_required("BOOLEAN_TEST_FALSE_LOWER").unwrap(), false);
|
||||
assert_eq!(get_env_bool_or_default("BOOLEAN_TEST_FALSE_LOWER", true), false);
|
||||
|
||||
let _g = EnvVarGuard::set("BOOLEAN_TEST_FALSE_UPPER", "FALSE");
|
||||
assert_eq!(get_env_bool_optional("BOOLEAN_TEST_FALSE_UPPER"), Some(false));
|
||||
assert_eq!(get_env_bool_required("BOOLEAN_TEST_FALSE_UPPER").unwrap(), false);
|
||||
assert_eq!(get_env_bool_or_default("BOOLEAN_TEST_FALSE_UPPER", true), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_returns_none_required_error_and_default() {
|
||||
let _g = EnvVarGuard::unset("BOOLEAN_TEST_MISSING");
|
||||
assert_eq!(get_env_bool_optional("BOOLEAN_TEST_MISSING"), None);
|
||||
assert!(matches!(get_env_bool_required("BOOLEAN_TEST_MISSING"), Err(EnvError::RequiredNotPresent { .. })));
|
||||
assert_eq!(get_env_bool_or_default("BOOLEAN_TEST_MISSING", true), true);
|
||||
assert_eq!(get_env_bool_or_default("BOOLEAN_TEST_MISSING", false), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn yes_is_unparseable() {
|
||||
let _g = EnvVarGuard::set("BOOLEAN_TEST_YES", "yes");
|
||||
assert_eq!(get_env_bool_optional("BOOLEAN_TEST_YES"), None);
|
||||
assert!(matches!(get_env_bool_required("BOOLEAN_TEST_YES"), Err(EnvError::ParseError { .. })));
|
||||
assert_eq!(get_env_bool_or_default("BOOLEAN_TEST_YES", true), true);
|
||||
assert_eq!(get_env_bool_or_default("BOOLEAN_TEST_YES", false), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn one_is_not_treated_as_true() {
|
||||
let _g = EnvVarGuard::set("BOOLEAN_TEST_ONE", "1");
|
||||
assert_eq!(get_env_bool_optional("BOOLEAN_TEST_ONE"), None);
|
||||
assert!(matches!(get_env_bool_required("BOOLEAN_TEST_ONE"), Err(EnvError::ParseError { .. })));
|
||||
assert_eq!(get_env_bool_or_default("BOOLEAN_TEST_ONE", true), true);
|
||||
assert_eq!(get_env_bool_or_default("BOOLEAN_TEST_ONE", false), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_string_is_unparseable() {
|
||||
let _g = EnvVarGuard::set("BOOLEAN_TEST_EMPTY", "");
|
||||
assert_eq!(get_env_bool_optional("BOOLEAN_TEST_EMPTY"), None);
|
||||
assert!(matches!(get_env_bool_required("BOOLEAN_TEST_EMPTY"), Err(EnvError::ParseError { .. })));
|
||||
assert_eq!(get_env_bool_or_default("BOOLEAN_TEST_EMPTY", true), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mixed_case_true_is_unparseable() {
|
||||
let _g = EnvVarGuard::set("BOOLEAN_TEST_MIXED_CASE", "TrUe");
|
||||
assert_eq!(get_env_bool_optional("BOOLEAN_TEST_MIXED_CASE"), None);
|
||||
assert!(matches!(get_env_bool_required("BOOLEAN_TEST_MIXED_CASE"), Err(EnvError::ParseError { .. })));
|
||||
assert_eq!(get_env_bool_or_default("BOOLEAN_TEST_MIXED_CASE", false), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn required_not_present_carries_env_var_name() {
|
||||
let _g = EnvVarGuard::unset("BOOLEAN_TEST_REQUIRED_NAME");
|
||||
match get_env_bool_required("BOOLEAN_TEST_REQUIRED_NAME") {
|
||||
Err(EnvError::RequiredNotPresent { name }) => {
|
||||
assert_eq!(name, "BOOLEAN_TEST_REQUIRED_NAME");
|
||||
},
|
||||
other => panic!("unexpected result: {:?}", other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,3 +63,42 @@ fn get_env_duration_seconds_internal(env_name: &str) -> Result<Option<Duration>,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::tests_common::EnvVarGuard;
|
||||
|
||||
#[test]
|
||||
fn zero_seconds_round_trips() {
|
||||
let _g = EnvVarGuard::set("DURATION_TEST_ZERO", "0");
|
||||
assert_eq!(get_env_duration_seconds_optional("DURATION_TEST_ZERO"), Some(Duration::from_secs(0)));
|
||||
assert_eq!(get_env_duration_seconds_required("DURATION_TEST_ZERO").unwrap(), Duration::from_secs(0));
|
||||
assert_eq!(get_env_duration_seconds_or_default("DURATION_TEST_ZERO", Duration::from_secs(99)), Duration::from_secs(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u64_max_seconds_round_trips() {
|
||||
let _g = EnvVarGuard::set("DURATION_TEST_U64_MAX", &u64::MAX.to_string());
|
||||
assert_eq!(get_env_duration_seconds_optional("DURATION_TEST_U64_MAX"), Some(Duration::from_secs(u64::MAX)));
|
||||
assert_eq!(get_env_duration_seconds_required("DURATION_TEST_U64_MAX").unwrap(), Duration::from_secs(u64::MAX));
|
||||
assert_eq!(get_env_duration_seconds_or_default("DURATION_TEST_U64_MAX", Duration::from_secs(1)), Duration::from_secs(u64::MAX));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn negative_is_unparseable() {
|
||||
let _g = EnvVarGuard::set("DURATION_TEST_NEGATIVE", "-1");
|
||||
assert_eq!(get_env_duration_seconds_optional("DURATION_TEST_NEGATIVE"), None);
|
||||
assert!(matches!(get_env_duration_seconds_required("DURATION_TEST_NEGATIVE"), Err(EnvError::ParseError { .. })));
|
||||
assert_eq!(get_env_duration_seconds_or_default("DURATION_TEST_NEGATIVE", Duration::from_secs(5)), Duration::from_secs(5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_returns_none_required_error_and_default() {
|
||||
let _g = EnvVarGuard::unset("DURATION_TEST_MISSING");
|
||||
assert_eq!(get_env_duration_seconds_optional("DURATION_TEST_MISSING"), None);
|
||||
assert!(matches!(get_env_duration_seconds_required("DURATION_TEST_MISSING"), Err(EnvError::RequiredNotPresent { .. })));
|
||||
assert_eq!(get_env_duration_seconds_or_default("DURATION_TEST_MISSING", Duration::from_secs(42)), Duration::from_secs(42));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,3 +49,52 @@ pub fn try_get_env_num_optional<T>(env_name: &str) -> Result<Option<T>, EnvError
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::tests_common::EnvVarGuard;
|
||||
|
||||
#[test]
|
||||
fn parses_i32() {
|
||||
let _g = EnvVarGuard::set("NUM_TEST_I32", "-42");
|
||||
assert_eq!(get_env_num("NUM_TEST_I32", 0i32).unwrap(), -42);
|
||||
assert_eq!(try_get_env_num_optional::<i32>("NUM_TEST_I32").unwrap(), Some(-42));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_u64() {
|
||||
let _g = EnvVarGuard::set("NUM_TEST_U64", "18446744073709551615");
|
||||
assert_eq!(get_env_num("NUM_TEST_U64", 0u64).unwrap(), u64::MAX);
|
||||
assert_eq!(try_get_env_num_optional::<u64>("NUM_TEST_U64").unwrap(), Some(u64::MAX));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_f64() {
|
||||
let _g = EnvVarGuard::set("NUM_TEST_F64", "3.14");
|
||||
assert_eq!(get_env_num("NUM_TEST_F64", 0.0f64).unwrap(), 3.14);
|
||||
assert_eq!(try_get_env_num_optional::<f64>("NUM_TEST_F64").unwrap(), Some(3.14));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u8_overflow_returns_parse_error() {
|
||||
let _g = EnvVarGuard::set("NUM_TEST_U8_OVERFLOW", "256");
|
||||
assert!(get_env_num("NUM_TEST_U8_OVERFLOW", 0u8).is_err());
|
||||
assert!(try_get_env_num_optional::<u8>("NUM_TEST_U8_OVERFLOW").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_returns_default_and_none() {
|
||||
let _g = EnvVarGuard::unset("NUM_TEST_MISSING");
|
||||
assert_eq!(get_env_num("NUM_TEST_MISSING", 99i32).unwrap(), 99);
|
||||
assert_eq!(try_get_env_num_optional::<i32>("NUM_TEST_MISSING").unwrap(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unparseable_returns_parse_error() {
|
||||
let _g = EnvVarGuard::set("NUM_TEST_UNPARSEABLE", "not_a_number");
|
||||
assert!(get_env_num("NUM_TEST_UNPARSEABLE", 0i32).is_err());
|
||||
assert!(try_get_env_num_optional::<i32>("NUM_TEST_UNPARSEABLE").is_err());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,3 +37,52 @@ pub fn get_env_string_required(env_name: &str) -> Result<String, EnvError> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::tests_common::EnvVarGuard;
|
||||
|
||||
#[test]
|
||||
fn returns_empty_string_when_set_to_empty() {
|
||||
let _g = EnvVarGuard::set("STRING_TEST_EMPTY", "");
|
||||
assert_eq!(get_env_string_optional("STRING_TEST_EMPTY"), Some("".to_string()));
|
||||
assert_eq!(get_env_string_required("STRING_TEST_EMPTY").unwrap(), "");
|
||||
assert_eq!(get_env_string_or_default("STRING_TEST_EMPTY", "default"), "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn preserves_unicode() {
|
||||
let _g = EnvVarGuard::set("STRING_TEST_UNICODE", "café🎨");
|
||||
assert_eq!(get_env_string_optional("STRING_TEST_UNICODE"), Some("café🎨".to_string()));
|
||||
assert_eq!(get_env_string_required("STRING_TEST_UNICODE").unwrap(), "café🎨");
|
||||
assert_eq!(get_env_string_or_default("STRING_TEST_UNICODE", "default"), "café🎨");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn preserves_whitespace() {
|
||||
let _g = EnvVarGuard::set("STRING_TEST_WHITESPACE", " hello \t");
|
||||
assert_eq!(get_env_string_optional("STRING_TEST_WHITESPACE"), Some(" hello \t".to_string()));
|
||||
assert_eq!(get_env_string_required("STRING_TEST_WHITESPACE").unwrap(), " hello \t");
|
||||
assert_eq!(get_env_string_or_default("STRING_TEST_WHITESPACE", "default"), " hello \t");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_returns_none_required_error_and_default() {
|
||||
let _g = EnvVarGuard::unset("STRING_TEST_MISSING");
|
||||
assert_eq!(get_env_string_optional("STRING_TEST_MISSING"), None);
|
||||
assert!(matches!(get_env_string_required("STRING_TEST_MISSING"), Err(EnvError::RequiredNotPresent { .. })));
|
||||
assert_eq!(get_env_string_or_default("STRING_TEST_MISSING", "fallback"), "fallback");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn required_not_present_carries_env_var_name() {
|
||||
let _g = EnvVarGuard::unset("STRING_TEST_REQUIRED_NAME");
|
||||
match get_env_string_required("STRING_TEST_REQUIRED_NAME") {
|
||||
Err(EnvError::RequiredNotPresent { name }) => {
|
||||
assert_eq!(name, "STRING_TEST_REQUIRED_NAME");
|
||||
},
|
||||
other => panic!("unexpected result: {:?}", other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ use serde::{Deserialize, Serialize};
|
||||
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_type::MediaFileType;
|
||||
use enums::common::visibility::Visibility;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
@@ -25,7 +24,6 @@ pub struct MediaFileDocument {
|
||||
|
||||
pub media_class: MediaFileClass,
|
||||
pub media_type: MediaFileType,
|
||||
pub maybe_media_subtype: Option<MediaFileSubtype>,
|
||||
pub maybe_engine_category: Option<MediaFileEngineCategory>,
|
||||
|
||||
pub maybe_mime_type: Option<String>,
|
||||
|
||||
-4
@@ -117,8 +117,6 @@ pub async fn insert_media_file_generic(
|
||||
let mut maybe_creator_file_synthetic_id : Option<u64> = None;
|
||||
let mut maybe_creator_category_synthetic_id : Option<u64> = None;
|
||||
|
||||
let is_batch_generated = args.maybe_batch_token.is_some();
|
||||
|
||||
let mut maybe_generation_provider_str = None;
|
||||
let mut is_intermediate_system_file = args.is_intermediate_system_file;
|
||||
let mut is_user_upload = args.is_user_upload;
|
||||
@@ -172,7 +170,6 @@ pub async fn insert_media_file_generic(
|
||||
maybe_origin_model_token = ?,
|
||||
maybe_origin_filename = ?,
|
||||
|
||||
is_batch_generated = ?,
|
||||
maybe_batch_token = ?,
|
||||
|
||||
maybe_mime_type = ?,
|
||||
@@ -232,7 +229,6 @@ pub async fn insert_media_file_generic(
|
||||
args.maybe_origin_model_token.map(|t| t.to_string()),
|
||||
args.maybe_origin_filename,
|
||||
|
||||
is_batch_generated,
|
||||
args.maybe_batch_token.map(|t| t.as_str()),
|
||||
|
||||
args.maybe_mime_type,
|
||||
|
||||
+5
-1
@@ -82,6 +82,10 @@ pub async fn insert_media_file_from_comfy_ui(args: InsertArgs<'_>) -> AnyhowResu
|
||||
|
||||
let maybe_model_type = args.maybe_model_type.map(|m| m.to_str());
|
||||
|
||||
let media_type = args.maybe_mime_type
|
||||
.and_then(MediaFileType::try_from_mime_type)
|
||||
.unwrap_or(MediaFileType::Video); // Coarse fallback for unrecognized mimes
|
||||
|
||||
let record_id = {
|
||||
let query_result = sqlx::query!(
|
||||
r#"
|
||||
@@ -129,7 +133,7 @@ SET
|
||||
result_token.as_str(),
|
||||
|
||||
MediaFileClass::Video.to_str(),
|
||||
MediaFileType::Video.to_str(), // TODO(bt,2024-04-30): This needs to become "mp4" after a frontend migration
|
||||
media_type.to_str(),
|
||||
|
||||
ORIGIN_CATEGORY.to_str(),
|
||||
product.to_str(),
|
||||
|
||||
+5
-1
@@ -69,6 +69,10 @@ pub async fn insert_media_file_from_f5_tts(
|
||||
const ORIGIN_CATEGORY : MediaFileOriginCategory = MediaFileOriginCategory::Inference;
|
||||
const ORIGIN_PRODUCT_CATEGORY : MediaFileOriginProductCategory = MediaFileOriginProductCategory::TextToSpeech;
|
||||
|
||||
let media_type = args.maybe_mime_type
|
||||
.and_then(MediaFileType::try_from_mime_type)
|
||||
.unwrap_or(MediaFileType::Audio); // Coarse fallback for unrecognized mimes
|
||||
|
||||
let record_id = {
|
||||
let query_result = sqlx::query!(
|
||||
r#"
|
||||
@@ -116,7 +120,7 @@ SET
|
||||
result_token.as_str(),
|
||||
|
||||
MediaFileClass::Audio.to_str(),
|
||||
MediaFileType::Audio.to_str(), // TODO(bt,2024-04-30): This needs to become "wav" after a frontend migration
|
||||
media_type.to_str(),
|
||||
|
||||
ORIGIN_CATEGORY.to_str(),
|
||||
ORIGIN_PRODUCT_CATEGORY.to_str(),
|
||||
|
||||
+5
-1
@@ -68,6 +68,10 @@ pub async fn insert_media_file_from_face_animation(
|
||||
const ORIGIN_PRODUCT_CATEGORY : MediaFileOriginProductCategory = MediaFileOriginProductCategory::FaceAnimator;
|
||||
const ORIGIN_MODEL_TYPE : MediaFileOriginModelType = MediaFileOriginModelType::SadTalker;
|
||||
|
||||
let media_type = args.maybe_mime_type
|
||||
.and_then(MediaFileType::try_from_mime_type)
|
||||
.unwrap_or(MediaFileType::Video); // Coarse fallback for unrecognized mimes
|
||||
|
||||
let record_id = {
|
||||
let query_result = sqlx::query!(
|
||||
r#"
|
||||
@@ -108,7 +112,7 @@ SET
|
||||
result_token.as_str(),
|
||||
|
||||
MediaFileClass::Video.to_str(),
|
||||
MediaFileType::Video.to_str(),
|
||||
media_type.to_str(),
|
||||
|
||||
ORIGIN_CATEGORY.to_str(),
|
||||
ORIGIN_PRODUCT_CATEGORY.to_str(),
|
||||
|
||||
+4
-2
@@ -66,7 +66,9 @@ pub async fn insert_media_file_from_rerender(
|
||||
const ORIGIN_CATEGORY : MediaFileOriginCategory = MediaFileOriginCategory::Inference;
|
||||
const ORIGIN_PRODUCT_CATEGORY : MediaFileOriginProductCategory = MediaFileOriginProductCategory::VideoFilter;
|
||||
const ORIGIN_MODEL_TYPE : MediaFileOriginModelType = MediaFileOriginModelType::Rerender;
|
||||
const MEDIA_TYPE : MediaFileType = MediaFileType::Video;
|
||||
let media_type = args.maybe_mime_type
|
||||
.and_then(MediaFileType::try_from_mime_type)
|
||||
.unwrap_or(MediaFileType::Video); // Coarse fallback for unrecognized mimes
|
||||
|
||||
let record_id = {
|
||||
let query_result = sqlx::query!(
|
||||
@@ -109,7 +111,7 @@ SET
|
||||
ORIGIN_PRODUCT_CATEGORY.to_str(),
|
||||
ORIGIN_MODEL_TYPE.to_str(),
|
||||
|
||||
MEDIA_TYPE.to_str(),
|
||||
media_type.to_str(),
|
||||
args.maybe_mime_type,
|
||||
args.file_size_bytes,
|
||||
|
||||
|
||||
+5
-1
@@ -69,6 +69,10 @@ pub async fn insert_media_file_from_seed_vc(
|
||||
const ORIGIN_CATEGORY : MediaFileOriginCategory = MediaFileOriginCategory::Inference;
|
||||
const ORIGIN_PRODUCT_CATEGORY : MediaFileOriginProductCategory = MediaFileOriginProductCategory::TextToSpeech;
|
||||
|
||||
let media_type = args.maybe_mime_type
|
||||
.and_then(MediaFileType::try_from_mime_type)
|
||||
.unwrap_or(MediaFileType::Audio); // Coarse fallback for unrecognized mimes
|
||||
|
||||
let record_id = {
|
||||
let query_result = sqlx::query!(
|
||||
r#"
|
||||
@@ -116,7 +120,7 @@ SET
|
||||
result_token.as_str(),
|
||||
|
||||
MediaFileClass::Audio.to_str(),
|
||||
MediaFileType::Audio.to_str(), // TODO(bt,2024-04-30): This needs to become "wav" after a frontend migration
|
||||
media_type.to_str(),
|
||||
|
||||
ORIGIN_CATEGORY.to_str(),
|
||||
ORIGIN_PRODUCT_CATEGORY.to_str(),
|
||||
|
||||
+5
-1
@@ -75,6 +75,10 @@ pub async fn insert_media_file_from_studio_gen2(args: InsertArgs<'_>) -> AnyhowR
|
||||
|
||||
const MODEL_TYPE : MediaFileOriginModelType = MediaFileOriginModelType::StorytellerStudio;
|
||||
|
||||
let media_type = args.maybe_mime_type
|
||||
.and_then(MediaFileType::try_from_mime_type)
|
||||
.unwrap_or(MediaFileType::Video); // Coarse fallback for unrecognized mimes
|
||||
|
||||
let record_id = {
|
||||
let query_result = sqlx::query!(
|
||||
r#"
|
||||
@@ -121,7 +125,7 @@ SET
|
||||
result_token.as_str(),
|
||||
|
||||
MediaFileClass::Video.to_str(),
|
||||
MediaFileType::Video.to_str(), // TODO(bt,2024-04-30): This needs to become "mp4" after a frontend migration
|
||||
media_type.to_str(),
|
||||
|
||||
ORIGIN_CATEGORY.to_str(),
|
||||
PRODUCT.to_str(),
|
||||
|
||||
+5
-1
@@ -69,6 +69,10 @@ pub async fn insert_media_file_from_tacotron2(
|
||||
const ORIGIN_CATEGORY : MediaFileOriginCategory = MediaFileOriginCategory::Inference;
|
||||
const ORIGIN_PRODUCT_CATEGORY : MediaFileOriginProductCategory = MediaFileOriginProductCategory::TextToSpeech;
|
||||
|
||||
let media_type = args.maybe_mime_type
|
||||
.and_then(MediaFileType::try_from_mime_type)
|
||||
.unwrap_or(MediaFileType::Audio); // Coarse fallback for unrecognized mimes
|
||||
|
||||
let record_id = {
|
||||
let query_result = sqlx::query!(
|
||||
r#"
|
||||
@@ -116,7 +120,7 @@ SET
|
||||
result_token.as_str(),
|
||||
|
||||
MediaFileClass::Audio.to_str(),
|
||||
MediaFileType::Audio.to_str(), // TODO(bt,2024-04-30): This needs to become "wav" after a frontend migration
|
||||
media_type.to_str(),
|
||||
|
||||
ORIGIN_CATEGORY.to_str(),
|
||||
ORIGIN_PRODUCT_CATEGORY.to_str(),
|
||||
|
||||
+5
-1
@@ -80,6 +80,10 @@ pub async fn insert_media_file_from_voice_conversion(
|
||||
const ORIGIN_CATEGORY : MediaFileOriginCategory = MediaFileOriginCategory::Inference;
|
||||
const ORIGIN_PRODUCT_CATEGORY : MediaFileOriginProductCategory = MediaFileOriginProductCategory::VoiceConversion;
|
||||
|
||||
let media_type = args.maybe_mime_type
|
||||
.and_then(MediaFileType::try_from_mime_type)
|
||||
.unwrap_or(MediaFileType::Audio); // Coarse fallback for unrecognized mimes
|
||||
|
||||
let record_id = {
|
||||
let query_result = sqlx::query!(
|
||||
r#"
|
||||
@@ -122,7 +126,7 @@ SET
|
||||
result_token.as_str(),
|
||||
|
||||
MediaFileClass::Audio.to_str(),
|
||||
MediaFileType::Audio.to_str(), // TODO(bt,2024-04-30): This needs to become "wav" after a frontend migration
|
||||
media_type.to_str(),
|
||||
|
||||
ORIGIN_CATEGORY.to_str(),
|
||||
ORIGIN_PRODUCT_CATEGORY.to_str(),
|
||||
|
||||
+4
-2
@@ -70,7 +70,9 @@ pub async fn insert_media_file_from_zero_shot(
|
||||
// Since fill this out apart of the funtion this seems like the only thing to change.
|
||||
const ORIGIN_CATEGORY : MediaFileOriginCategory = MediaFileOriginCategory::Inference;
|
||||
const ORIGIN_PRODUCT_CATEGORY : MediaFileOriginProductCategory = MediaFileOriginProductCategory::ZeroShotVoice;
|
||||
const MEDIA_TYPE : MediaFileType = MediaFileType::Audio;
|
||||
let media_type = args.maybe_mime_type
|
||||
.and_then(MediaFileType::try_from_mime_type)
|
||||
.unwrap_or(MediaFileType::Audio); // Coarse fallback for unrecognized mimes
|
||||
|
||||
let record_id = {
|
||||
let query_result = sqlx::query!(
|
||||
@@ -118,7 +120,7 @@ pub async fn insert_media_file_from_zero_shot(
|
||||
|
||||
args.job.maybe_raw_inference_text,
|
||||
|
||||
MEDIA_TYPE.to_str(),
|
||||
media_type.to_str(),
|
||||
args.maybe_mime_type,
|
||||
args.file_size_bytes,
|
||||
|
||||
|
||||
-6
@@ -12,7 +12,6 @@ use enums::by_table::media_files::media_file_animation_type::MediaFileAnimationT
|
||||
use enums::traits::mysql_from_row::MySqlFromRow as _;
|
||||
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::by_table::model_weights::weights_category::WeightsCategory;
|
||||
use enums::by_table::model_weights::weights_types::WeightsType;
|
||||
@@ -38,7 +37,6 @@ pub struct MediaFile {
|
||||
pub maybe_engine_category: Option<MediaFileEngineCategory>,
|
||||
pub maybe_animation_type: Option<MediaFileAnimationType>,
|
||||
|
||||
pub maybe_media_subtype: Option<MediaFileSubtype>,
|
||||
|
||||
// TODO: Bucket hash bits.
|
||||
|
||||
@@ -125,7 +123,6 @@ pub struct MediaFileRaw {
|
||||
pub maybe_engine_category: Option<MediaFileEngineCategory>,
|
||||
pub maybe_animation_type: Option<MediaFileAnimationType>,
|
||||
|
||||
pub maybe_media_subtype: Option<MediaFileSubtype>,
|
||||
|
||||
// TODO: Bucket hash bits.
|
||||
|
||||
@@ -234,7 +231,6 @@ pub async fn batch_get_media_files(
|
||||
media_type: record.media_type,
|
||||
maybe_engine_category: record.maybe_engine_category,
|
||||
maybe_animation_type: record.maybe_animation_type,
|
||||
maybe_media_subtype: record.maybe_media_subtype,
|
||||
maybe_batch_token: record.maybe_batch_token,
|
||||
maybe_title: record.maybe_title,
|
||||
maybe_text_transcript: record.maybe_text_transcript,
|
||||
@@ -294,7 +290,6 @@ SELECT
|
||||
m.maybe_engine_category,
|
||||
m.maybe_animation_type,
|
||||
|
||||
m.maybe_media_subtype,
|
||||
|
||||
users.token as maybe_creator_user_token,
|
||||
users.username as maybe_creator_username,
|
||||
@@ -390,7 +385,6 @@ impl FromRow<'_, MySqlRow> for MediaFileRaw {
|
||||
maybe_engine_category: MediaFileEngineCategory::try_from_mysql_row_nullable(row, "maybe_engine_category")?,
|
||||
maybe_animation_type: MediaFileAnimationType::try_from_mysql_row_nullable(row, "maybe_animation_type")?,
|
||||
|
||||
maybe_media_subtype: MediaFileSubtype::try_from_mysql_row_nullable(row, "maybe_media_subtype")?,
|
||||
|
||||
maybe_batch_token: BatchGenerationToken::try_from_mysql_row_nullable(row, "maybe_batch_token")?,
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ use chrono::{DateTime, Utc};
|
||||
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_type::MediaFileType;
|
||||
use enums::by_table::model_weights::weights_category::WeightsCategory;
|
||||
use enums::by_table::model_weights::weights_types::WeightsType;
|
||||
@@ -39,8 +38,6 @@ pub struct MediaFile {
|
||||
pub maybe_engine_category: Option<MediaFileEngineCategory>,
|
||||
pub maybe_animation_type: Option<MediaFileAnimationType>,
|
||||
|
||||
pub maybe_media_subtype: Option<MediaFileSubtype>,
|
||||
|
||||
pub maybe_mime_type: Option<String>,
|
||||
|
||||
// TODO: Other media details (file size, dimensions, duration, etc.)
|
||||
@@ -134,8 +131,6 @@ pub struct MediaFileRaw {
|
||||
pub maybe_engine_category: Option<MediaFileEngineCategory>,
|
||||
pub maybe_animation_type: Option<MediaFileAnimationType>,
|
||||
|
||||
pub maybe_media_subtype: Option<MediaFileSubtype>,
|
||||
|
||||
pub maybe_mime_type: Option<String>,
|
||||
|
||||
pub maybe_batch_token: Option<BatchGenerationToken>,
|
||||
@@ -263,7 +258,6 @@ pub async fn get_media_file_with_transactor(
|
||||
maybe_engine_category: record.maybe_engine_category,
|
||||
maybe_animation_type: record.maybe_animation_type,
|
||||
media_class: record.media_class,
|
||||
maybe_media_subtype: record.maybe_media_subtype,
|
||||
maybe_mime_type: record.maybe_mime_type,
|
||||
maybe_batch_token: record.maybe_batch_token,
|
||||
maybe_style_transfer_source_media_file_token: record.maybe_style_transfer_source_media_file_token,
|
||||
@@ -327,8 +321,6 @@ SELECT
|
||||
m.maybe_engine_category as `maybe_engine_category: enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory`,
|
||||
m.maybe_animation_type as `maybe_animation_type: enums::by_table::media_files::media_file_animation_type::MediaFileAnimationType`,
|
||||
|
||||
m.maybe_media_subtype as `maybe_media_subtype: enums::by_table::media_files::media_file_subtype::MediaFileSubtype`,
|
||||
|
||||
m.maybe_mime_type,
|
||||
|
||||
users.token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,
|
||||
@@ -450,8 +442,6 @@ SELECT
|
||||
m.maybe_engine_category as `maybe_engine_category: enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory`,
|
||||
m.maybe_animation_type as `maybe_animation_type: enums::by_table::media_files::media_file_animation_type::MediaFileAnimationType`,
|
||||
|
||||
m.maybe_media_subtype as `maybe_media_subtype: enums::by_table::media_files::media_file_subtype::MediaFileSubtype`,
|
||||
|
||||
m.maybe_mime_type,
|
||||
|
||||
users.token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,
|
||||
|
||||
-20
@@ -14,7 +14,6 @@ use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCat
|
||||
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;
|
||||
use enums::common::visibility::Visibility;
|
||||
use errors::AnyhowResult;
|
||||
@@ -42,7 +41,6 @@ pub struct MediaFileForElasticsearchRecord {
|
||||
|
||||
pub maybe_origin_filename: Option<String>,
|
||||
|
||||
pub is_batch_generated: bool,
|
||||
pub maybe_batch_token: Option<BatchGenerationToken>,
|
||||
|
||||
pub is_user_upload: bool,
|
||||
@@ -59,11 +57,8 @@ pub struct MediaFileForElasticsearchRecord {
|
||||
pub maybe_style_transfer_source_media_file_token: Option<MediaFileToken>,
|
||||
pub maybe_scene_source_media_file_token: Option<MediaFileToken>,
|
||||
|
||||
pub nsfw_status: String,
|
||||
|
||||
pub media_type: MediaFileType,
|
||||
pub media_class: MediaFileClass,
|
||||
pub maybe_media_subtype: Option<MediaFileSubtype>,
|
||||
|
||||
pub maybe_mime_type: Option<String>,
|
||||
pub file_size_bytes: u64,
|
||||
@@ -159,7 +154,6 @@ pub async fn list_media_files_for_elastic_search_backfill_using_cursor(
|
||||
maybe_origin_model_type: record.maybe_origin_model_type,
|
||||
maybe_origin_model_token: record.maybe_origin_model_token,
|
||||
maybe_origin_filename: record.maybe_origin_filename,
|
||||
is_batch_generated: i8_to_bool(record.is_batch_generated),
|
||||
maybe_batch_token: record.maybe_batch_token,
|
||||
is_user_upload: i8_to_bool(record.is_user_upload),
|
||||
is_intermediate_system_file: i8_to_bool(record.is_intermediate_system_file),
|
||||
@@ -170,10 +164,8 @@ pub async fn list_media_files_for_elastic_search_backfill_using_cursor(
|
||||
maybe_cover_image_public_bucket_extension: record.maybe_cover_image_public_bucket_extension,
|
||||
maybe_style_transfer_source_media_file_token: record.maybe_style_transfer_source_media_file_token,
|
||||
maybe_scene_source_media_file_token: record.maybe_scene_source_media_file_token,
|
||||
nsfw_status: record.nsfw_status,
|
||||
media_type: record.media_type,
|
||||
media_class: record.media_class,
|
||||
maybe_media_subtype: record.maybe_media_subtype,
|
||||
maybe_mime_type: record.maybe_mime_type,
|
||||
file_size_bytes: record.file_size_bytes as u64,
|
||||
maybe_duration_millis: record.maybe_duration_millis.map(|d| d as u64),
|
||||
@@ -222,7 +214,6 @@ SELECT
|
||||
m.maybe_origin_model_token,
|
||||
m.maybe_origin_filename,
|
||||
|
||||
m.is_batch_generated,
|
||||
m.maybe_batch_token,
|
||||
|
||||
m.is_user_upload,
|
||||
@@ -238,11 +229,8 @@ SELECT
|
||||
m.maybe_style_transfer_source_media_file_token,
|
||||
m.maybe_scene_source_media_file_token,
|
||||
|
||||
m.nsfw_status,
|
||||
|
||||
m.media_type,
|
||||
m.media_class,
|
||||
m.maybe_media_subtype,
|
||||
|
||||
m.maybe_mime_type,
|
||||
m.file_size_bytes,
|
||||
@@ -372,7 +360,6 @@ struct RawRecord {
|
||||
|
||||
pub maybe_origin_filename: Option<String>,
|
||||
|
||||
pub is_batch_generated: i8,
|
||||
pub maybe_batch_token: Option<BatchGenerationToken>,
|
||||
|
||||
pub is_user_upload: i8,
|
||||
@@ -389,11 +376,8 @@ struct RawRecord {
|
||||
pub maybe_style_transfer_source_media_file_token: Option<MediaFileToken>,
|
||||
pub maybe_scene_source_media_file_token: Option<MediaFileToken>,
|
||||
|
||||
pub nsfw_status: String,
|
||||
|
||||
pub media_type: MediaFileType,
|
||||
pub media_class: MediaFileClass,
|
||||
pub maybe_media_subtype: Option<MediaFileSubtype>,
|
||||
|
||||
pub maybe_mime_type: Option<String>,
|
||||
pub file_size_bytes: i32,
|
||||
@@ -459,7 +443,6 @@ impl FromRow<'_, MySqlRow> for RawRecord {
|
||||
maybe_origin_model_token: row.try_get("maybe_origin_model_token")?,
|
||||
maybe_origin_filename: row.try_get("maybe_origin_filename")?,
|
||||
|
||||
is_batch_generated: row.try_get("is_batch_generated")?,
|
||||
maybe_batch_token: BatchGenerationToken::try_from_mysql_row_nullable(row, "maybe_batch_token")?,
|
||||
|
||||
is_user_upload: row.try_get("is_user_upload")?,
|
||||
@@ -475,11 +458,8 @@ impl FromRow<'_, MySqlRow> for RawRecord {
|
||||
maybe_style_transfer_source_media_file_token: row.try_get("maybe_style_transfer_source_media_file_token")?,
|
||||
maybe_scene_source_media_file_token: row.try_get("maybe_scene_source_media_file_token")?,
|
||||
|
||||
nsfw_status: row.try_get("nsfw_status")?,
|
||||
|
||||
media_type: MediaFileType::try_from_mysql_row(row, "media_type")?,
|
||||
media_class: MediaFileClass::try_from_mysql_row(row, "media_class")?,
|
||||
maybe_media_subtype: MediaFileSubtype::try_from_mysql_row_nullable(row, "maybe_media_subtype")?,
|
||||
|
||||
maybe_mime_type: row.try_get("maybe_mime_type")?,
|
||||
file_size_bytes: row.try_get("file_size_bytes")?,
|
||||
|
||||
-9
@@ -8,7 +8,6 @@ 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_product_category::MediaFileOriginProductCategory;
|
||||
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 errors::AnyhowResult;
|
||||
@@ -43,8 +42,6 @@ pub struct UpsertMediaFileFromUploadArgs<'a> {
|
||||
|
||||
pub upload_type: UploadType,
|
||||
|
||||
pub maybe_media_subtype: Option<MediaFileSubtype>,
|
||||
|
||||
pub maybe_mime_type: Option<&'a str>,
|
||||
pub file_size_bytes: u64,
|
||||
pub duration_millis: u64,
|
||||
@@ -115,7 +112,6 @@ SET
|
||||
maybe_engine_category = ?,
|
||||
maybe_animation_type = ?,
|
||||
|
||||
maybe_media_subtype = ?,
|
||||
maybe_mime_type = ?,
|
||||
file_size_bytes = ?,
|
||||
|
||||
@@ -150,7 +146,6 @@ ON DUPLICATE KEY UPDATE
|
||||
maybe_engine_category = ?,
|
||||
maybe_animation_type = ?,
|
||||
|
||||
maybe_media_subtype = ?,
|
||||
maybe_mime_type = ?,
|
||||
file_size_bytes = ?,
|
||||
|
||||
@@ -185,8 +180,6 @@ ON DUPLICATE KEY UPDATE
|
||||
args.maybe_engine_category.map(|s| s.to_str()),
|
||||
args.maybe_animation_type.map(|s| s.to_str()),
|
||||
|
||||
args.maybe_media_subtype.map(|s| s.to_str()),
|
||||
|
||||
args.maybe_mime_type,
|
||||
args.file_size_bytes,
|
||||
|
||||
@@ -216,8 +209,6 @@ ON DUPLICATE KEY UPDATE
|
||||
args.maybe_engine_category.map(|s| s.to_str()),
|
||||
args.maybe_animation_type.map(|s| s.to_str()),
|
||||
|
||||
args.maybe_media_subtype.map(|s| s.to_str()),
|
||||
|
||||
args.maybe_mime_type,
|
||||
args.file_size_bytes,
|
||||
|
||||
|
||||
+9
@@ -183,9 +183,18 @@ impl RawUserBookmarkRecord {
|
||||
MediaFileType::Jpg => Some("image media file".to_string()),
|
||||
MediaFileType::Png => Some("image media file".to_string()),
|
||||
MediaFileType::Gif => Some("image media file".to_string()),
|
||||
MediaFileType::Webp => Some("image media file".to_string()),
|
||||
MediaFileType::Mp4 => Some("video media file".to_string()),
|
||||
MediaFileType::Webm => Some("video media file".to_string()),
|
||||
MediaFileType::Mov => Some("video media file".to_string()),
|
||||
MediaFileType::Wav => Some("audio media file".to_string()),
|
||||
MediaFileType::Mp3 => Some("audio media file".to_string()),
|
||||
MediaFileType::Opus => Some("audio media file".to_string()),
|
||||
MediaFileType::Ogg => Some("audio media file".to_string()),
|
||||
MediaFileType::Aac => Some("audio media file".to_string()),
|
||||
MediaFileType::M4a => Some("audio media file".to_string()),
|
||||
MediaFileType::Flac => Some("audio media file".to_string()),
|
||||
MediaFileType::Json => Some("project file".to_string()),
|
||||
}),
|
||||
UserBookmarkEntityType::VoiceConversionModel => self.maybe_descriptive_text_voice_conversion_model_title,
|
||||
UserBookmarkEntityType::ZsVoice => self.maybe_descriptive_text_zs_voice_title,
|
||||
|
||||
@@ -6,6 +6,8 @@ use strum::EnumCount;
|
||||
use strum::EnumIter;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use crate::by_table::media_files::media_file_class::MediaFileClass;
|
||||
|
||||
/// Used in the `media_files` table in a `VARCHAR(16)` field.
|
||||
///
|
||||
/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY.
|
||||
@@ -90,6 +92,36 @@ pub enum MediaFileType {
|
||||
|
||||
/// Mp3 audio
|
||||
Mp3,
|
||||
|
||||
// ========================= LESS SUPPORT FOR THE FILES BELOW THIS LINE ========================= //
|
||||
|
||||
/// Webp images
|
||||
Webp,
|
||||
|
||||
/// Webm videos
|
||||
Webm,
|
||||
|
||||
/// QuickTime videos
|
||||
Mov,
|
||||
|
||||
/// Opus audio
|
||||
Opus,
|
||||
|
||||
/// Ogg audio
|
||||
Ogg,
|
||||
|
||||
/// AAC audio
|
||||
Aac,
|
||||
|
||||
/// M4a audio
|
||||
M4a,
|
||||
|
||||
/// FLAC audio
|
||||
Flac,
|
||||
|
||||
/// Generic JSON documents (eg. internal project files).
|
||||
/// NB: 3D scene files predate this and use `scene_json` instead.
|
||||
Json,
|
||||
}
|
||||
|
||||
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
|
||||
@@ -110,7 +142,53 @@ impl MediaFileType {
|
||||
pub fn is_jpg_or_png_or_legacy_image(&self) -> bool {
|
||||
matches!(self, Self::Jpg | Self::Png | Self::Image)
|
||||
}
|
||||
|
||||
|
||||
/// Any image format, including the legacy coarse `Image` type.
|
||||
pub fn is_image(&self) -> bool {
|
||||
matches!(self, Self::Image | Self::Jpg | Self::Png | Self::Gif | Self::Webp)
|
||||
}
|
||||
|
||||
/// The broad `media_class` this file format belongs to.
|
||||
pub fn to_media_class(&self) -> MediaFileClass {
|
||||
match self {
|
||||
Self::Audio
|
||||
| Self::Wav
|
||||
| Self::Mp3
|
||||
| Self::Opus
|
||||
| Self::Ogg
|
||||
| Self::Aac
|
||||
| Self::M4a
|
||||
| Self::Flac => MediaFileClass::Audio,
|
||||
|
||||
Self::Image
|
||||
| Self::Jpg
|
||||
| Self::Png
|
||||
| Self::Gif
|
||||
| Self::Webp => MediaFileClass::Image,
|
||||
|
||||
Self::Video
|
||||
| Self::Mp4
|
||||
| Self::Webm
|
||||
| Self::Mov => MediaFileClass::Video,
|
||||
|
||||
Self::Bvh
|
||||
| Self::Fbx
|
||||
| Self::Obj
|
||||
| Self::Glb
|
||||
| Self::Gltf
|
||||
| Self::Spz
|
||||
| Self::SceneRon
|
||||
| Self::SceneJson
|
||||
| Self::Pmd
|
||||
| Self::Vmd
|
||||
| Self::Pmx
|
||||
| Self::Csv => MediaFileClass::Dimensional,
|
||||
|
||||
// Generic project documents don't have a class yet.
|
||||
Self::Json => MediaFileClass::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `MediaFileType` if the mime type matches one of the known types.
|
||||
/// This is not exhaustive.
|
||||
/// (NB: In general we shouldn't keep much application logic in the `enums` crate,
|
||||
@@ -119,19 +197,80 @@ impl MediaFileType {
|
||||
match mime_type {
|
||||
"image/jpeg" => Some(Self::Jpg),
|
||||
"image/png" => Some(Self::Png),
|
||||
"image/gif" => Some(Self::Gif),
|
||||
"image/webp" => Some(Self::Webp),
|
||||
"video/mp4" => Some(Self::Mp4),
|
||||
"video/webm" => Some(Self::Webm),
|
||||
"video/quicktime" => Some(Self::Mov),
|
||||
"audio/wav" => Some(Self::Wav),
|
||||
"audio/x-wav" => Some(Self::Wav),
|
||||
"audio/wave" => Some(Self::Wav),
|
||||
"audio/mpeg" => Some(Self::Mp3),
|
||||
"audio/mp3" => Some(Self::Mp3),
|
||||
"audio/opus" => Some(Self::Opus),
|
||||
"audio/ogg" => Some(Self::Ogg),
|
||||
"audio/aac" => Some(Self::Aac),
|
||||
"audio/m4a" => Some(Self::M4a),
|
||||
"audio/x-m4a" => Some(Self::M4a),
|
||||
"audio/mp4" => Some(Self::M4a),
|
||||
"audio/flac" => Some(Self::Flac),
|
||||
"audio/x-flac" => Some(Self::Flac),
|
||||
"model/gltf-binary" => Some(Self::Glb),
|
||||
"model/gltf+json" => Some(Self::Gltf),
|
||||
"model/fbx" => Some(Self::Fbx),
|
||||
"application/fbx" => Some(Self::Fbx),
|
||||
"model/obj" => Some(Self::Obj),
|
||||
//"audio/wav" => Some(Self::Wav), // NB: Not sure if this is correct
|
||||
//"audio/mpeg" => Some(Self::Mp3), // NB: Not sure if this is correct
|
||||
//"image/gif" => Some(Self::Gif), // NB: Not sure if this is correct
|
||||
//"model/gltf+json" => Some(Self::Gltf), // NB: Not sure if this is correct
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Tries the input as a filename first, then as a bare extension.
|
||||
/// Useful as a fallback when `try_from_mime_type` fails.
|
||||
pub fn try_from_filename_or_extension(filename_or_extension: &str) -> Option<Self> {
|
||||
Self::try_from_filename(filename_or_extension)
|
||||
.or_else(|| Self::try_from_extension(filename_or_extension))
|
||||
}
|
||||
|
||||
/// Returns the `MediaFileType` for a filename by examining its extension.
|
||||
pub fn try_from_filename(filename: &str) -> Option<Self> {
|
||||
let (_, extension) = filename.trim().rsplit_once('.')?;
|
||||
Self::try_from_extension(extension)
|
||||
}
|
||||
|
||||
/// Returns the `MediaFileType` for a known file extension.
|
||||
/// Accepts extensions with or without a leading dot, in any letter case.
|
||||
pub fn try_from_extension(extension: &str) -> Option<Self> {
|
||||
let extension = extension.trim().trim_start_matches('.').to_ascii_lowercase();
|
||||
match extension.as_str() {
|
||||
"jpg" | "jpeg" => Some(Self::Jpg),
|
||||
"png" => Some(Self::Png),
|
||||
"gif" => Some(Self::Gif),
|
||||
"webp" => Some(Self::Webp),
|
||||
"mp4" => Some(Self::Mp4),
|
||||
"webm" => Some(Self::Webm),
|
||||
"mov" => Some(Self::Mov),
|
||||
"wav" => Some(Self::Wav),
|
||||
"mp3" => Some(Self::Mp3),
|
||||
"opus" => Some(Self::Opus),
|
||||
"ogg" => Some(Self::Ogg),
|
||||
"aac" => Some(Self::Aac),
|
||||
"m4a" => Some(Self::M4a),
|
||||
"flac" => Some(Self::Flac),
|
||||
"bvh" => Some(Self::Bvh),
|
||||
"fbx" => Some(Self::Fbx),
|
||||
"obj" => Some(Self::Obj),
|
||||
"glb" => Some(Self::Glb),
|
||||
"gltf" => Some(Self::Gltf),
|
||||
"spz" => Some(Self::Spz),
|
||||
"pmd" => Some(Self::Pmd),
|
||||
"vmd" => Some(Self::Vmd),
|
||||
"pmx" => Some(Self::Pmx),
|
||||
"csv" => Some(Self::Csv),
|
||||
"json" => Some(Self::Json),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Audio => "audio",
|
||||
@@ -155,6 +294,15 @@ impl MediaFileType {
|
||||
Self::Mp4 => "mp4",
|
||||
Self::Wav => "wav",
|
||||
Self::Mp3 => "mp3",
|
||||
Self::Webp => "webp",
|
||||
Self::Webm => "webm",
|
||||
Self::Mov => "mov",
|
||||
Self::Opus => "opus",
|
||||
Self::Ogg => "ogg",
|
||||
Self::Aac => "aac",
|
||||
Self::M4a => "m4a",
|
||||
Self::Flac => "flac",
|
||||
Self::Json => "json",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,6 +329,15 @@ impl MediaFileType {
|
||||
"mp4" => Ok(Self::Mp4),
|
||||
"wav" => Ok(Self::Wav),
|
||||
"mp3" => Ok(Self::Mp3),
|
||||
"webp" => Ok(Self::Webp),
|
||||
"webm" => Ok(Self::Webm),
|
||||
"mov" => Ok(Self::Mov),
|
||||
"opus" => Ok(Self::Opus),
|
||||
"ogg" => Ok(Self::Ogg),
|
||||
"aac" => Ok(Self::Aac),
|
||||
"m4a" => Ok(Self::M4a),
|
||||
"flac" => Ok(Self::Flac),
|
||||
"json" => Ok(Self::Json),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
@@ -210,12 +367,22 @@ impl MediaFileType {
|
||||
Self::Mp4,
|
||||
Self::Wav,
|
||||
Self::Mp3,
|
||||
Self::Webp,
|
||||
Self::Webm,
|
||||
Self::Mov,
|
||||
Self::Opus,
|
||||
Self::Ogg,
|
||||
Self::Aac,
|
||||
Self::M4a,
|
||||
Self::Flac,
|
||||
Self::Json,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::by_table::media_files::media_file_class::MediaFileClass;
|
||||
use crate::by_table::media_files::media_file_type::MediaFileType;
|
||||
use crate::test_helpers::assert_serialization;
|
||||
|
||||
@@ -268,6 +435,15 @@ mod tests {
|
||||
assert_serialization(MediaFileType::Mp4, "mp4");
|
||||
assert_serialization(MediaFileType::Wav, "wav");
|
||||
assert_serialization(MediaFileType::Mp3, "mp3");
|
||||
assert_serialization(MediaFileType::Webp, "webp");
|
||||
assert_serialization(MediaFileType::Webm, "webm");
|
||||
assert_serialization(MediaFileType::Mov, "mov");
|
||||
assert_serialization(MediaFileType::Opus, "opus");
|
||||
assert_serialization(MediaFileType::Ogg, "ogg");
|
||||
assert_serialization(MediaFileType::Aac, "aac");
|
||||
assert_serialization(MediaFileType::M4a, "m4a");
|
||||
assert_serialization(MediaFileType::Flac, "flac");
|
||||
assert_serialization(MediaFileType::Json, "json");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,6 +472,15 @@ mod tests {
|
||||
assert_eq!(MediaFileType::Mp4.to_str(), "mp4");
|
||||
assert_eq!(MediaFileType::Wav.to_str(), "wav");
|
||||
assert_eq!(MediaFileType::Mp3.to_str(), "mp3");
|
||||
assert_eq!(MediaFileType::Webp.to_str(), "webp");
|
||||
assert_eq!(MediaFileType::Webm.to_str(), "webm");
|
||||
assert_eq!(MediaFileType::Mov.to_str(), "mov");
|
||||
assert_eq!(MediaFileType::Opus.to_str(), "opus");
|
||||
assert_eq!(MediaFileType::Ogg.to_str(), "ogg");
|
||||
assert_eq!(MediaFileType::Aac.to_str(), "aac");
|
||||
assert_eq!(MediaFileType::M4a.to_str(), "m4a");
|
||||
assert_eq!(MediaFileType::Flac.to_str(), "flac");
|
||||
assert_eq!(MediaFileType::Json.to_str(), "json");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -320,8 +505,185 @@ mod tests {
|
||||
assert_eq!(MediaFileType::from_str("mp4").unwrap(), MediaFileType::Mp4);
|
||||
assert_eq!(MediaFileType::from_str("wav").unwrap(), MediaFileType::Wav);
|
||||
assert_eq!(MediaFileType::from_str("mp3").unwrap(), MediaFileType::Mp3);
|
||||
assert_eq!(MediaFileType::from_str("webp").unwrap(), MediaFileType::Webp);
|
||||
assert_eq!(MediaFileType::from_str("webm").unwrap(), MediaFileType::Webm);
|
||||
assert_eq!(MediaFileType::from_str("mov").unwrap(), MediaFileType::Mov);
|
||||
assert_eq!(MediaFileType::from_str("opus").unwrap(), MediaFileType::Opus);
|
||||
assert_eq!(MediaFileType::from_str("ogg").unwrap(), MediaFileType::Ogg);
|
||||
assert_eq!(MediaFileType::from_str("aac").unwrap(), MediaFileType::Aac);
|
||||
assert_eq!(MediaFileType::from_str("m4a").unwrap(), MediaFileType::M4a);
|
||||
assert_eq!(MediaFileType::from_str("flac").unwrap(), MediaFileType::Flac);
|
||||
assert_eq!(MediaFileType::from_str("json").unwrap(), MediaFileType::Json);
|
||||
assert!(MediaFileType::from_str("foo").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_media_class() {
|
||||
assert_eq!(MediaFileType::Audio.to_media_class(), MediaFileClass::Audio);
|
||||
assert_eq!(MediaFileType::Image.to_media_class(), MediaFileClass::Image);
|
||||
assert_eq!(MediaFileType::Video.to_media_class(), MediaFileClass::Video);
|
||||
assert_eq!(MediaFileType::Bvh.to_media_class(), MediaFileClass::Dimensional);
|
||||
assert_eq!(MediaFileType::Fbx.to_media_class(), MediaFileClass::Dimensional);
|
||||
assert_eq!(MediaFileType::Obj.to_media_class(), MediaFileClass::Dimensional);
|
||||
assert_eq!(MediaFileType::Glb.to_media_class(), MediaFileClass::Dimensional);
|
||||
assert_eq!(MediaFileType::Gltf.to_media_class(), MediaFileClass::Dimensional);
|
||||
assert_eq!(MediaFileType::Spz.to_media_class(), MediaFileClass::Dimensional);
|
||||
assert_eq!(MediaFileType::SceneRon.to_media_class(), MediaFileClass::Dimensional);
|
||||
assert_eq!(MediaFileType::SceneJson.to_media_class(), MediaFileClass::Dimensional);
|
||||
assert_eq!(MediaFileType::Pmd.to_media_class(), MediaFileClass::Dimensional);
|
||||
assert_eq!(MediaFileType::Vmd.to_media_class(), MediaFileClass::Dimensional);
|
||||
assert_eq!(MediaFileType::Pmx.to_media_class(), MediaFileClass::Dimensional);
|
||||
assert_eq!(MediaFileType::Csv.to_media_class(), MediaFileClass::Dimensional);
|
||||
assert_eq!(MediaFileType::Jpg.to_media_class(), MediaFileClass::Image);
|
||||
assert_eq!(MediaFileType::Png.to_media_class(), MediaFileClass::Image);
|
||||
assert_eq!(MediaFileType::Gif.to_media_class(), MediaFileClass::Image);
|
||||
assert_eq!(MediaFileType::Webp.to_media_class(), MediaFileClass::Image);
|
||||
assert_eq!(MediaFileType::Mp4.to_media_class(), MediaFileClass::Video);
|
||||
assert_eq!(MediaFileType::Webm.to_media_class(), MediaFileClass::Video);
|
||||
assert_eq!(MediaFileType::Mov.to_media_class(), MediaFileClass::Video);
|
||||
assert_eq!(MediaFileType::Wav.to_media_class(), MediaFileClass::Audio);
|
||||
assert_eq!(MediaFileType::Mp3.to_media_class(), MediaFileClass::Audio);
|
||||
assert_eq!(MediaFileType::Opus.to_media_class(), MediaFileClass::Audio);
|
||||
assert_eq!(MediaFileType::Ogg.to_media_class(), MediaFileClass::Audio);
|
||||
assert_eq!(MediaFileType::Aac.to_media_class(), MediaFileClass::Audio);
|
||||
assert_eq!(MediaFileType::M4a.to_media_class(), MediaFileClass::Audio);
|
||||
assert_eq!(MediaFileType::Flac.to_media_class(), MediaFileClass::Audio);
|
||||
assert_eq!(MediaFileType::Json.to_media_class(), MediaFileClass::Unknown);
|
||||
}
|
||||
}
|
||||
|
||||
mod format_detection {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn try_from_mime_type() {
|
||||
assert_eq!(MediaFileType::try_from_mime_type("image/jpeg"), Some(MediaFileType::Jpg));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("image/png"), Some(MediaFileType::Png));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("image/gif"), Some(MediaFileType::Gif));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("image/webp"), Some(MediaFileType::Webp));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("video/mp4"), Some(MediaFileType::Mp4));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("video/webm"), Some(MediaFileType::Webm));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("video/quicktime"), Some(MediaFileType::Mov));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("audio/wav"), Some(MediaFileType::Wav));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("audio/x-wav"), Some(MediaFileType::Wav));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("audio/wave"), Some(MediaFileType::Wav));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("audio/mpeg"), Some(MediaFileType::Mp3));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("audio/mp3"), Some(MediaFileType::Mp3));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("audio/opus"), Some(MediaFileType::Opus));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("audio/ogg"), Some(MediaFileType::Ogg));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("audio/aac"), Some(MediaFileType::Aac));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("audio/m4a"), Some(MediaFileType::M4a));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("audio/x-m4a"), Some(MediaFileType::M4a));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("audio/mp4"), Some(MediaFileType::M4a));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("audio/flac"), Some(MediaFileType::Flac));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("audio/x-flac"), Some(MediaFileType::Flac));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("model/gltf-binary"), Some(MediaFileType::Glb));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("model/gltf+json"), Some(MediaFileType::Gltf));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("model/fbx"), Some(MediaFileType::Fbx));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("application/fbx"), Some(MediaFileType::Fbx));
|
||||
assert_eq!(MediaFileType::try_from_mime_type("model/obj"), Some(MediaFileType::Obj));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_mime_type_unknown_mimes() {
|
||||
// NB: application/json is deliberately unmapped — scene JSON, mood boards,
|
||||
// and other project files can't be told apart by mime alone.
|
||||
assert_eq!(MediaFileType::try_from_mime_type("application/json"), None);
|
||||
// NB: application/gzip is the mime for spz splats, but gzip isn't
|
||||
// necessarily a splat, so it stays unmapped.
|
||||
assert_eq!(MediaFileType::try_from_mime_type("application/gzip"), None);
|
||||
assert_eq!(MediaFileType::try_from_mime_type("application/octet-stream"), None);
|
||||
assert_eq!(MediaFileType::try_from_mime_type("text/plain"), None);
|
||||
assert_eq!(MediaFileType::try_from_mime_type(""), None);
|
||||
assert_eq!(MediaFileType::try_from_mime_type("IMAGE/PNG"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_extension() {
|
||||
assert_eq!(MediaFileType::try_from_extension("jpg"), Some(MediaFileType::Jpg));
|
||||
assert_eq!(MediaFileType::try_from_extension("jpeg"), Some(MediaFileType::Jpg));
|
||||
assert_eq!(MediaFileType::try_from_extension("png"), Some(MediaFileType::Png));
|
||||
assert_eq!(MediaFileType::try_from_extension("gif"), Some(MediaFileType::Gif));
|
||||
assert_eq!(MediaFileType::try_from_extension("webp"), Some(MediaFileType::Webp));
|
||||
assert_eq!(MediaFileType::try_from_extension("mp4"), Some(MediaFileType::Mp4));
|
||||
assert_eq!(MediaFileType::try_from_extension("webm"), Some(MediaFileType::Webm));
|
||||
assert_eq!(MediaFileType::try_from_extension("mov"), Some(MediaFileType::Mov));
|
||||
assert_eq!(MediaFileType::try_from_extension("wav"), Some(MediaFileType::Wav));
|
||||
assert_eq!(MediaFileType::try_from_extension("mp3"), Some(MediaFileType::Mp3));
|
||||
assert_eq!(MediaFileType::try_from_extension("opus"), Some(MediaFileType::Opus));
|
||||
assert_eq!(MediaFileType::try_from_extension("ogg"), Some(MediaFileType::Ogg));
|
||||
assert_eq!(MediaFileType::try_from_extension("aac"), Some(MediaFileType::Aac));
|
||||
assert_eq!(MediaFileType::try_from_extension("m4a"), Some(MediaFileType::M4a));
|
||||
assert_eq!(MediaFileType::try_from_extension("flac"), Some(MediaFileType::Flac));
|
||||
assert_eq!(MediaFileType::try_from_extension("bvh"), Some(MediaFileType::Bvh));
|
||||
assert_eq!(MediaFileType::try_from_extension("fbx"), Some(MediaFileType::Fbx));
|
||||
assert_eq!(MediaFileType::try_from_extension("obj"), Some(MediaFileType::Obj));
|
||||
assert_eq!(MediaFileType::try_from_extension("glb"), Some(MediaFileType::Glb));
|
||||
assert_eq!(MediaFileType::try_from_extension("gltf"), Some(MediaFileType::Gltf));
|
||||
assert_eq!(MediaFileType::try_from_extension("spz"), Some(MediaFileType::Spz));
|
||||
assert_eq!(MediaFileType::try_from_extension("pmd"), Some(MediaFileType::Pmd));
|
||||
assert_eq!(MediaFileType::try_from_extension("vmd"), Some(MediaFileType::Vmd));
|
||||
assert_eq!(MediaFileType::try_from_extension("pmx"), Some(MediaFileType::Pmx));
|
||||
assert_eq!(MediaFileType::try_from_extension("csv"), Some(MediaFileType::Csv));
|
||||
assert_eq!(MediaFileType::try_from_extension("json"), Some(MediaFileType::Json));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_extension_normalization() {
|
||||
// Leading dot
|
||||
assert_eq!(MediaFileType::try_from_extension(".mp4"), Some(MediaFileType::Mp4));
|
||||
assert_eq!(MediaFileType::try_from_extension(".spz"), Some(MediaFileType::Spz));
|
||||
// Case insensitivity
|
||||
assert_eq!(MediaFileType::try_from_extension("JPG"), Some(MediaFileType::Jpg));
|
||||
assert_eq!(MediaFileType::try_from_extension(".WebP"), Some(MediaFileType::Webp));
|
||||
// Whitespace
|
||||
assert_eq!(MediaFileType::try_from_extension(" png "), Some(MediaFileType::Png));
|
||||
assert_eq!(MediaFileType::try_from_extension(" .glb "), Some(MediaFileType::Glb));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_extension_unknown_extensions() {
|
||||
assert_eq!(MediaFileType::try_from_extension("ron"), None);
|
||||
assert_eq!(MediaFileType::try_from_extension("exe"), None);
|
||||
assert_eq!(MediaFileType::try_from_extension("scene_json"), None);
|
||||
assert_eq!(MediaFileType::try_from_extension("audio"), None);
|
||||
assert_eq!(MediaFileType::try_from_extension(""), None);
|
||||
assert_eq!(MediaFileType::try_from_extension("."), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_filename() {
|
||||
assert_eq!(MediaFileType::try_from_filename("photo.jpg"), Some(MediaFileType::Jpg));
|
||||
assert_eq!(MediaFileType::try_from_filename("PHOTO.JPEG"), Some(MediaFileType::Jpg));
|
||||
assert_eq!(MediaFileType::try_from_filename("clip.final.mp4"), Some(MediaFileType::Mp4));
|
||||
assert_eq!(MediaFileType::try_from_filename("model.GLB"), Some(MediaFileType::Glb));
|
||||
assert_eq!(MediaFileType::try_from_filename("scene.spz"), Some(MediaFileType::Spz));
|
||||
assert_eq!(MediaFileType::try_from_filename("data.json"), Some(MediaFileType::Json));
|
||||
assert_eq!(MediaFileType::try_from_filename(" padded.png "), Some(MediaFileType::Png));
|
||||
// Failures
|
||||
assert_eq!(MediaFileType::try_from_filename("archive.tar.gz"), None);
|
||||
assert_eq!(MediaFileType::try_from_filename("noextension"), None);
|
||||
assert_eq!(MediaFileType::try_from_filename("file."), None);
|
||||
assert_eq!(MediaFileType::try_from_filename(".gitignore"), None);
|
||||
assert_eq!(MediaFileType::try_from_filename(""), None);
|
||||
// NB: a bare extension is not a filename (no dot separator)
|
||||
assert_eq!(MediaFileType::try_from_filename("mp4"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_filename_or_extension() {
|
||||
// Filenames
|
||||
assert_eq!(MediaFileType::try_from_filename_or_extension("movie.mp4"), Some(MediaFileType::Mp4));
|
||||
assert_eq!(MediaFileType::try_from_filename_or_extension("track.FLAC"), Some(MediaFileType::Flac));
|
||||
// Bare extensions, with and without a leading dot
|
||||
assert_eq!(MediaFileType::try_from_filename_or_extension("mp4"), Some(MediaFileType::Mp4));
|
||||
assert_eq!(MediaFileType::try_from_filename_or_extension(".mp4"), Some(MediaFileType::Mp4));
|
||||
assert_eq!(MediaFileType::try_from_filename_or_extension("webp"), Some(MediaFileType::Webp));
|
||||
// Failures
|
||||
assert_eq!(MediaFileType::try_from_filename_or_extension("movie.xyz"), None);
|
||||
assert_eq!(MediaFileType::try_from_filename_or_extension("unknown"), None);
|
||||
assert_eq!(MediaFileType::try_from_filename_or_extension(""), None);
|
||||
}
|
||||
}
|
||||
|
||||
mod manual_variant_checks {
|
||||
@@ -330,7 +692,7 @@ mod tests {
|
||||
#[test]
|
||||
fn all_variants() {
|
||||
let mut variants = MediaFileType::all_variants();
|
||||
assert_eq!(variants.len(), 21);
|
||||
assert_eq!(variants.len(), 30);
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileType::Audio));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileType::Image));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileType::Video));
|
||||
@@ -352,6 +714,15 @@ mod tests {
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileType::Mp4));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileType::Wav));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileType::Mp3));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileType::Webp));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileType::Webm));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileType::Mov));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileType::Opus));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileType::Ogg));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileType::Aac));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileType::M4a));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileType::Flac));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileType::Json));
|
||||
assert_eq!(variants.pop_first(), None);
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -126,7 +126,6 @@ async fn create_document_from_record(elasticsearch: &Elasticsearch, record: Medi
|
||||
|
||||
media_class: record.media_class,
|
||||
media_type: record.media_type,
|
||||
maybe_media_subtype: record.maybe_media_subtype,
|
||||
maybe_engine_category: record.maybe_engine_category,
|
||||
maybe_animation_type: record.maybe_animation_type,
|
||||
|
||||
|
||||
+2
-7
@@ -251,13 +251,8 @@ pub async fn process_job_inference(
|
||||
}
|
||||
};
|
||||
|
||||
let media_type = match metadata.mimetype.as_ref() {
|
||||
"image/png" => MediaFileType::Png,
|
||||
"image/jpeg" => MediaFileType::Jpg,
|
||||
"image/gif" => MediaFileType::Gif,
|
||||
"image/webp" => MediaFileType::Image, // Fallback
|
||||
_ => MediaFileType::Image, // Fallback
|
||||
};
|
||||
let media_type = MediaFileType::try_from_mime_type(metadata.mimetype.as_ref())
|
||||
.unwrap_or(MediaFileType::Image); // Coarse fallback for unrecognized mimes
|
||||
|
||||
// extra_file_modification_info: todo!(), // JSON ENCODED STRUCT
|
||||
let (media_file_token, _id) = insert_media_file_generic_from_job(InsertFromJobArgs {
|
||||
|
||||
+3
-1
@@ -257,7 +257,9 @@ pub async fn process_job(args: BvhToWorkflowJobArgs<'_>) -> Result<JobSuccessRes
|
||||
pool: &args.job_dependencies.db.mysql_pool,
|
||||
job: &job,
|
||||
media_class: MediaFileClass::Video,
|
||||
media_type: MediaFileType::Video,
|
||||
media_type: maybe_mimetype.as_deref()
|
||||
.and_then(MediaFileType::try_from_mime_type)
|
||||
.unwrap_or(MediaFileType::Video), // Coarse fallback for unrecognized mimes
|
||||
origin_category: MediaFileOriginCategory::Processed,
|
||||
origin_product_category: MediaFileOriginProductCategory::Mocap,
|
||||
maybe_origin_model_type: None,
|
||||
|
||||
@@ -259,7 +259,6 @@ 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_product_category::MediaFileOriginProductCategory;
|
||||
use enums::by_table::media_files::media_file_subtype::MediaFileSubtype;
|
||||
use enums::by_table::media_files::media_file_type::MediaFileType;
|
||||
use enums::by_table::model_weights::{weights_category::WeightsCategory, weights_types::WeightsType};
|
||||
use enums::by_table::prompt_context_items::prompt_context_semantic_type::PromptContextSemanticType;
|
||||
@@ -710,7 +709,6 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
MediaFileEngineCategory,
|
||||
MediaFileOriginCategory,
|
||||
MediaFileOriginProductCategory,
|
||||
MediaFileSubtype,
|
||||
MediaFileType,
|
||||
CommonModelClass,
|
||||
CommonModelType,
|
||||
|
||||
+3
-20
@@ -177,26 +177,9 @@ pub async fn process_upload_media_file(
|
||||
// do not have any open issues filed. They may simply be too old:
|
||||
// - .wma (audio/x-ms-wma)
|
||||
// - .avi (video/x-msvideo)
|
||||
media_file_type = match mimetype {
|
||||
// Audio
|
||||
"audio/aac" /* .aac */ => Some(MediaFileType::Audio),
|
||||
"audio/m4a" /* .m4a */ => Some(MediaFileType::Audio),
|
||||
"audio/mpeg" /* .mp3 */ => Some(MediaFileType::Audio),
|
||||
"audio/ogg" /* .ogg */ => Some(MediaFileType::Audio),
|
||||
"audio/opus" /* .opus */ => Some(MediaFileType::Audio),
|
||||
"audio/x-flac" /* .flac */ => Some(MediaFileType::Audio),
|
||||
"audio/x-wav" /* .wav */ => Some(MediaFileType::Audio),
|
||||
// Image — `webp` has no dedicated variant yet
|
||||
"image/gif" /* .gif */ => Some(MediaFileType::Gif),
|
||||
"image/jpeg" /* .jpg */ => Some(MediaFileType::Jpg),
|
||||
"image/png" /* .png */ => Some(MediaFileType::Png),
|
||||
"image/webp" /* .webp */ => Some(MediaFileType::Image), // TODO: Replace.
|
||||
// Video
|
||||
"video/mp4" /* .mp4 */ => Some(MediaFileType::Video),
|
||||
"video/quicktime" /* .mov */ => Some(MediaFileType::Video),
|
||||
"video/webm" /* .webm */ => Some(MediaFileType::Video),
|
||||
_ => None,
|
||||
};
|
||||
// NB: mimetypes are gated by the allow-list check above; this only maps
|
||||
// the already-permitted set to concrete media types.
|
||||
media_file_type = MediaFileType::try_from_mime_type(mimetype);
|
||||
|
||||
let do_audio_decode = match mimetype {
|
||||
// TODO: Revisit when Safari can send us this metadata consistently
|
||||
|
||||
+5
-7
@@ -236,13 +236,11 @@ pub async fn upload_snapshot_media_file_handler(
|
||||
MediaFileUploadError::ServerError
|
||||
})?;
|
||||
|
||||
let media_file_type = match mimetype.as_str() {
|
||||
"image/jpeg" => MediaFileType::Jpg,
|
||||
"image/png" => MediaFileType::Png,
|
||||
"image/gif" => MediaFileType::Gif,
|
||||
"image/webp" => MediaFileType::Image, // Fallback
|
||||
_ => MediaFileType::Image, // Fallback
|
||||
};
|
||||
let maybe_upload_filename = form.snapshot.file_name.as_deref();
|
||||
|
||||
let media_file_type = MediaFileType::try_from_mime_type(&mimetype)
|
||||
.or_else(|| maybe_upload_filename.and_then(MediaFileType::try_from_filename_or_extension))
|
||||
.unwrap_or(MediaFileType::Image); // Coarse fallback for unrecognized files
|
||||
|
||||
let (token, record_id) = insert_media_file_from_file_upload(InsertMediaFileFromUploadArgs {
|
||||
maybe_media_class: Some(MediaFileClass::Image),
|
||||
|
||||
+2
-2
@@ -129,9 +129,9 @@ pub async fn set_media_file_cover_image_handler(
|
||||
//let can_use_image = media_file.creator_set_visibility == Visibility::Public
|
||||
// && media_file.media_type == MediaFileType::Image;
|
||||
|
||||
let can_use_image = media_file.media_type == MediaFileType::Image;
|
||||
let can_use_image = media_file.media_type.is_image();
|
||||
|
||||
if !can_use_image {
|
||||
if !can_use_image {
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("Invalid media file token.".to_string()));
|
||||
}
|
||||
|
||||
|
||||
-7
@@ -10,7 +10,6 @@ use chrono::{DateTime, Utc};
|
||||
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_type::MediaFileType;
|
||||
use enums::by_table::model_weights::weights_category::WeightsCategory;
|
||||
use enums::by_table::model_weights::weights_types::WeightsType;
|
||||
@@ -79,11 +78,6 @@ pub struct BatchMediaFileInfo {
|
||||
/// this describes the animation regime used or supported.
|
||||
pub maybe_animation_type: Option<MediaFileAnimationType>,
|
||||
|
||||
/// If the media file has a subtype, we'll report it.
|
||||
/// This is mostly used for Bevy engine files.
|
||||
#[deprecated(note="This was for the Bevy engine. Do not use.")]
|
||||
pub maybe_media_subtype: Option<MediaFileSubtype>,
|
||||
|
||||
/// Extension for the engine to load over remote:// URLs.
|
||||
#[deprecated(note="This was for the Bevy engine. Do not use.")]
|
||||
pub maybe_engine_extension: Option<String>,
|
||||
@@ -289,7 +283,6 @@ pub async fn batch_get_media_files_handler(
|
||||
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_engine_extension,
|
||||
maybe_batch_token: result.maybe_batch_token,
|
||||
media_links: MediaLinksBuilder::from_media_path_and_env(
|
||||
|
||||
-9
@@ -19,7 +19,6 @@ use chrono::{DateTime, Utc};
|
||||
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_type::MediaFileType;
|
||||
use enums::by_table::model_weights::weights_category::WeightsCategory;
|
||||
use enums::by_table::model_weights::weights_types::WeightsType;
|
||||
@@ -69,11 +68,6 @@ pub struct MediaFileInfo {
|
||||
/// this describes the animation regime used or supported.
|
||||
pub maybe_animation_type: Option<MediaFileAnimationType>,
|
||||
|
||||
/// If the media file has a subtype, we'll report it.
|
||||
/// This is mostly used for Bevy engine files.
|
||||
#[deprecated(note="This was for the Bevy engine. Do not use.")]
|
||||
pub maybe_media_subtype: Option<MediaFileSubtype>,
|
||||
|
||||
/// Extension for the engine to load over remote:// URLs.
|
||||
#[deprecated(note="This was for the Bevy engine. Do not use.")]
|
||||
pub maybe_engine_extension: Option<String>,
|
||||
@@ -321,8 +315,6 @@ 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: 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,
|
||||
@@ -460,7 +452,6 @@ async fn emulate_media_file_with_legacy_tts_result_lookup(
|
||||
media_type: MediaFileType::Audio, // NB: Always audio
|
||||
maybe_engine_category: None,
|
||||
maybe_animation_type: None,
|
||||
maybe_media_subtype: None,
|
||||
maybe_engine_extension: None,
|
||||
maybe_batch_token: None,
|
||||
maybe_scene_source_media_file_token: None,
|
||||
|
||||
+5
-1
@@ -331,9 +331,13 @@ pub async fn upload_audio_media_file_handler(
|
||||
UploadType::Filesystem
|
||||
};
|
||||
|
||||
let maybe_upload_filename = form.file.file_name.as_deref();
|
||||
|
||||
let (token, record_id) = insert_media_file_from_file_upload(InsertMediaFileFromUploadArgs {
|
||||
maybe_media_class: Some(MediaFileClass::Audio),
|
||||
media_file_type: MediaFileType::Audio,
|
||||
media_file_type: MediaFileType::try_from_mime_type(&mimetype)
|
||||
.or_else(|| maybe_upload_filename.and_then(MediaFileType::try_from_filename_or_extension))
|
||||
.unwrap_or(MediaFileType::Audio), // Coarse fallback for unrecognized files
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
maybe_creator_anonymous_visitor_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
|
||||
+6
-43
@@ -204,26 +204,11 @@ pub async fn process_upload_media_file(
|
||||
// do not have any open issues filed. They may simply be too old:
|
||||
// - .wma (audio/x-ms-wma)
|
||||
// - .avi (video/x-msvideo)
|
||||
media_file_type = match mimetype {
|
||||
// Audio
|
||||
"audio/aac" /* .aac */ => Some(MediaFileType::Audio),
|
||||
"audio/m4a" /* .m4a */ => Some(MediaFileType::Audio),
|
||||
"audio/mpeg" /* .mp3 */ => Some(MediaFileType::Audio),
|
||||
"audio/ogg" /* .ogg */ => Some(MediaFileType::Audio),
|
||||
"audio/opus" /* .opus */ => Some(MediaFileType::Audio),
|
||||
"audio/x-flac" /* .flac */ => Some(MediaFileType::Audio),
|
||||
"audio/x-wav" /* .wav */ => Some(MediaFileType::Audio),
|
||||
// Image — `webp` has no dedicated variant yet
|
||||
"image/gif" /* .gif */ => Some(MediaFileType::Gif),
|
||||
"image/jpeg" /* .jpg */ => Some(MediaFileType::Jpg),
|
||||
"image/png" /* .png */ => Some(MediaFileType::Png),
|
||||
"image/webp" /* .webp */ => Some(MediaFileType::Image),
|
||||
// Video
|
||||
"video/mp4" /* .mp4 */ => Some(MediaFileType::Video),
|
||||
"video/quicktime" /* .mov */ => Some(MediaFileType::Video),
|
||||
"video/webm" /* .webm */ => Some(MediaFileType::Video),
|
||||
_ => None,
|
||||
};
|
||||
// NB: mimetypes are gated by the `allowed_mimetypes` check above; this only
|
||||
// maps the already-permitted set to concrete media types.
|
||||
let maybe_upload_filename = upload_media_request.file_name.as_deref();
|
||||
media_file_type = MediaFileType::try_from_mime_type(mimetype)
|
||||
.or_else(|| maybe_upload_filename.and_then(MediaFileType::try_from_filename_or_extension));
|
||||
|
||||
let do_audio_decode = match mimetype {
|
||||
// TODO: Revisit when Safari can send us this metadata consistently
|
||||
@@ -313,29 +298,7 @@ pub async fn process_upload_media_file(
|
||||
},
|
||||
};
|
||||
|
||||
let media_file_class = match media_file_type {
|
||||
MediaFileType::Audio => MediaFileClass::Audio,
|
||||
MediaFileType::Image => MediaFileClass::Image,
|
||||
MediaFileType::Video => MediaFileClass::Video,
|
||||
MediaFileType::Bvh => MediaFileClass::Dimensional,
|
||||
MediaFileType::Fbx => MediaFileClass::Dimensional,
|
||||
MediaFileType::Obj => MediaFileClass::Dimensional,
|
||||
MediaFileType::Glb => MediaFileClass::Dimensional,
|
||||
MediaFileType::Gltf => MediaFileClass::Dimensional,
|
||||
MediaFileType::Spz => MediaFileClass::Dimensional,
|
||||
MediaFileType::SceneRon => MediaFileClass::Dimensional,
|
||||
MediaFileType::SceneJson => MediaFileClass::Dimensional,
|
||||
MediaFileType::Pmd => MediaFileClass::Dimensional,
|
||||
MediaFileType::Vmd => MediaFileClass::Dimensional,
|
||||
MediaFileType::Csv => MediaFileClass::Dimensional,
|
||||
MediaFileType::Pmx => MediaFileClass::Dimensional,
|
||||
MediaFileType::Jpg => MediaFileClass::Image,
|
||||
MediaFileType::Png => MediaFileClass::Image,
|
||||
MediaFileType::Gif => MediaFileClass::Image,
|
||||
MediaFileType::Mp4 => MediaFileClass::Video,
|
||||
MediaFileType::Wav => MediaFileClass::Audio,
|
||||
MediaFileType::Mp3 => MediaFileClass::Audio,
|
||||
};
|
||||
let media_file_class = media_file_type.to_media_class();
|
||||
|
||||
let upload_type = match upload_media_request.media_source {
|
||||
MediaFileUploadSource::Unknown => UploadType::Filesystem,
|
||||
|
||||
+5
-7
@@ -299,13 +299,11 @@ pub async fn upload_image_media_file_handler(
|
||||
UploadType::Filesystem
|
||||
};
|
||||
|
||||
let media_file_type = match mimetype.as_str() {
|
||||
"image/jpeg" => MediaFileType::Jpg,
|
||||
"image/png" => MediaFileType::Png,
|
||||
"image/gif" => MediaFileType::Gif,
|
||||
"image/webp" => MediaFileType::Image, // Fallback
|
||||
_ => MediaFileType::Image, // fallback
|
||||
};
|
||||
let maybe_upload_filename = form.file.file_name.as_deref();
|
||||
|
||||
let media_file_type = MediaFileType::try_from_mime_type(&mimetype)
|
||||
.or_else(|| maybe_upload_filename.and_then(MediaFileType::try_from_filename_or_extension))
|
||||
.unwrap_or(MediaFileType::Image); // Coarse fallback for unrecognized files
|
||||
|
||||
let (token, record_id) = insert_media_file_from_file_upload(InsertMediaFileFromUploadArgs {
|
||||
maybe_media_class: Some(MediaFileClass::Image),
|
||||
|
||||
+1
-5
@@ -389,11 +389,7 @@ fn validate_and_process_form(
|
||||
}
|
||||
};
|
||||
|
||||
let media_class = match media_type {
|
||||
MediaFileType::Jpg | MediaFileType::Png | MediaFileType::Gif => MediaFileClass::Image,
|
||||
MediaFileType::Mp4 => MediaFileClass::Video,
|
||||
_ => MediaFileClass::Dimensional,
|
||||
};
|
||||
let media_class = media_type.to_media_class();
|
||||
|
||||
Ok(FileInfo {
|
||||
media_class,
|
||||
|
||||
+5
-1
@@ -504,9 +504,13 @@ pub async fn upload_new_video_media_file_handler(
|
||||
UploadType::Filesystem
|
||||
};
|
||||
|
||||
let maybe_upload_filename = form.file.file_name.as_deref();
|
||||
|
||||
let (token, record_id) = insert_media_file_from_file_upload(InsertMediaFileFromUploadArgs {
|
||||
maybe_media_class: Some(MediaFileClass::Video),
|
||||
media_file_type: MediaFileType::Video,
|
||||
media_file_type: MediaFileType::try_from_mime_type(&mimetype)
|
||||
.or_else(|| maybe_upload_filename.and_then(MediaFileType::try_from_filename_or_extension))
|
||||
.unwrap_or(MediaFileType::Video), // Coarse fallback for unrecognized files
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
maybe_creator_anonymous_visitor_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
|
||||
+2
-1
@@ -221,7 +221,8 @@ pub async fn upload_video_media_file_handler(
|
||||
// TODO(bt, 2024-02-22): This should be a transaction.
|
||||
let (token, record_id) = insert_media_file_from_file_upload(InsertMediaFileFromUploadArgs {
|
||||
maybe_media_class: Some(MediaFileClass::Video),
|
||||
media_file_type: MediaFileType::Video,
|
||||
media_file_type: MediaFileType::try_from_mime_type(mimetype)
|
||||
.unwrap_or(MediaFileType::Video), // Coarse fallback for unrecognized mimes
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
maybe_creator_anonymous_visitor_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
|
||||
-1
@@ -231,7 +231,6 @@ pub async fn write_engine_asset_media_file_handler(
|
||||
media_file_type,
|
||||
maybe_engine_category: upload_media_request.maybe_engine_category,
|
||||
maybe_animation_type: upload_media_request.maybe_animation_type,
|
||||
maybe_media_subtype: None,
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
maybe_creator_anonymous_visitor_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
|
||||
-1
@@ -219,7 +219,6 @@ pub async fn write_scene_file_media_file_handler(
|
||||
media_file_type: MediaFileType::SceneJson,
|
||||
maybe_engine_category: Some(MediaFileEngineCategory::Scene),
|
||||
maybe_animation_type: None,
|
||||
maybe_media_subtype: None,
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
maybe_creator_anonymous_visitor_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
|
||||
+7
-10
@@ -202,15 +202,12 @@ impl MediaUploadKind {
|
||||
}
|
||||
|
||||
fn media_file_type(&self, mimetype: &str) -> MediaFileType {
|
||||
match self {
|
||||
MediaUploadKind::Image => match mimetype {
|
||||
"image/jpeg" => MediaFileType::Jpg,
|
||||
"image/png" => MediaFileType::Png,
|
||||
"image/gif" => MediaFileType::Gif,
|
||||
_ => MediaFileType::Image,
|
||||
},
|
||||
MediaUploadKind::Video => MediaFileType::Video,
|
||||
MediaUploadKind::Audio => MediaFileType::Audio,
|
||||
}
|
||||
MediaFileType::try_from_mime_type(mimetype)
|
||||
.unwrap_or(match self {
|
||||
// Coarse fallbacks for unrecognized mimes
|
||||
MediaUploadKind::Image => MediaFileType::Image,
|
||||
MediaUploadKind::Video => MediaFileType::Video,
|
||||
MediaUploadKind::Audio => MediaFileType::Audio,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -275,9 +275,13 @@ pub async fn omni_upload_audio_media_file_handler(
|
||||
UploadType::Filesystem
|
||||
};
|
||||
|
||||
let maybe_upload_filename = form.file.file_name.as_deref();
|
||||
|
||||
let (token, record_id) = insert_media_file_from_file_upload(InsertMediaFileFromUploadArgs {
|
||||
maybe_media_class: Some(MediaFileClass::Audio),
|
||||
media_file_type: MediaFileType::Audio,
|
||||
media_file_type: MediaFileType::try_from_mime_type(&mimetype)
|
||||
.or_else(|| maybe_upload_filename.and_then(MediaFileType::try_from_filename_or_extension))
|
||||
.unwrap_or(MediaFileType::Audio), // Coarse fallback for unrecognized files
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
// NB: AVT (anonymous visitor) tokens are a web-session concept; API-key callers have none.
|
||||
maybe_creator_anonymous_visitor_token: None,
|
||||
|
||||
+5
-7
@@ -259,13 +259,11 @@ pub async fn omni_upload_image_media_file_handler(
|
||||
UploadType::Filesystem
|
||||
};
|
||||
|
||||
let media_file_type = match mimetype.as_str() {
|
||||
"image/jpeg" => MediaFileType::Jpg,
|
||||
"image/png" => MediaFileType::Png,
|
||||
"image/gif" => MediaFileType::Gif,
|
||||
"image/webp" => MediaFileType::Image, // Fallback
|
||||
_ => MediaFileType::Image, // fallback
|
||||
};
|
||||
let maybe_upload_filename = form.file.file_name.as_deref();
|
||||
|
||||
let media_file_type = MediaFileType::try_from_mime_type(&mimetype)
|
||||
.or_else(|| maybe_upload_filename.and_then(MediaFileType::try_from_filename_or_extension))
|
||||
.unwrap_or(MediaFileType::Image); // Coarse fallback for unrecognized files
|
||||
|
||||
let (token, record_id) = insert_media_file_from_file_upload(InsertMediaFileFromUploadArgs {
|
||||
maybe_media_class: Some(MediaFileClass::Image),
|
||||
|
||||
+5
-1
@@ -456,9 +456,13 @@ pub async fn omni_upload_video_media_file_handler(
|
||||
UploadType::Filesystem
|
||||
};
|
||||
|
||||
let maybe_upload_filename = form.file.file_name.as_deref();
|
||||
|
||||
let (token, record_id) = insert_media_file_from_file_upload(InsertMediaFileFromUploadArgs {
|
||||
maybe_media_class: Some(MediaFileClass::Video),
|
||||
media_file_type: MediaFileType::Video,
|
||||
media_file_type: MediaFileType::try_from_mime_type(&mimetype)
|
||||
.or_else(|| maybe_upload_filename.and_then(MediaFileType::try_from_filename_or_extension))
|
||||
.unwrap_or(MediaFileType::Video), // Coarse fallback for unrecognized files
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
// NB: AVT (anonymous visitor) tokens are a web-session concept; API-key callers have none.
|
||||
maybe_creator_anonymous_visitor_token: None,
|
||||
|
||||
+8
-13
@@ -5,11 +5,10 @@ use actix_web::{web, HttpRequest};
|
||||
use artcraft_api_defs::omni_gen::cost_and_generate_requests::omni_gen_audio_cost_and_generate_request::OmniGenAudioCostAndGenerateRequest;
|
||||
use artcraft_api_defs::omni_gen::cost_response::omni_gen_audio_cost_response::OmniGenAudioCostResponse;
|
||||
use artcraft_router::api::router_provider::RouterProvider;
|
||||
use log::warn;
|
||||
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::endpoints::omni_gen::shared_utils::map_router_cost_error::map_router_cost_error;
|
||||
use crate::http_server::endpoints::omni_gen::generate::audio::helpers::hydrate_router_request::hydrate_to_router_request;
|
||||
use crate::http_server::endpoints::omni_gen::shared_utils::audio::validate_audio_request::validate_audio_request;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
/// Estimate the cost of an audio generation.
|
||||
@@ -29,22 +28,18 @@ pub async fn omni_gen_audio_cost_handler(
|
||||
request: Json<OmniGenAudioCostAndGenerateRequest>,
|
||||
_server_state: web::Data<Arc<ServerState>>,
|
||||
) -> Result<Json<OmniGenAudioCostResponse>, CommonWebError> {
|
||||
validate_audio_request(&request)?;
|
||||
|
||||
// NB: Deliberately no input validation here. The UI polls this endpoint
|
||||
// while the user is still composing the request (no prompt typed, nothing
|
||||
// attached), and pricing is a total function of the model and options.
|
||||
// Bad requests are rejected by the generate endpoint.
|
||||
let mut builder = hydrate_to_router_request(&request)?;
|
||||
|
||||
builder.provider = RouterProvider::Artcraft;
|
||||
builder.provider = RouterProvider::Artcraft; // NB: User is paying for ArtCraft credits / generation
|
||||
|
||||
let estimate = builder.build2()
|
||||
.map_err(|e| {
|
||||
warn!("Failed to build audio cost estimate: {}", e);
|
||||
CommonWebError::from_error(e)
|
||||
})?
|
||||
.map_err(map_router_cost_error)?
|
||||
.estimate_cost()
|
||||
.map_err(|e| {
|
||||
warn!("Failed to estimate audio cost: {}", e);
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
.map_err(map_router_cost_error)?;
|
||||
|
||||
Ok(Json(OmniGenAudioCostResponse {
|
||||
success: true,
|
||||
|
||||
+4
-10
@@ -8,9 +8,9 @@ use artcraft_router::api::image_list_ref::ImageListRef;
|
||||
use artcraft_router::api::router_provider::RouterProvider;
|
||||
use artcraft_router::generate::generate_image::generate_image_request_builder::GenerateImageRequestBuilder;
|
||||
use artcraft_router::generate::generate_image::image_generation_cost_estimate::ImageGenerationCostEstimate;
|
||||
use log::warn;
|
||||
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::endpoints::omni_gen::shared_utils::map_router_cost_error::map_router_cost_error;
|
||||
use crate::http_server::endpoints::omni_gen::generate::image::hydrate_to_router_request::hydrate_to_router_request;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
@@ -33,18 +33,12 @@ pub async fn omni_gen_image_cost_handler(
|
||||
) -> Result<Json<OmniGenImageCostResponse>, CommonWebError> {
|
||||
let mut builder = hydrate_to_router_request(&request)?;
|
||||
|
||||
builder.provider = RouterProvider::Artcraft; // NB: Explicitly spell this out.
|
||||
builder.provider = RouterProvider::Artcraft; // NB: User is paying for ArtCraft credits / generation
|
||||
|
||||
let estimate = builder.build2()
|
||||
.map_err(|e| {
|
||||
warn!("Failed to build cost estimate: {}", e);
|
||||
CommonWebError::from_error(e)
|
||||
})?
|
||||
.map_err(map_router_cost_error)?
|
||||
.estimate_cost()
|
||||
.map_err(|e| {
|
||||
warn!("Failed to estimate cost: {}", e);
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
.map_err(map_router_cost_error)?;
|
||||
|
||||
Ok(Json(OmniGenImageCostResponse {
|
||||
success: true,
|
||||
|
||||
+8
-13
@@ -5,11 +5,10 @@ use actix_web::{web, HttpRequest};
|
||||
use artcraft_api_defs::omni_gen::cost_and_generate_requests::omni_gen_mesh_cost_and_generate_request::OmniGenMeshCostAndGenerateRequest;
|
||||
use artcraft_api_defs::omni_gen::cost_response::omni_gen_mesh_cost_response::OmniGenMeshCostResponse;
|
||||
use artcraft_router::api::router_provider::RouterProvider;
|
||||
use log::warn;
|
||||
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::endpoints::omni_gen::shared_utils::map_router_cost_error::map_router_cost_error;
|
||||
use crate::http_server::endpoints::omni_gen::generate::mesh::helpers::hydrate_router_request::hydrate_to_router_request;
|
||||
use crate::http_server::endpoints::omni_gen::shared_utils::mesh::validate_mesh_request::validate_mesh_request;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
/// Estimate the cost of a mesh (3D object) generation.
|
||||
@@ -29,22 +28,18 @@ pub async fn omni_gen_mesh_cost_handler(
|
||||
request: Json<OmniGenMeshCostAndGenerateRequest>,
|
||||
_server_state: web::Data<Arc<ServerState>>,
|
||||
) -> Result<Json<OmniGenMeshCostResponse>, CommonWebError> {
|
||||
validate_mesh_request(&request)?;
|
||||
|
||||
// NB: Deliberately no input validation here. The UI polls this endpoint
|
||||
// while the user is still composing the request (no prompt typed, nothing
|
||||
// attached), and pricing is a total function of the model and options.
|
||||
// Bad requests are rejected by the generate endpoint.
|
||||
let mut builder = hydrate_to_router_request(&request)?;
|
||||
|
||||
builder.provider = RouterProvider::Artcraft;
|
||||
builder.provider = RouterProvider::Artcraft; // NB: User is paying for ArtCraft credits / generation
|
||||
|
||||
let estimate = builder.build2()
|
||||
.map_err(|e| {
|
||||
warn!("Failed to build mesh cost estimate: {}", e);
|
||||
CommonWebError::from_error(e)
|
||||
})?
|
||||
.map_err(map_router_cost_error)?
|
||||
.estimate_cost()
|
||||
.map_err(|e| {
|
||||
warn!("Failed to estimate mesh cost: {}", e);
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
.map_err(map_router_cost_error)?;
|
||||
|
||||
Ok(Json(OmniGenMeshCostResponse {
|
||||
success: true,
|
||||
|
||||
+8
-13
@@ -5,11 +5,10 @@ use actix_web::{web, HttpRequest};
|
||||
use artcraft_api_defs::omni_gen::cost_and_generate_requests::omni_gen_splat_cost_and_generate_request::OmniGenSplatCostAndGenerateRequest;
|
||||
use artcraft_api_defs::omni_gen::cost_response::omni_gen_splat_cost_response::OmniGenSplatCostResponse;
|
||||
use artcraft_router::api::router_provider::RouterProvider;
|
||||
use log::warn;
|
||||
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::endpoints::omni_gen::shared_utils::map_router_cost_error::map_router_cost_error;
|
||||
use crate::http_server::endpoints::omni_gen::generate::splat::helpers::hydrate_router_request::hydrate_to_router_request;
|
||||
use crate::http_server::endpoints::omni_gen::shared_utils::splat::validate_splat_request::validate_splat_request;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
/// Estimate the cost of a splat (3D world) generation.
|
||||
@@ -29,22 +28,18 @@ pub async fn omni_gen_splat_cost_handler(
|
||||
request: Json<OmniGenSplatCostAndGenerateRequest>,
|
||||
_server_state: web::Data<Arc<ServerState>>,
|
||||
) -> Result<Json<OmniGenSplatCostResponse>, CommonWebError> {
|
||||
validate_splat_request(&request)?;
|
||||
|
||||
// NB: Deliberately no input validation here. The UI polls this endpoint
|
||||
// while the user is still composing the request (no prompt typed, nothing
|
||||
// attached), and pricing is a total function of the model and options.
|
||||
// Bad requests are rejected by the generate endpoint.
|
||||
let mut builder = hydrate_to_router_request(&request)?;
|
||||
|
||||
builder.provider = RouterProvider::Artcraft;
|
||||
builder.provider = RouterProvider::Artcraft; // NB: User is paying for ArtCraft credits / generation
|
||||
|
||||
let estimate = builder.build2()
|
||||
.map_err(|e| {
|
||||
warn!("Failed to build splat cost estimate: {}", e);
|
||||
CommonWebError::from_error(e)
|
||||
})?
|
||||
.map_err(map_router_cost_error)?
|
||||
.estimate_cost()
|
||||
.map_err(|e| {
|
||||
warn!("Failed to estimate splat cost: {}", e);
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
.map_err(map_router_cost_error)?;
|
||||
|
||||
Ok(Json(OmniGenSplatCostResponse {
|
||||
success: true,
|
||||
|
||||
+102
-18
@@ -1,15 +1,11 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::endpoints::omni_gen::shared_utils::map_router_cost_error::map_router_cost_error;
|
||||
use crate::http_server::endpoints::omni_gen::generate::video::helpers::hydrate_router_request::hydrate_to_router_request;
|
||||
use crate::http_server::endpoints::omni_gen::shared_utils::video::validate_video_request::validate_video_request;
|
||||
use crate::state::server_state::ServerState;
|
||||
use actix_web::web::Json;
|
||||
use actix_web::{web, HttpRequest};
|
||||
use actix_web::HttpRequest;
|
||||
use artcraft_api_defs::omni_gen::cost_and_generate_requests::omni_gen_video_cost_and_generate_request::OmniGenVideoCostAndGenerateRequest;
|
||||
use artcraft_api_defs::omni_gen::cost_response::omni_gen_video_cost_response::OmniGenVideoCostResponse;
|
||||
use artcraft_router::api::router_provider::RouterProvider;
|
||||
use log::warn;
|
||||
|
||||
/// Estimate the cost of a video generation.
|
||||
#[utoipa::path(
|
||||
@@ -26,24 +22,19 @@ use log::warn;
|
||||
pub async fn omni_gen_video_cost_handler(
|
||||
_http_request: HttpRequest,
|
||||
request: Json<OmniGenVideoCostAndGenerateRequest>,
|
||||
_server_state: web::Data<Arc<ServerState>>,
|
||||
) -> Result<Json<OmniGenVideoCostResponse>, CommonWebError> {
|
||||
validate_video_request(&request)?;
|
||||
|
||||
// NB: Deliberately no input validation here. The UI polls this endpoint
|
||||
// while the user is still composing the request (no prompt typed, nothing
|
||||
// attached), and pricing is a total function of the model and options.
|
||||
// Bad requests are rejected by the generate endpoint.
|
||||
let mut builder = hydrate_to_router_request(&request)?;
|
||||
|
||||
builder.provider = RouterProvider::Artcraft;
|
||||
builder.provider = RouterProvider::Artcraft; // NB: User is paying for ArtCraft credits / generation
|
||||
|
||||
let estimate = builder.build2()
|
||||
.map_err(|e| {
|
||||
warn!("Failed to build cost estimate: {}", e);
|
||||
CommonWebError::from_error(e)
|
||||
})?
|
||||
.map_err(map_router_cost_error)?
|
||||
.estimate_cost()
|
||||
.map_err(|e| {
|
||||
warn!("Failed to estimate cost: {}", e);
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
.map_err(map_router_cost_error)?;
|
||||
|
||||
Ok(Json(OmniGenVideoCostResponse {
|
||||
success: true,
|
||||
@@ -56,3 +47,96 @@ pub async fn omni_gen_video_cost_handler(
|
||||
failures_are_refunded: estimate.failures_are_refunded,
|
||||
}))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use actix_http::StatusCode;
|
||||
use actix_web::test::TestRequest;
|
||||
use actix_web::ResponseError;
|
||||
use enums::common::generation::common_video_model::CommonVideoModel;
|
||||
|
||||
use super::*;
|
||||
|
||||
mod cost_without_inputs_tests {
|
||||
use super::*;
|
||||
|
||||
/// Regression: xAI's v1.5 rejects text-to-video at generation time, but
|
||||
/// the cost endpoint must still quote an image-less request — the cost
|
||||
/// UI polls for a price before the user attaches an image. This request
|
||||
/// shape used to be rejected (handler validation, then a router build
|
||||
/// error that surfaced as a 500).
|
||||
#[tokio::test]
|
||||
async fn grok_1p5_without_an_image_gets_a_quote() {
|
||||
let response = post_cost_request(base_request(CommonVideoModel::GrokImagineVideo1p5))
|
||||
.await
|
||||
.expect("image-less grok 1.5 cost estimate should succeed");
|
||||
assert!(response.success);
|
||||
assert!(response.cost_in_credits.unwrap() > 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn bare_model_gets_a_quote_for_representative_models() {
|
||||
for model in [
|
||||
CommonVideoModel::GrokImagineVideo,
|
||||
CommonVideoModel::Kling3p0Pro,
|
||||
CommonVideoModel::Seedance2p0,
|
||||
CommonVideoModel::Sora2,
|
||||
CommonVideoModel::Veo3p1,
|
||||
CommonVideoModel::ViduQ3,
|
||||
] {
|
||||
let response = post_cost_request(base_request(model))
|
||||
.await
|
||||
.unwrap_or_else(|e| panic!("bare-model cost estimate should succeed for {model:?}: {e:?}"));
|
||||
assert!(response.cost_in_credits.unwrap() > 0, "no cost for {model:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod error_mapping_tests {
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn unroutable_model_returns_400_not_500() {
|
||||
// grok_video has no Artcraft route in the router; this must surface
|
||||
// as a 400, not a 500 (it 500'd in production before the
|
||||
// map_router_cost_error mapping).
|
||||
let err = post_cost_request(base_request(CommonVideoModel::GrokVideo))
|
||||
.await
|
||||
.expect_err("unroutable model should be rejected");
|
||||
assert_eq!(err.status_code(), StatusCode::BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
async fn post_cost_request(
|
||||
body: OmniGenVideoCostAndGenerateRequest,
|
||||
) -> Result<OmniGenVideoCostResponse, CommonWebError> {
|
||||
let http_request = TestRequest::post()
|
||||
.uri("/v1/omni_gen/cost/video")
|
||||
.to_http_request();
|
||||
omni_gen_video_cost_handler(http_request, Json(body))
|
||||
.await
|
||||
.map(Json::into_inner)
|
||||
}
|
||||
|
||||
fn base_request(model: CommonVideoModel) -> OmniGenVideoCostAndGenerateRequest {
|
||||
OmniGenVideoCostAndGenerateRequest {
|
||||
idempotency_token: None,
|
||||
model: Some(model),
|
||||
prompt: None,
|
||||
negative_prompt: None,
|
||||
start_frame_image_media_token: None,
|
||||
end_frame_image_media_token: None,
|
||||
reference_image_media_tokens: None,
|
||||
reference_video_media_tokens: None,
|
||||
reference_audio_media_tokens: None,
|
||||
reference_character_tokens: None,
|
||||
resolution: None,
|
||||
aspect_ratio: None,
|
||||
bitrate: None,
|
||||
quality: None,
|
||||
duration_seconds: None,
|
||||
video_batch_count: None,
|
||||
generate_audio: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -7,7 +7,11 @@ const SEED_AUDIO_SAMPLE_RATES_HZ: [u32; 6] = [8000, 16000, 24000, 32000, 44100,
|
||||
const SEED_AUDIO_MAX_AUDIO_REFERENCES: usize = 3;
|
||||
const SEED_AUDIO_MAX_IMAGE_REFERENCES: usize = 1;
|
||||
|
||||
/// Validate requests before they incur user costs or send API requests.
|
||||
/// Validate generation requests before they incur user costs or send API
|
||||
/// requests.
|
||||
///
|
||||
/// NB: The cost endpoint deliberately does NOT call this — the UI polls for
|
||||
/// a price while the user is still composing the request.
|
||||
pub fn validate_audio_request(
|
||||
request: &OmniGenAudioCostAndGenerateRequest,
|
||||
) -> Result<(), CommonWebError> {
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
use artcraft_router::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use log::warn;
|
||||
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
/// Map a router error from a cost-estimation path to an HTTP error.
|
||||
///
|
||||
/// Caller mistakes — a model the router can't price (e.g. no Artcraft
|
||||
/// route), bad option values — surface as 400s with the router's message.
|
||||
/// Infrastructure-class errors stay 500s.
|
||||
pub fn map_router_cost_error(error: ArtcraftRouterError) -> CommonWebError {
|
||||
match &error {
|
||||
ArtcraftRouterError::InvalidInput(reason) => {
|
||||
warn!("Cost estimate rejected: {}", reason);
|
||||
CommonWebError::BadInputWithSimpleMessage(reason.to_string())
|
||||
}
|
||||
ArtcraftRouterError::Client(_)
|
||||
| ArtcraftRouterError::UnsupportedModel(_)
|
||||
| ArtcraftRouterError::UnsupportedProviderAndModelForNewApi(_) => {
|
||||
// NB: Don't leak configuration details.
|
||||
warn!("Cost estimate rejected: {}", error);
|
||||
CommonWebError::BadInputWithSimpleMessage("Bad input for model".to_string())
|
||||
}
|
||||
_ => {
|
||||
warn!("Cost estimate failed: {}", error);
|
||||
CommonWebError::from_error(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -18,7 +18,11 @@ const MESHY_MAX_FACE_COUNT: u64 = 300_000;
|
||||
/// Rodin v2.5 Fast accepts up to five input images.
|
||||
const RODIN_MAX_REFERENCE_IMAGES: usize = 5;
|
||||
|
||||
/// Validate requests before they incur user costs or send API requests.
|
||||
/// Validate generation requests before they incur user costs or send API
|
||||
/// requests.
|
||||
///
|
||||
/// NB: The cost endpoint deliberately does NOT call this — the UI polls for
|
||||
/// a price while the user is still composing the request.
|
||||
pub fn validate_mesh_request(
|
||||
request: &OmniGenMeshCostAndGenerateRequest,
|
||||
) -> Result<(), CommonWebError> {
|
||||
|
||||
+1
@@ -1,4 +1,5 @@
|
||||
pub mod audio;
|
||||
pub mod map_router_cost_error;
|
||||
pub mod map_seedance2pro_router_error;
|
||||
pub mod mesh;
|
||||
pub mod splat;
|
||||
|
||||
+5
-1
@@ -5,7 +5,11 @@ use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
/// World Labs MultiImage input accepts up to this many reference images.
|
||||
const MAX_IMAGE_REFERENCES: usize = 4;
|
||||
|
||||
/// Validate requests before they incur user costs or send API requests.
|
||||
/// Validate generation requests before they incur user costs or send API
|
||||
/// requests.
|
||||
///
|
||||
/// NB: The cost endpoint deliberately does NOT call this — the UI polls for
|
||||
/// a price while the user is still composing the request.
|
||||
///
|
||||
/// Model presence is enforced later during hydration; the input-shape rules
|
||||
/// below apply uniformly to all Marble models.
|
||||
|
||||
+2
-2
@@ -134,9 +134,9 @@ pub async fn set_model_weight_cover_image_handler(
|
||||
//let can_use_image = media_file.creator_set_visibility == Visibility::Public
|
||||
// && media_file.media_type == MediaFileType::Image;
|
||||
|
||||
let can_use_image = media_file.media_type == MediaFileType::Image;
|
||||
let can_use_image = media_file.media_type.is_image();
|
||||
|
||||
if !can_use_image {
|
||||
if !can_use_image {
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("Invalid media file token.".to_string()));
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -158,7 +158,7 @@ pub async fn update_weight_handler(
|
||||
let maybe_media_file_type = maybe_media_file.map(|media_file| media_file.media_type);
|
||||
|
||||
match maybe_media_file_type {
|
||||
Some(MediaFileType::Image) => cover_image = Some(CoverImageOption::SetCoverImage(media_file_token)),
|
||||
Some(media_file_type) if media_file_type.is_image() => cover_image = Some(CoverImageOption::SetCoverImage(media_file_token)),
|
||||
None => return Err(CommonWebError::BadInputWithSimpleMessage("Media file does not exist".to_string())),
|
||||
_ => return Err(CommonWebError::BadInputWithSimpleMessage("Media file is the wrong type".to_string())),
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ describe("MediaFilesApi", () => {
|
||||
},
|
||||
maybe_duration_millis: 0,
|
||||
maybe_engine_category: "scene",
|
||||
maybe_media_subtype: "mixamo",
|
||||
maybe_model_weight_info: {
|
||||
maybe_cover_image_public_bucket_path: "string",
|
||||
maybe_weight_creator: {
|
||||
|
||||
@@ -31,28 +31,3 @@ export enum MediaFileType {
|
||||
None = "none",
|
||||
}
|
||||
|
||||
export enum MediaFileSubtype {
|
||||
/// Animation file from Mixamo
|
||||
/// Primarily used for FBX and GLB.
|
||||
Mixamo = "mixamo",
|
||||
|
||||
/// Animation file from MocapNet
|
||||
/// Primarily used for BVH.
|
||||
MocapNet = "mocap_net",
|
||||
|
||||
/// Generic animation case
|
||||
/// Used for BVH files, but can also pertain to animation-only files of other types.
|
||||
AnimationOnly = "animation_only",
|
||||
|
||||
// TODO(bt,2024-03-08): Migrate records and code, then remove
|
||||
/// DEPRECATED: Use `SceneImport` instead.
|
||||
Scene = "scene",
|
||||
|
||||
/// Generic 3D scene file.
|
||||
/// Can pertain to glTF, glB, FBX, etc.
|
||||
SceneImport = "scene_import",
|
||||
|
||||
/// Native Storyteller scene format.
|
||||
/// Typically stored in a `.scn.ron` file.
|
||||
StorytellerScene = "storyteller_scene",
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { MediaFileClass } from "../enums/MediaFileClass";
|
||||
import { MediaFileType, MediaFileSubtype } from "../enums/MediaFileType";
|
||||
import { MediaFileType } from "../enums/MediaFileType";
|
||||
import { WeightCategory } from "../enums/WeightCategory";
|
||||
import { WeightType } from "../enums/WeightType";
|
||||
import { UserInfo } from "./Users";
|
||||
@@ -9,7 +9,6 @@ export interface MediaFile {
|
||||
media_type: MediaFileType;
|
||||
media_class: MediaFileClass | null;
|
||||
maybe_animation_type: string | null;
|
||||
maybe_media_subtype: MediaFileSubtype | null;
|
||||
maybe_engine_extension: string | null;
|
||||
maybe_batch_token: string;
|
||||
maybe_original_filename: string | null;
|
||||
|
||||
@@ -50,7 +50,6 @@ export {
|
||||
FilterMediaClasses,
|
||||
FilterMediaType,
|
||||
MediaFileType,
|
||||
MediaFileSubtype,
|
||||
MediaFileClass,
|
||||
ToastTypes,
|
||||
WeightCategory,
|
||||
|
||||
@@ -34,28 +34,3 @@ export enum MediaFileType {
|
||||
None = "none",
|
||||
}
|
||||
|
||||
export enum MediaFileSubtype {
|
||||
/// Animation file from Mixamo
|
||||
/// Primarily used for FBX and GLB.
|
||||
Mixamo = "mixamo",
|
||||
|
||||
/// Animation file from MocapNet
|
||||
/// Primarily used for BVH.
|
||||
MocapNet = "mocap_net",
|
||||
|
||||
/// Generic animation case
|
||||
/// Used for BVH files, but can also pertain to animation-only files of other types.
|
||||
AnimationOnly = "animation_only",
|
||||
|
||||
// TODO(bt,2024-03-08): Migrate records and code, then remove
|
||||
/// DEPRECATED: Use `SceneImport` instead.
|
||||
Scene = "scene",
|
||||
|
||||
/// Generic 3D scene file.
|
||||
/// Can pertain to glTF, glB, FBX, etc.
|
||||
SceneImport = "scene_import",
|
||||
|
||||
/// Native Storyteller scene format.
|
||||
/// Typically stored in a `.scn.ron` file.
|
||||
StorytellerScene = "storyteller_scene",
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import { UserDetailsLight } from "./types";
|
||||
|
||||
import {
|
||||
MediaFileClass,
|
||||
MediaFileSubtype,
|
||||
MediaFileType,
|
||||
WeightCategory,
|
||||
WeightType,
|
||||
@@ -13,7 +12,6 @@ export interface MediaInfo {
|
||||
media_type: MediaFileType;
|
||||
media_class: MediaFileClass | null;
|
||||
maybe_animation_type: string | null;
|
||||
maybe_media_subtype: MediaFileSubtype | null;
|
||||
maybe_engine_extension: string | null;
|
||||
maybe_batch_token: string;
|
||||
maybe_original_filename: string | null;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
/// Basic information to display a user and their avatar.
|
||||
import {
|
||||
MediaFileClass,
|
||||
MediaFileSubtype,
|
||||
MediaFileType,
|
||||
WeightCategory,
|
||||
WeightType,
|
||||
@@ -29,7 +28,6 @@ export interface MediaFile {
|
||||
token: string;
|
||||
media_type: MediaFileType;
|
||||
media_class: MediaFileClass | null;
|
||||
maybe_media_subtype: MediaFileSubtype | null;
|
||||
public_bucket_path: string;
|
||||
maybe_engine_extension: string | null;
|
||||
maybe_batch_token: string;
|
||||
|
||||
Reference in New Issue
Block a user