From 97c48c79fb2dcb6d97e2d08ad3ca93fd600b9ce5 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Wed, 3 Dec 2025 17:50:31 -0500 Subject: [PATCH] kling 2.6 --- ...e_kling_v2p6_pro_image_to_video_webhook.rs | 87 +++++++++++++++ .../src/requests/webhook/video/image/mod.rs | 3 +- ...ue_kling_v2p6_pro_text_to_video_webhook.rs | 103 ++++++++++++++++++ .../src/requests/webhook/video/text/mod.rs | 3 +- .../src/endpoints/fal_ai/kling_video/mod.rs | 14 +++ .../v2_6/kling_v2p6_pro_image_to_video.rs | 39 +++++++ .../v2_6/kling_v2p6_pro_text_to_video.rs | 46 ++++++++ .../endpoints/fal_ai/kling_video/v2_6/mod.rs | 2 + 8 files changed, 295 insertions(+), 2 deletions(-) create mode 100644 crates/api_clients/fal_client/src/requests/webhook/video/image/enqueue_kling_v2p6_pro_image_to_video_webhook.rs create mode 100644 crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_v2p6_pro_text_to_video_webhook.rs create mode 100644 crates/vendor/fal-rs/src/endpoints/fal_ai/kling_video/v2_6/kling_v2p6_pro_image_to_video.rs create mode 100644 crates/vendor/fal-rs/src/endpoints/fal_ai/kling_video/v2_6/kling_v2p6_pro_text_to_video.rs create mode 100644 crates/vendor/fal-rs/src/endpoints/fal_ai/kling_video/v2_6/mod.rs diff --git a/crates/api_clients/fal_client/src/requests/webhook/video/image/enqueue_kling_v2p6_pro_image_to_video_webhook.rs b/crates/api_clients/fal_client/src/requests/webhook/video/image/enqueue_kling_v2p6_pro_image_to_video_webhook.rs new file mode 100644 index 0000000000..7d8c3413b8 --- /dev/null +++ b/crates/api_clients/fal_client/src/requests/webhook/video/image/enqueue_kling_v2p6_pro_image_to_video_webhook.rs @@ -0,0 +1,87 @@ +use crate::creds::fal_api_key::FalApiKey; +use crate::error::classify_fal_error::classify_fal_error; +use crate::error::fal_error_plus::FalErrorPlus; +use fal::endpoints::fal_ai::kling_video::v2_6::kling_v2p6_pro_image_to_video::{kling_v2p6_pro_image_to_video, KlingV2p6ProImageToVideoInput}; +use fal::webhook::WebhookResponse; +use reqwest::IntoUrl; + +pub struct EnqueueKlingV2p6ProImageToVideoArgs<'a, R: IntoUrl> { + // Request required + pub prompt: String, + pub image_url: String, + + // Optional args + pub generate_audio: Option, + pub negative_prompt: Option, + pub duration: Option, + + // Fulfillment + pub webhook_url: R, + pub api_key: &'a FalApiKey, +} + +#[derive(Copy, Clone, Debug)] +pub enum EnqueueKlingV2p6ProImageToVideoDurationSeconds { + Five, + Ten, +} + +pub async fn enqueue_kling_v2p6_pro_image_to_video_webhook( + args: EnqueueKlingV2p6ProImageToVideoArgs<'_, R> +) -> Result { + + let duration = args.duration + .map(|resolution| match resolution { + EnqueueKlingV2p6ProImageToVideoDurationSeconds::Five => "5", + EnqueueKlingV2p6ProImageToVideoDurationSeconds::Ten => "10", + }) + .map(|resolution| resolution.to_string()); + + let request = KlingV2p6ProImageToVideoInput { + prompt: args.prompt, + image_url: args.image_url, + // Optionals + duration, + negative_prompt: args.negative_prompt, + generate_audio: args.generate_audio, + }; + + let result = kling_v2p6_pro_image_to_video(request) + .with_api_key(&args.api_key.0) + .queue_webhook(args.webhook_url) + .await; + + result.map_err(|err| classify_fal_error(err)) +} + +#[cfg(test)] +mod tests { + use crate::creds::fal_api_key::FalApiKey; + use crate::requests::webhook::video::image::enqueue_kling_v2p6_pro_image_to_video_webhook::{enqueue_kling_v2p6_pro_image_to_video_webhook, EnqueueKlingV2p6ProImageToVideoArgs, EnqueueKlingV2p6ProImageToVideoDurationSeconds}; + use errors::AnyhowResult; + use std::fs::read_to_string; + use test_data::web::image_urls::ERNEST_SCARED_STUPID_IMAGE_URL; + + #[tokio::test] + #[ignore] + async fn test() -> AnyhowResult<()> { + // XXX: Don't commit secrets! + let secret = read_to_string("/home/bt/Artcraft/credentials/fal_api_key.txt")?; + + let api_key = FalApiKey::from_str(&secret); + + let args = EnqueueKlingV2p6ProImageToVideoArgs { + image_url: ERNEST_SCARED_STUPID_IMAGE_URL.to_string(), + prompt: "the man says, 'these ghosts sure are scary!' and then runs. behind him, a group of ghosts appear from the trees and chase him. the camera tracks the action. finally, the man yells, 'go away ghosts'.".to_string(), + negative_prompt: None, + generate_audio: Some(true), + duration: Some(EnqueueKlingV2p6ProImageToVideoDurationSeconds::Ten), + api_key: &api_key, + webhook_url: "https://example.com/webhook", + }; + + let result = enqueue_kling_v2p6_pro_image_to_video_webhook(args).await?; + + Ok(()) + } +} diff --git a/crates/api_clients/fal_client/src/requests/webhook/video/image/mod.rs b/crates/api_clients/fal_client/src/requests/webhook/video/image/mod.rs index 39b1d8ea15..dd70b03c59 100644 --- a/crates/api_clients/fal_client/src/requests/webhook/video/image/mod.rs +++ b/crates/api_clients/fal_client/src/requests/webhook/video/image/mod.rs @@ -1,2 +1,3 @@ pub mod enqueue_kling_v2p5_turbo_pro_image_to_video_webhook; -pub mod enqueue_kling_v2p5_turbo_standard_image_to_video_webhook; \ No newline at end of file +pub mod enqueue_kling_v2p5_turbo_standard_image_to_video_webhook; +pub mod enqueue_kling_v2p6_pro_image_to_video_webhook; \ No newline at end of file diff --git a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_v2p6_pro_text_to_video_webhook.rs b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_v2p6_pro_text_to_video_webhook.rs new file mode 100644 index 0000000000..7089149daf --- /dev/null +++ b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_v2p6_pro_text_to_video_webhook.rs @@ -0,0 +1,103 @@ +use crate::creds::fal_api_key::FalApiKey; +use crate::error::classify_fal_error::classify_fal_error; +use crate::error::fal_error_plus::FalErrorPlus; +use fal::endpoints::fal_ai::kling_video::v2_6::kling_v2p6_pro_text_to_video::{kling_v2p6_pro_text_to_video, KlingV2p6ProTextToVideoInput}; +use fal::webhook::WebhookResponse; +use reqwest::IntoUrl; + +pub struct EnqueueKlingV2p6ProTextToVideoArgs<'a, R: IntoUrl> { + // Request required + pub prompt: String, + + // Optional args + pub generate_audio: Option, + pub negative_prompt: Option, + pub duration: Option, + pub aspect_ratio: Option, + + // Fulfillment + pub webhook_url: R, + pub api_key: &'a FalApiKey, +} + +#[derive(Copy, Clone, Debug)] +pub enum EnqueueKlingV2p6ProTextToVideoDurationSeconds { + Five, + Ten, +} + +#[derive(Copy, Clone, Debug)] +pub enum EnqueueKlingV2p6ProTextToVideoAspectRatio { + Square, + SixteenByNine, + NineBySixteen, +} + +pub async fn enqueue_kling_v2p6_pro_text_to_video_webhook( + args: EnqueueKlingV2p6ProTextToVideoArgs<'_, R> +) -> Result { + + let duration = args.duration + .map(|resolution| match resolution { + EnqueueKlingV2p6ProTextToVideoDurationSeconds::Five => "5", + EnqueueKlingV2p6ProTextToVideoDurationSeconds::Ten => "10", + }) + .map(|s| s.to_string()); + + let aspect_ratio = args.aspect_ratio + .map(|aspect| match aspect { + EnqueueKlingV2p6ProTextToVideoAspectRatio::Square => "1:1", + EnqueueKlingV2p6ProTextToVideoAspectRatio::SixteenByNine => "16:9", + EnqueueKlingV2p6ProTextToVideoAspectRatio::NineBySixteen => "9:16", + }) + .map(|s| s.to_string()); + + let request = KlingV2p6ProTextToVideoInput { + prompt: args.prompt, + // Optionals + generate_audio: args.generate_audio, + duration, + aspect_ratio, + negative_prompt: args.negative_prompt, + // Constants + cfg_scale: None, + }; + + let result = kling_v2p6_pro_text_to_video(request) + .with_api_key(&args.api_key.0) + .queue_webhook(args.webhook_url) + .await; + + result.map_err(|err| classify_fal_error(err)) +} + +#[cfg(test)] +mod tests { + use crate::creds::fal_api_key::FalApiKey; + use errors::AnyhowResult; + use std::fs::read_to_string; + use crate::requests::webhook::video::text::enqueue_kling_v2p6_pro_text_to_video_webhook::{enqueue_kling_v2p6_pro_text_to_video_webhook, EnqueueKlingV2p6ProTextToVideoArgs, EnqueueKlingV2p6ProTextToVideoAspectRatio, EnqueueKlingV2p6ProTextToVideoDurationSeconds}; + + #[tokio::test] + #[ignore] + async fn test() -> AnyhowResult<()> { + // XXX: Don't commit secrets! + let secret = read_to_string("/home/bt/Artcraft/credentials/fal_api_key.txt")?; + + let api_key = FalApiKey::from_str(&secret); + + let args = EnqueueKlingV2p6ProTextToVideoArgs { + prompt: "a humanoid lizard creature walks around on the surface of an alien planet. the sky is purple and there are yellow plants. The lizard says, 'You should consider day trading'. Suddenly a giant t-rex comes in from off screen and eats the lizard creature.".to_string(), + negative_prompt: None, + aspect_ratio: Some(EnqueueKlingV2p6ProTextToVideoAspectRatio::SixteenByNine), + duration: Some(EnqueueKlingV2p6ProTextToVideoDurationSeconds::Ten), + generate_audio: Some(true), + api_key: &api_key, + webhook_url: "https://example.com/webhook", + }; + + let result = enqueue_kling_v2p6_pro_text_to_video_webhook(args).await?; + + Ok(()) + } +} diff --git a/crates/api_clients/fal_client/src/requests/webhook/video/text/mod.rs b/crates/api_clients/fal_client/src/requests/webhook/video/text/mod.rs index 07dbce240b..457b4e2f3f 100644 --- a/crates/api_clients/fal_client/src/requests/webhook/video/text/mod.rs +++ b/crates/api_clients/fal_client/src/requests/webhook/video/text/mod.rs @@ -1 +1,2 @@ -pub mod enqueue_kling_v2p5_turbo_pro_text_to_video_webhook; \ No newline at end of file +pub mod enqueue_kling_v2p5_turbo_pro_text_to_video_webhook; +pub mod enqueue_kling_v2p6_pro_text_to_video_webhook; \ No newline at end of file diff --git a/crates/vendor/fal-rs/src/endpoints/fal_ai/kling_video/mod.rs b/crates/vendor/fal-rs/src/endpoints/fal_ai/kling_video/mod.rs index 1df3cb90c4..df04d9cb04 100644 --- a/crates/vendor/fal-rs/src/endpoints/fal_ai/kling_video/mod.rs +++ b/crates/vendor/fal-rs/src/endpoints/fal_ai/kling_video/mod.rs @@ -68,3 +68,17 @@ pub mod v2_1; ))) )] pub mod v2_5; +#[cfg(any( + feature = "endpoints", + feature = "endpoints_fal-ai", + feature = "endpoints_fal-ai_kling-video" +))] +#[cfg_attr( + docsrs, + doc(cfg(any( + feature = "endpoints", + feature = "endpoints_fal-ai", + feature = "endpoints_fal-ai_kling-video" + ))) +)] +pub mod v2_6; diff --git a/crates/vendor/fal-rs/src/endpoints/fal_ai/kling_video/v2_6/kling_v2p6_pro_image_to_video.rs b/crates/vendor/fal-rs/src/endpoints/fal_ai/kling_video/v2_6/kling_v2p6_pro_image_to_video.rs new file mode 100644 index 0000000000..be86b18aad --- /dev/null +++ b/crates/vendor/fal-rs/src/endpoints/fal_ai/kling_video/v2_6/kling_v2p6_pro_image_to_video.rs @@ -0,0 +1,39 @@ +use crate::prelude::{Deserialize, FalRequest, Serialize}; + +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct KlingV2p6ProImageToVideoInput { + pub prompt: String, + + /// Starting frame + pub image_url: String, + + /// Generate audio + #[serde(skip_serializing_if = "Option::is_none")] + pub generate_audio: Option, + + /// Optional negative prompt + #[serde(skip_serializing_if = "Option::is_none")] + pub negative_prompt: Option, + + /// Duration in seconds + /// Options: "5", "10" + #[serde(skip_serializing_if = "Option::is_none")] + pub duration: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct KlingV2p6ProImageToVideoOutput { + pub video: VideoFile, +} + +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct VideoFile { + /// The URL where the file can be downloaded from. + pub url: String, +} + +pub fn kling_v2p6_pro_image_to_video( + params: KlingV2p6ProImageToVideoInput, +) -> FalRequest { + FalRequest::new("fal-ai/kling-video/v2.6/pro/image-to-video", params) +} diff --git a/crates/vendor/fal-rs/src/endpoints/fal_ai/kling_video/v2_6/kling_v2p6_pro_text_to_video.rs b/crates/vendor/fal-rs/src/endpoints/fal_ai/kling_video/v2_6/kling_v2p6_pro_text_to_video.rs new file mode 100644 index 0000000000..5649bca3f9 --- /dev/null +++ b/crates/vendor/fal-rs/src/endpoints/fal_ai/kling_video/v2_6/kling_v2p6_pro_text_to_video.rs @@ -0,0 +1,46 @@ +use crate::prelude::{Deserialize, FalRequest, Serialize}; + +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct KlingV2p6ProTextToVideoInput { + pub prompt: String, + + /// Aspect ratio + /// Possible enum values: "16:9", "9:16", "1:1" + pub aspect_ratio: Option, + + /// Generate audio + #[serde(skip_serializing_if = "Option::is_none")] + pub generate_audio: Option, + + /// Optional negative prompt + #[serde(skip_serializing_if = "Option::is_none")] + pub negative_prompt: Option, + + /// Duration in seconds + /// Options: "5", "10" + #[serde(skip_serializing_if = "Option::is_none")] + pub duration: Option, + + /// The CFG (Classifier Free Guidance) scale is a measure of how close you want the model to + /// stick to your prompt. + /// Default value: 0.5 + #[serde(skip_serializing_if = "Option::is_none")] + pub cfg_scale: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct KlingV2p6ProTextToVideoOutput { + pub video: VideoFile, +} + +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct VideoFile { + /// The URL where the file can be downloaded from. + pub url: String, +} + +pub fn kling_v2p6_pro_text_to_video( + params: KlingV2p6ProTextToVideoInput, +) -> FalRequest { + FalRequest::new("fal-ai/kling-video/v2.6/pro/text-to-video", params) +} diff --git a/crates/vendor/fal-rs/src/endpoints/fal_ai/kling_video/v2_6/mod.rs b/crates/vendor/fal-rs/src/endpoints/fal_ai/kling_video/v2_6/mod.rs new file mode 100644 index 0000000000..6b45e041e4 --- /dev/null +++ b/crates/vendor/fal-rs/src/endpoints/fal_ai/kling_video/v2_6/mod.rs @@ -0,0 +1,2 @@ +pub mod kling_v2p6_pro_image_to_video; +pub mod kling_v2p6_pro_text_to_video; \ No newline at end of file