kling 2.6

This commit is contained in:
Brandon Thomas committed 2025-12-03 17:50:31 -05:00
1 parent 74f0c3a40f
commit 97c48c79fb
8 files changed
+295 -2

No files matched your search

@@ -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<bool>,
pub negative_prompt: Option<String>,
pub duration: Option<EnqueueKlingV2p6ProImageToVideoDurationSeconds>,
// 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<R: IntoUrl>(
args: EnqueueKlingV2p6ProImageToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
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(())
}
}
@@ -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;
pub mod enqueue_kling_v2p5_turbo_standard_image_to_video_webhook;
pub mod enqueue_kling_v2p6_pro_image_to_video_webhook;
@@ -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<bool>,
pub negative_prompt: Option<String>,
pub duration: Option<EnqueueKlingV2p6ProTextToVideoDurationSeconds>,
pub aspect_ratio: Option<EnqueueKlingV2p6ProTextToVideoAspectRatio>,
// 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<R: IntoUrl>(
args: EnqueueKlingV2p6ProTextToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
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(())
}
}
@@ -1 +1,2 @@
pub mod enqueue_kling_v2p5_turbo_pro_text_to_video_webhook;
pub mod enqueue_kling_v2p5_turbo_pro_text_to_video_webhook;
pub mod enqueue_kling_v2p6_pro_text_to_video_webhook;
@@ -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;
@@ -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<bool>,
/// Optional negative prompt
#[serde(skip_serializing_if = "Option::is_none")]
pub negative_prompt: Option<String>,
/// Duration in seconds
/// Options: "5", "10"
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<String>,
}
#[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<KlingV2p6ProImageToVideoInput, KlingV2p6ProImageToVideoOutput> {
FalRequest::new("fal-ai/kling-video/v2.6/pro/image-to-video", params)
}
@@ -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<String>,
/// Generate audio
#[serde(skip_serializing_if = "Option::is_none")]
pub generate_audio: Option<bool>,
/// Optional negative prompt
#[serde(skip_serializing_if = "Option::is_none")]
pub negative_prompt: Option<String>,
/// Duration in seconds
/// Options: "5", "10"
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<String>,
/// 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<f32>,
}
#[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<KlingV2p6ProTextToVideoInput, KlingV2p6ProTextToVideoOutput> {
FalRequest::new("fal-ai/kling-video/v2.6/pro/text-to-video", params)
}
@@ -0,0 +1,2 @@
pub mod kling_v2p6_pro_image_to_video;
pub mod kling_v2p6_pro_text_to_video;