From 9cb6f3a60c3ccfa40fe2e7d92117f975107b64f3 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Sun, 15 Jun 2025 01:42:18 -0400 Subject: [PATCH] rename endpoint, add aspect ratio control --- .../enqueue/image/handle_image_artcraft.rs | 4 +- .../enqueue/video/handle_video_artcraft.rs | 10 +++-- .../enqueue/video/handle_video_fal.rs | 7 ++-- .../fal_kling_image_to_video_command.rs | 11 ++--- ...=> enqueue_kling_16_pro_image_to_video.rs} | 42 +++++++++++++------ .../src/requests/queue/video_gen/mod.rs | 2 +- ...ue_kling_16_pro_image_to_video_webhook.rs} | 25 ++++++++--- .../src/requests/webhook/video/mod.rs | 2 +- ...> generate_kling_16_pro_image_to_video.rs} | 10 ++--- .../src/generate/video/mod.rs | 2 +- ... generate_kling_1_6_pro_image_to_video.rs} | 19 +++++++-- .../src/generate/video/mod.rs | 2 +- ...> generate_kling_1_6_pro_video_handler.rs} | 33 +++++++++------ .../endpoints/generate/video/mod.rs | 2 +- .../http_server/routes/add_generate_routes.rs | 6 +-- 15 files changed, 117 insertions(+), 60 deletions(-) rename crates/lib/api_clients/fal_client/src/requests/queue/video_gen/{enqueue_kling_16_image_to_video.rs => enqueue_kling_16_pro_image_to_video.rs} (57%) rename crates/lib/api_clients/fal_client/src/requests/webhook/video/{enqueue_kling_16_image_to_video_webhook.rs => enqueue_kling_16_pro_image_to_video_webhook.rs} (76%) rename crates/lib/api_clients/storyteller_client/src/generate/video/{generate_kling16_image_to_video.rs => generate_kling_16_pro_image_to_video.rs} (80%) rename crates/schema/public/api/artcraft_api_defs/src/generate/video/{generate_kling_1_6_image_to_video.rs => generate_kling_1_6_pro_image_to_video.rs} (53%) rename crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/{generate_kling_1_6_video_handler.rs => generate_kling_1_6_pro_video_handler.rs} (83%) diff --git a/crates/desktop/artcraft/src/core/commands/enqueue/image/handle_image_artcraft.rs b/crates/desktop/artcraft/src/core/commands/enqueue/image/handle_image_artcraft.rs index ad3e75c18b..3594e5117c 100644 --- a/crates/desktop/artcraft/src/core/commands/enqueue/image/handle_image_artcraft.rs +++ b/crates/desktop/artcraft/src/core/commands/enqueue/image/handle_image_artcraft.rs @@ -15,7 +15,7 @@ use crate::services::storyteller::state::storyteller_credential_manager::Storyte use anyhow::anyhow; use artcraft_api_defs::generate::image::generate_flux_pro_11_ultra_text_to_image::GenerateFluxPro11UltraTextToImageRequest; use artcraft_api_defs::generate::object::generate_hunyuan_2_image_to_3d::GenerateHunyuan2ImageTo3dRequest; -use artcraft_api_defs::generate::video::generate_kling_1_6_image_to_video::GenerateKling16ImageToVideoRequest; +use artcraft_api_defs::generate::video::generate_kling_1_6_pro_image_to_video::GenerateKling16ProImageToVideoRequest; use fal_client::creds::fal_api_key::FalApiKey; use fal_client::requests::queue::enqueue_hunyuan2_image_to_3d::{enqueue_hunyuan2_image_to_3d, Hunyuan2Args}; use fal_client::requests::queue::image_gen::enqueue_flux_pro_11_ultra_text_to_image::{enqueue_flux_pro_11_ultra_text_to_image, FluxPro11UltraTextToImageArgs}; @@ -24,7 +24,7 @@ use idempotency::uuid::generate_random_uuid; use log::{error, info, warn}; use storyteller_client::generate::image::generate_flux_pro_11_ultra_text_to_image::generate_flux_pro_11_ultra_text_to_image; use storyteller_client::generate::object::generate_hunyuan2_image_to_3d::generate_hunyuan2_image_to_3d; -use storyteller_client::generate::video::generate_kling16_image_to_video::generate_kling16_image_to_video; +use storyteller_client::generate::video::generate_kling_16_pro_image_to_video::generate_kling_16_pro_image_to_video; use storyteller_client::utils::api_host::ApiHost; use tauri::{AppHandle, State}; diff --git a/crates/desktop/artcraft/src/core/commands/enqueue/video/handle_video_artcraft.rs b/crates/desktop/artcraft/src/core/commands/enqueue/video/handle_video_artcraft.rs index b7d2908016..c3a3ec4de9 100644 --- a/crates/desktop/artcraft/src/core/commands/enqueue/video/handle_video_artcraft.rs +++ b/crates/desktop/artcraft/src/core/commands/enqueue/video/handle_video_artcraft.rs @@ -16,17 +16,18 @@ use crate::services::sora::state::sora_task_queue::SoraTaskQueue; use crate::services::storyteller::state::storyteller_credential_manager::StorytellerCredentialManager; use anyhow::anyhow; use artcraft_api_defs::generate::object::generate_hunyuan_2_image_to_3d::GenerateHunyuan2ImageTo3dRequest; +use artcraft_api_defs::generate::video::generate_kling_1_6_pro_image_to_video::{GenerateKling16ProAspectRatio, GenerateKling16ProImageToVideoRequest}; use fal_client::creds::fal_api_key::FalApiKey; use fal_client::requests::queue::enqueue_hunyuan2_image_to_3d::{enqueue_hunyuan2_image_to_3d, Hunyuan2Args}; use fal_client::requests::queue::image_gen::enqueue_flux_pro_11_ultra_text_to_image::{enqueue_flux_pro_11_ultra_text_to_image, FluxPro11UltraTextToImageArgs}; use fal_client::requests::queue::image_gen::enqueue_recraft3_text_to_image::{enqueue_recraft3_text_to_image, Recraft3TextToImageArgs}; +use fal_client::requests::queue::video_gen::enqueue_kling_16_pro_image_to_video::Kling16ProAspectRatio; use idempotency::uuid::generate_random_uuid; use log::{error, info, warn}; use storyteller_client::generate::object::generate_hunyuan2_image_to_3d::generate_hunyuan2_image_to_3d; +use storyteller_client::generate::video::generate_kling_16_pro_image_to_video::generate_kling_16_pro_image_to_video; use storyteller_client::utils::api_host::ApiHost; use tauri::{AppHandle, State}; -use artcraft_api_defs::generate::video::generate_kling_1_6_image_to_video::GenerateKling16ImageToVideoRequest; -use storyteller_client::generate::video::generate_kling16_image_to_video::generate_kling16_image_to_video; pub async fn handle_video_artcraft( request: EnqueueImageToVideoRequest, @@ -71,12 +72,13 @@ pub async fn handle_video_artcraft( Some(EnqueueImageToVideoModel::Kling16) => { info!("enqueue Kling 1.6"); selected_model = Some(GenerationModel::Kling1_6); - let request = GenerateKling16ImageToVideoRequest { + let request = GenerateKling16ProImageToVideoRequest { uuid_idempotency_token, media_file_token: request.image_media_token, + aspect_ratio: Some(GenerateKling16ProAspectRatio::WideSixteenNine), prompt: None, }; - let result = generate_kling16_image_to_video( + let result = generate_kling_16_pro_image_to_video( &ApiHost::Storyteller, Some(&creds), request, diff --git a/crates/desktop/artcraft/src/core/commands/enqueue/video/handle_video_fal.rs b/crates/desktop/artcraft/src/core/commands/enqueue/video/handle_video_fal.rs index 283966679d..3204a7b154 100644 --- a/crates/desktop/artcraft/src/core/commands/enqueue/video/handle_video_fal.rs +++ b/crates/desktop/artcraft/src/core/commands/enqueue/video/handle_video_fal.rs @@ -18,7 +18,7 @@ use fal_client::creds::fal_api_key::FalApiKey; use fal_client::requests::queue::enqueue_hunyuan2_image_to_3d::{enqueue_hunyuan2_image_to_3d, Hunyuan2Args}; use fal_client::requests::queue::image_gen::enqueue_flux_pro_11_ultra_text_to_image::{enqueue_flux_pro_11_ultra_text_to_image, FluxPro11UltraTextToImageArgs}; use fal_client::requests::queue::image_gen::enqueue_recraft3_text_to_image::{enqueue_recraft3_text_to_image, Recraft3TextToImageArgs}; -use fal_client::requests::queue::video_gen::enqueue_kling_16_image_to_video::{enqueue_kling_16_image_to_video, Kling16Args, Kling16Duration}; +use fal_client::requests::queue::video_gen::enqueue_kling_16_pro_image_to_video::{enqueue_kling_16_pro_image_to_video, Kling16ProArgs, Kling16ProAspectRatio, Kling16ProDuration}; use log::{error, info, warn}; use tauri::AppHandle; @@ -73,10 +73,11 @@ pub async fn handle_video_fal( Some(EnqueueImageToVideoModel::Kling16) => { info!("enqueue Kling 1.6 image to video"); selected_model = Some(GenerationModel::Kling1_6); - enqueue_kling_16_image_to_video(Kling16Args { + enqueue_kling_16_pro_image_to_video(Kling16ProArgs { image_path: filename, api_key: &api_key, - duration: Kling16Duration::Default, + duration: Kling16ProDuration::Default, + aspect_ratio: Kling16ProAspectRatio::WideSixteenNine, prompt: "", }).await } diff --git a/crates/desktop/artcraft/src/services/fal/commands/fal_kling_image_to_video_command.rs b/crates/desktop/artcraft/src/services/fal/commands/fal_kling_image_to_video_command.rs index 828dd0fc24..3dbd65c081 100644 --- a/crates/desktop/artcraft/src/services/fal/commands/fal_kling_image_to_video_command.rs +++ b/crates/desktop/artcraft/src/services/fal/commands/fal_kling_image_to_video_command.rs @@ -1,3 +1,4 @@ +use crate::core::artcraft_error::ArtcraftError; use crate::core::commands::response::failure_response_wrapper::{CommandErrorResponseWrapper, CommandErrorStatus}; use crate::core::commands::response::shorthand::Response; use crate::core::events::basic_sendable_event_trait::BasicSendableEvent; @@ -24,7 +25,7 @@ use base64::prelude::BASE64_STANDARD; use base64::{DecodeError, Engine}; use errors::{AnyhowError, AnyhowResult}; use fal_client::error::fal_error_plus::FalErrorPlus; -use fal_client::requests::queue::video_gen::enqueue_kling_16_image_to_video::{enqueue_kling_16_image_to_video, Kling16Args, Kling16Duration}; +use fal_client::requests::queue::video_gen::enqueue_kling_16_pro_image_to_video::{enqueue_kling_16_pro_image_to_video, Kling16ProArgs, Kling16ProAspectRatio, Kling16ProDuration}; use filesys::file_read_bytes::file_read_bytes; use image::codecs::png::{CompressionType, FilterType, PngEncoder}; use image::{DynamicImage, EncodableLayout, ImageReader}; @@ -49,14 +50,13 @@ use std::path::PathBuf; use std::time::Duration; use storyteller_client::error::api_error::ApiError; use storyteller_client::error::api_error::ApiError::InternalServerError; +use storyteller_client::error::storyteller_error::StorytellerError; use storyteller_client::media_files::get_media_file::{get_media_file, GetMediaFileSuccessResponse}; use storyteller_client::media_files::upload_image_media_file_from_file::upload_image_media_file_from_file; use storyteller_client::utils::api_host::ApiHost; use tauri::{AppHandle, Emitter, Manager, State}; use tempfile::NamedTempFile; -use storyteller_client::error::storyteller_error::StorytellerError; use tokens::tokens::media_files::MediaFileToken; -use crate::core::artcraft_error::ArtcraftError; #[derive(Deserialize)] pub struct FalKlingImageToVideoRequest { @@ -233,10 +233,11 @@ pub async fn image_to_video( let filename = temp_download.path().to_path_buf(); - let enqueued = enqueue_kling_16_image_to_video(Kling16Args { + let enqueued = enqueue_kling_16_pro_image_to_video(Kling16ProArgs { image_path: filename, api_key: &api_key, - duration: Kling16Duration::Default, + duration: Kling16ProDuration::Default, + aspect_ratio: Kling16ProAspectRatio::WideSixteenNine, prompt: request.prompt.as_deref().unwrap_or(""), }).await?; diff --git a/crates/lib/api_clients/fal_client/src/requests/queue/video_gen/enqueue_kling_16_image_to_video.rs b/crates/lib/api_clients/fal_client/src/requests/queue/video_gen/enqueue_kling_16_pro_image_to_video.rs similarity index 57% rename from crates/lib/api_clients/fal_client/src/requests/queue/video_gen/enqueue_kling_16_image_to_video.rs rename to crates/lib/api_clients/fal_client/src/requests/queue/video_gen/enqueue_kling_16_pro_image_to_video.rs index a664299a06..c07455c22d 100644 --- a/crates/lib/api_clients/fal_client/src/requests/queue/video_gen/enqueue_kling_16_image_to_video.rs +++ b/crates/lib/api_clients/fal_client/src/requests/queue/video_gen/enqueue_kling_16_pro_image_to_video.rs @@ -8,35 +8,50 @@ use futures::StreamExt; use std::io::Write; use std::path::Path; -pub struct Kling16Args<'a, P: AsRef> { +pub struct Kling16ProArgs<'a, P: AsRef> { pub image_path: P, pub prompt: &'a str, pub api_key: &'a FalApiKey, - pub duration: Kling16Duration, + pub duration: Kling16ProDuration, + pub aspect_ratio: Kling16ProAspectRatio, } #[derive(Copy, Clone, Debug)] -pub enum Kling16Duration { +pub enum Kling16ProDuration { Default, FiveSeconds, TenSeconds, } -pub async fn enqueue_kling_16_image_to_video>(args: Kling16Args<'_, P>) -> Result { +#[derive(Copy, Clone, Debug)] +pub enum Kling16ProAspectRatio { + Square, // 1:1 + WideSixteenNine, // 16:9 + TallNineSixteen, // 9:16 +} + +pub async fn enqueue_kling_16_pro_image_to_video>(args: Kling16ProArgs<'_, P>) -> Result { let image_url = file_to_base64_url(args.image_path)?; let duration = match args.duration{ - Kling16Duration::Default => None, - Kling16Duration::FiveSeconds => Some("5".to_string()), // Gross... - Kling16Duration::TenSeconds => Some("10".to_string()), + Kling16ProDuration::Default => None, + Kling16ProDuration::FiveSeconds => Some("5".to_string()), // Gross... + Kling16ProDuration::TenSeconds => Some("10".to_string()), + }; + + let aspect_ratio = match args.aspect_ratio { + Kling16ProAspectRatio::Square => Some("1:1".to_string()), + Kling16ProAspectRatio::WideSixteenNine => Some("16:9".to_string()), + Kling16ProAspectRatio::TallNineSixteen => Some("9:16".to_string()), }; let request = ProImageToVideoRequest { image_url, prompt: args.prompt.to_string(), - aspect_ratio: None, - cfg_scale: None, + aspect_ratio, duration, + // Maybe expose these later + cfg_scale: None, negative_prompt: None, tail_image_url: None, }; @@ -57,7 +72,7 @@ pub async fn enqueue_kling_16_image_to_video>(args: Kling16Args<' #[cfg(test)] mod tests { use crate::creds::fal_api_key::FalApiKey; - use crate::requests::queue::video_gen::enqueue_kling_16_image_to_video::{enqueue_kling_16_image_to_video, Kling16Args, Kling16Duration}; + use crate::requests::queue::video_gen::enqueue_kling_16_pro_image_to_video::{enqueue_kling_16_pro_image_to_video, Kling16ProArgs, Kling16ProAspectRatio, Kling16ProDuration}; use errors::AnyhowResult; use std::fs::read_to_string; use testing::test_file_path::test_file_path; @@ -72,14 +87,15 @@ mod tests { let api_key = FalApiKey::from_str(&secret); - let args = Kling16Args { + let args = Kling16ProArgs { image_path: image, prompt: "a corgi looks out over the water", api_key: &api_key, - duration: Kling16Duration::Default, + duration: Kling16ProDuration::Default, + aspect_ratio: Kling16ProAspectRatio::Square, }; - let result = enqueue_kling_16_image_to_video(args).await?; + let result = enqueue_kling_16_pro_image_to_video(args).await?; Ok(()) } diff --git a/crates/lib/api_clients/fal_client/src/requests/queue/video_gen/mod.rs b/crates/lib/api_clients/fal_client/src/requests/queue/video_gen/mod.rs index 7776327a79..228901495d 100644 --- a/crates/lib/api_clients/fal_client/src/requests/queue/video_gen/mod.rs +++ b/crates/lib/api_clients/fal_client/src/requests/queue/video_gen/mod.rs @@ -1,2 +1,2 @@ -pub mod enqueue_kling_16_image_to_video; +pub mod enqueue_kling_16_pro_image_to_video; pub mod enqueue_minimax_01_image_to_video; \ No newline at end of file diff --git a/crates/lib/api_clients/fal_client/src/requests/webhook/video/enqueue_kling_16_image_to_video_webhook.rs b/crates/lib/api_clients/fal_client/src/requests/webhook/video/enqueue_kling_16_pro_image_to_video_webhook.rs similarity index 76% rename from crates/lib/api_clients/fal_client/src/requests/webhook/video/enqueue_kling_16_image_to_video_webhook.rs rename to crates/lib/api_clients/fal_client/src/requests/webhook/video/enqueue_kling_16_pro_image_to_video_webhook.rs index 345c12c5da..9e6f9a72a3 100644 --- a/crates/lib/api_clients/fal_client/src/requests/webhook/video/enqueue_kling_16_image_to_video_webhook.rs +++ b/crates/lib/api_clients/fal_client/src/requests/webhook/video/enqueue_kling_16_pro_image_to_video_webhook.rs @@ -5,12 +5,13 @@ use fal::endpoints::fal_ai::kling_video::v1_6::pro::image_to_video::{image_to_vi use fal::webhook::WebhookResponse; use reqwest::IntoUrl; -pub struct Kling16Args<'a, U: IntoUrl, V: IntoUrl> { +pub struct Kling16ProArgs<'a, U: IntoUrl, V: IntoUrl> { pub image_url: U, pub webhook_url: V, pub prompt: &'a str, pub api_key: &'a FalApiKey, pub duration: Kling16Duration, + pub aspect_ratio: Kling16ProAspectRatio, } #[derive(Copy, Clone, Debug)] @@ -20,8 +21,15 @@ pub enum Kling16Duration { TenSeconds, } -pub async fn enqueue_kling_16_image_to_video_webhook( - args: Kling16Args<'_, U, V> +#[derive(Copy, Clone, Debug)] +pub enum Kling16ProAspectRatio { + Square, // 1:1 + WideSixteenNine, // 16:9 + TallNineSixteen, // 9:16 +} + +pub async fn enqueue_kling_16_pro_image_to_video_webhook( + args: Kling16ProArgs<'_, U, V> ) -> Result { let duration = match args.duration { Kling16Duration::Default => None, @@ -29,14 +37,21 @@ pub async fn enqueue_kling_16_image_to_video_webhook( Kling16Duration::TenSeconds => Some("10".to_string()), }; + let aspect_ratio = match args.aspect_ratio { + Kling16ProAspectRatio::Square => Some("1:1".to_string()), + Kling16ProAspectRatio::WideSixteenNine => Some("16:9".to_string()), + Kling16ProAspectRatio::TallNineSixteen => Some("9:16".to_string()), + }; + let image_url = args.image_url.as_str().to_string(); let request = ProImageToVideoRequest { image_url, prompt: args.prompt.to_string(), - aspect_ratio: None, - cfg_scale: None, + aspect_ratio, duration, + // Maybe expose these later + cfg_scale: None, negative_prompt: None, tail_image_url: None, }; diff --git a/crates/lib/api_clients/fal_client/src/requests/webhook/video/mod.rs b/crates/lib/api_clients/fal_client/src/requests/webhook/video/mod.rs index 74dead225d..84cf24c510 100644 --- a/crates/lib/api_clients/fal_client/src/requests/webhook/video/mod.rs +++ b/crates/lib/api_clients/fal_client/src/requests/webhook/video/mod.rs @@ -1 +1 @@ -pub mod enqueue_kling_16_image_to_video_webhook; \ No newline at end of file +pub mod enqueue_kling_16_pro_image_to_video_webhook; \ No newline at end of file diff --git a/crates/lib/api_clients/storyteller_client/src/generate/video/generate_kling16_image_to_video.rs b/crates/lib/api_clients/storyteller_client/src/generate/video/generate_kling_16_pro_image_to_video.rs similarity index 80% rename from crates/lib/api_clients/storyteller_client/src/generate/video/generate_kling16_image_to_video.rs rename to crates/lib/api_clients/storyteller_client/src/generate/video/generate_kling_16_pro_image_to_video.rs index 33b0c7bd08..c3164adf65 100644 --- a/crates/lib/api_clients/storyteller_client/src/generate/video/generate_kling16_image_to_video.rs +++ b/crates/lib/api_clients/storyteller_client/src/generate/video/generate_kling_16_pro_image_to_video.rs @@ -5,15 +5,15 @@ use crate::error::storyteller_error::StorytellerError; use crate::utils::api_host::ApiHost; use crate::utils::constants::{APPLICATION_JSON, USER_AGENT}; use crate::utils::filter_bad_response::filter_bad_response; -use artcraft_api_defs::generate::video::generate_kling_1_6_image_to_video::{GenerateKling16ImageToVideoRequest, GenerateKling16ImageToVideoResponse, GENERATE_KLING_1_6_IMAGE_TO_VIDEO_URL_PATH}; +use artcraft_api_defs::generate::video::generate_kling_1_6_pro_image_to_video::{GenerateKling16ProImageToVideoRequest, GenerateKling16ProImageToVideoResponse, GENERATE_KLING_1_6_PRO_IMAGE_TO_VIDEO_URL_PATH}; use log::{debug, info}; use reqwest::Client; -pub async fn generate_kling16_image_to_video( +pub async fn generate_kling_16_pro_image_to_video( api_host: &ApiHost, maybe_creds: Option<&StorytellerCredentialSet>, - request: GenerateKling16ImageToVideoRequest, -) -> Result { + request: GenerateKling16ProImageToVideoRequest, +) -> Result { let url = get_route(api_host); @@ -64,5 +64,5 @@ pub async fn generate_kling16_image_to_video( fn get_route(api_host: &ApiHost) -> String { let api_hostname = api_host.to_api_hostname(); - format!("https://{}{}", api_hostname, GENERATE_KLING_1_6_IMAGE_TO_VIDEO_URL_PATH) + format!("https://{}{}", api_hostname, GENERATE_KLING_1_6_PRO_IMAGE_TO_VIDEO_URL_PATH) } diff --git a/crates/lib/api_clients/storyteller_client/src/generate/video/mod.rs b/crates/lib/api_clients/storyteller_client/src/generate/video/mod.rs index 66ebbedd46..f2afa94ca9 100644 --- a/crates/lib/api_clients/storyteller_client/src/generate/video/mod.rs +++ b/crates/lib/api_clients/storyteller_client/src/generate/video/mod.rs @@ -1 +1 @@ -pub mod generate_kling16_image_to_video; \ No newline at end of file +pub mod generate_kling_16_pro_image_to_video; \ No newline at end of file diff --git a/crates/schema/public/api/artcraft_api_defs/src/generate/video/generate_kling_1_6_image_to_video.rs b/crates/schema/public/api/artcraft_api_defs/src/generate/video/generate_kling_1_6_pro_image_to_video.rs similarity index 53% rename from crates/schema/public/api/artcraft_api_defs/src/generate/video/generate_kling_1_6_image_to_video.rs rename to crates/schema/public/api/artcraft_api_defs/src/generate/video/generate_kling_1_6_pro_image_to_video.rs index 75eb6193da..2a03c28862 100644 --- a/crates/schema/public/api/artcraft_api_defs/src/generate/video/generate_kling_1_6_image_to_video.rs +++ b/crates/schema/public/api/artcraft_api_defs/src/generate/video/generate_kling_1_6_pro_image_to_video.rs @@ -3,10 +3,10 @@ use tokens::tokens::generic_inference_jobs::InferenceJobToken; use tokens::tokens::media_files::MediaFileToken; use utoipa::ToSchema; -pub const GENERATE_KLING_1_6_IMAGE_TO_VIDEO_URL_PATH: &str = "/v1/generate/video/kling_16_image_to_video"; +pub const GENERATE_KLING_1_6_PRO_IMAGE_TO_VIDEO_URL_PATH: &str = "/v1/generate/video/kling_1.6_pro_image_to_video"; #[derive(Serialize, Deserialize, ToSchema)] -pub struct GenerateKling16ImageToVideoRequest { +pub struct GenerateKling16ProImageToVideoRequest { /// Idempotency token to prevent duplicate requests. pub uuid_idempotency_token: String, @@ -16,10 +16,23 @@ pub struct GenerateKling16ImageToVideoRequest { /// Optional text prompt. pub prompt: Option, + + /// Optional: apsect ratio of the generated video. + pub aspect_ratio: Option, } #[derive(Serialize, Deserialize, ToSchema)] -pub struct GenerateKling16ImageToVideoResponse { +pub enum GenerateKling16ProAspectRatio { + /// 16:9 aspect ratio + WideSixteenNine, + /// 9:16 aspect ratio + TallNineSixteen, + /// 1:1 aspect ratio + Square, +} + +#[derive(Serialize, Deserialize, ToSchema)] +pub struct GenerateKling16ProImageToVideoResponse { pub success: bool, pub inference_job_token: InferenceJobToken, } diff --git a/crates/schema/public/api/artcraft_api_defs/src/generate/video/mod.rs b/crates/schema/public/api/artcraft_api_defs/src/generate/video/mod.rs index 2c1da8e82a..5a1956a8f5 100644 --- a/crates/schema/public/api/artcraft_api_defs/src/generate/video/mod.rs +++ b/crates/schema/public/api/artcraft_api_defs/src/generate/video/mod.rs @@ -1 +1 @@ -pub mod generate_kling_1_6_image_to_video; \ No newline at end of file +pub mod generate_kling_1_6_pro_image_to_video; \ No newline at end of file diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/generate_kling_1_6_video_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/generate_kling_1_6_pro_video_handler.rs similarity index 83% rename from crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/generate_kling_1_6_video_handler.rs rename to crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/generate_kling_1_6_pro_video_handler.rs index 50919dba97..5fb024db90 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/generate_kling_1_6_video_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/generate_kling_1_6_pro_video_handler.rs @@ -15,13 +15,14 @@ use actix_web::http::StatusCode; use actix_web::web::Json; use actix_web::web::Path; use actix_web::{web, HttpRequest, HttpResponse}; -use artcraft_api_defs::generate::video::generate_kling_1_6_image_to_video::GenerateKling16ImageToVideoRequest; -use artcraft_api_defs::generate::video::generate_kling_1_6_image_to_video::GenerateKling16ImageToVideoResponse; +use artcraft_api_defs::generate::video::generate_kling_1_6_pro_image_to_video::GenerateKling16ProImageToVideoResponse; +use artcraft_api_defs::generate::video::generate_kling_1_6_pro_image_to_video::{GenerateKling16ProAspectRatio, GenerateKling16ProImageToVideoRequest}; use bucket_paths::legacy::typified_paths::public::media_files::bucket_file_path::MediaFileBucketPath; use enums::common::visibility::Visibility; -use fal_client::requests::webhook::video::enqueue_kling_16_image_to_video_webhook::enqueue_kling_16_image_to_video_webhook; -use fal_client::requests::webhook::video::enqueue_kling_16_image_to_video_webhook::Kling16Args; -use fal_client::requests::webhook::video::enqueue_kling_16_image_to_video_webhook::Kling16Duration; +use fal_client::requests::webhook::video::enqueue_kling_16_pro_image_to_video_webhook::enqueue_kling_16_pro_image_to_video_webhook; +use fal_client::requests::webhook::video::enqueue_kling_16_pro_image_to_video_webhook::Kling16Duration; +use fal_client::requests::webhook::video::enqueue_kling_16_pro_image_to_video_webhook::Kling16ProArgs; +use fal_client::requests::webhook::video::enqueue_kling_16_pro_image_to_video_webhook::Kling16ProAspectRatio; use http_server_common::request::get_request_ip::get_request_ip; use http_server_common::response::serialize_as_json_error::serialize_as_json_error; use idempotency::uuid::generate_random_uuid; @@ -96,7 +97,7 @@ impl fmt::Display for GenerateKling16VideoError { #[utoipa::path( post, tag = "Generate Videos", - path = "/v1/generate/video/kling_16_image_to_video", + path = "/v1/generate/video/kling_1.6_pro_image_to_video", responses( (status = 200, description = "Success", body = RemoveImageBackgroundResponse), (status = 400, description = "Bad input", body = RemoveImageBackgroundError), @@ -107,11 +108,11 @@ impl fmt::Display for GenerateKling16VideoError { ("request" = RemoveImageBackgroundRequest, description = "Payload for Request"), ) )] -pub async fn generate_kling_1_6_video_handler( +pub async fn generate_kling_1_6_pro_video_handler( http_request: HttpRequest, - request: Json, + request: Json, server_state: web::Data> -) -> Result, GenerateKling16VideoError> { +) -> Result, GenerateKling16VideoError> { let maybe_user_session = server_state .session_checker .maybe_get_user_session(&http_request, &server_state.mysql_pool) @@ -196,15 +197,23 @@ pub async fn generate_kling_1_6_video_handler( .map(|prompt| prompt.trim()) .unwrap_or_else(|| ""); - let args = Kling16Args { + let aspect_ratio = match &request.aspect_ratio { + Some(GenerateKling16ProAspectRatio::Square) => Kling16ProAspectRatio::Square, + Some(GenerateKling16ProAspectRatio::WideSixteenNine) => Kling16ProAspectRatio::WideSixteenNine, + Some(GenerateKling16ProAspectRatio::TallNineSixteen) => Kling16ProAspectRatio::TallNineSixteen, + None => Kling16ProAspectRatio::WideSixteenNine, // Default to 16:9 + }; + + let args = Kling16ProArgs { image_url: media_links.cdn_url, webhook_url: &server_state.fal.webhook_url, duration: Kling16Duration::Default, prompt: prompt, + aspect_ratio: aspect_ratio, api_key: &server_state.fal.api_key, }; - let fal_result = enqueue_kling_16_image_to_video_webhook(args) + let fal_result = enqueue_kling_16_pro_image_to_video_webhook(args) .await .map_err(|err| { warn!("Error calling remove_background_rembg_webhook: {:?}", err); @@ -241,7 +250,7 @@ pub async fn generate_kling_1_6_video_handler( } }; - Ok(Json(GenerateKling16ImageToVideoResponse { + Ok(Json(GenerateKling16ProImageToVideoResponse { success: true, inference_job_token: job_token, })) diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/mod.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/mod.rs index 272055b52e..d7a0e16804 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/mod.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/mod.rs @@ -1 +1 @@ -pub mod generate_kling_1_6_video_handler; \ No newline at end of file +pub mod generate_kling_1_6_pro_video_handler; \ No newline at end of file diff --git a/crates/service/web/storyteller_web/src/http_server/routes/add_generate_routes.rs b/crates/service/web/storyteller_web/src/http_server/routes/add_generate_routes.rs index 0b3fbeb002..4ab6f6bbcc 100644 --- a/crates/service/web/storyteller_web/src/http_server/routes/add_generate_routes.rs +++ b/crates/service/web/storyteller_web/src/http_server/routes/add_generate_routes.rs @@ -1,7 +1,7 @@ use crate::http_server::endpoints::generate::image::generate_flux_pro_ultra_text_to_image_handler::generate_flux_pro_11_ultra_text_to_image_handler; use crate::http_server::endpoints::generate::image::remove_image_background_handler::remove_image_background_handler; use crate::http_server::endpoints::generate::object::generate_hunyuan2_image_to_3d_handler::generate_hunyuan_2_image_to_3d_handler; -use crate::http_server::endpoints::generate::video::generate_kling_1_6_video_handler::generate_kling_1_6_video_handler; +use crate::http_server::endpoints::generate::video::generate_kling_1_6_pro_video_handler::generate_kling_1_6_pro_video_handler; use actix_http::body::MessageBody; use actix_service::ServiceFactory; use actix_web::dev::{ServiceRequest, ServiceResponse}; @@ -30,8 +30,8 @@ where ) ) .service(web::scope("/video") - .service(web::resource("/kling_16_image_to_video") - .route(web::post().to(generate_kling_1_6_video_handler)) + .service(web::resource("/kling_1.6_pro_image_to_video") + .route(web::post().to(generate_kling_1_6_pro_video_handler)) .route(web::head().to(|| HttpResponse::Ok())) ) )