Compare commits

...
Author SHA1 Message Date
Brandon Thomas 6903b1dba0 veo 3.1 text to video 2025-12-04 16:07:33 -05:00
Brandon Thomas e60d8f8a13 image to video fast 2025-12-04 15:58:09 -05:00
Brandon Thomas 0dd9e81b25 image to video 2025-12-04 15:48:38 -05:00
Brandon Thomas 26126d4985 fast 2025-12-04 15:42:55 -05:00
Brandon Thomas 67580c3ab9 veo 3.1 wrapper 2025-12-04 15:34:59 -05:00
Brandon Thomas 44167c9926 hailuo models - fal wrapper 2025-12-04 15:18:43 -05:00
Brandon Thomas 8661e983af sora 2 text to video fal wrapper 2025-12-04 13:33:53 -05:00
Brandon Thomas 99fbebdb2a sora2 i2v fal wrapper 2025-12-04 13:24:34 -05:00
Brandon Thomas e8ff0c1e28 seedream 4.5 fal wrapper 2025-12-04 12:57:30 -05:00
Brandon Thomas 32cda55005 hailuo 2.3 pro 2025-12-04 12:30:39 -05:00
Brandon Thomas c6b8267873 seedream 4.5 2025-12-04 12:09:13 -05:00
Brandon Thomas 46a3f0b29f typo 2025-12-03 21:25:15 -05:00
Brandon Thomas 88a183b6ce sora 2 text to video 2025-12-03 21:24:54 -05:00
Brandon Thomas c02bbbf30a sora 2 i2v 2025-12-03 21:09:22 -05:00
Brandon Thomas b6ef07dbb4 sora 2 pro i2v 2025-12-03 20:55:41 -05:00
Brandon Thomas 4c823d8f2a veo 3.1 fast 2025-12-03 20:33:08 -05:00
Brandon Thomas cf59f03465 veo 3.1 text to video 2025-12-03 20:23:59 -05:00
Brandon Thomas a8d1a30547 veo 3.1 first frame 2025-12-03 20:18:28 -05:00
Brandon Thomas 508b3c9d4e fal.rs veo 3.1 first/last frame 2025-12-03 20:06:59 -05:00
Brandon Thomas c73a4470e7 pixverse v5 2025-12-03 18:50:57 -05:00
Brandon Thomas 97c48c79fb kling 2.6 2025-12-03 17:50:31 -05:00
Brandon Thomas 74f0c3a40f rest of kling 2.5 2025-12-03 17:20:07 -05:00
Brandon Thomas ec6b930005 kling 2.5 turbo pro i2v 2025-12-03 17:08:32 -05:00
Brandon Thomas f975fccef0 wip 2025-12-03 15:51:49 -05:00
Brandon Thomas a2855f423b kling 2.5 2025-12-02 22:14:09 -05:00
Brandon Thomas eba50a71a4 refactor 2025-12-02 19:46:57 -05:00
Brandon Thomas 9d35468329 fal wrapper seedream v4 + tests 2025-12-02 19:09:15 -05:00
Brandon Thomas 3bb0e7d2eb bytedance seedream v4 fal.rs 2025-12-02 17:56:03 -05:00
Brandon Thomas 69cc2db080 add fal wrapper nb integrations 2025-12-02 14:57:00 -05:00
Brandon Thomas bbb62bb1a8 fal.rs nanobanana wrappers 2025-12-02 14:20:10 -05:00
Brandon Thomas 736ac055cc grok generation modes 2025-12-02 14:10:49 -05:00
84 changed files with 4606 additions and 7 deletions
@@ -0,0 +1,143 @@
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::bytedance::seedream::bytedance_seedream_v4_edit_image::{bytedance_seedream_v4_edit_image, BytedanceSeedreamV4EditImageInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueBytedanceSeedreamV4EditImageArgs<'a, R: IntoUrl> {
// Request required
pub prompt: &'a str,
pub image_urls: Vec<String>,
// Optional args
pub num_images: Option<EnqueueBytedanceSeedreamV4EditImageNumImages>,
pub max_images: Option<EnqueueBytedanceSeedreamV4EditImageMaxImages>,
pub image_size: Option<EnqueueBytedanceSeedreamV4EditImageSize>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4EditImageNumImages {
One,
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4EditImageMaxImages {
One,
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4EditImageSize {
// Square
Square,
SquareHd,
// Tall
PortraitFourThree,
PortraitSixteenNine,
// Wide
LandscapeFourThree,
LandscapeSixteenNine,
// Auto
Auto,
Auto2k,
Auto4k,
}
pub async fn enqueue_bytedance_seedream_v4_edit_image_webhook<R: IntoUrl>(
args: EnqueueBytedanceSeedreamV4EditImageArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let num_images = args.num_images
.map(|num_images| match num_images {
EnqueueBytedanceSeedreamV4EditImageNumImages::One => 1,
EnqueueBytedanceSeedreamV4EditImageNumImages::Two => 2,
EnqueueBytedanceSeedreamV4EditImageNumImages::Three => 3,
EnqueueBytedanceSeedreamV4EditImageNumImages::Four => 4,
});
let max_images = args.max_images
.map(|num_images| match num_images {
EnqueueBytedanceSeedreamV4EditImageMaxImages::One => 1,
EnqueueBytedanceSeedreamV4EditImageMaxImages::Two => 2,
EnqueueBytedanceSeedreamV4EditImageMaxImages::Three => 3,
EnqueueBytedanceSeedreamV4EditImageMaxImages::Four => 4,
});
let image_size = args.image_size
.map(|image_size| match image_size {
EnqueueBytedanceSeedreamV4EditImageSize::Square => "square",
EnqueueBytedanceSeedreamV4EditImageSize::SquareHd => "square_hd",
EnqueueBytedanceSeedreamV4EditImageSize::PortraitFourThree => "portrait_4_3",
EnqueueBytedanceSeedreamV4EditImageSize::PortraitSixteenNine => "portrait_16_9",
EnqueueBytedanceSeedreamV4EditImageSize::LandscapeFourThree => "landscape_4_3",
EnqueueBytedanceSeedreamV4EditImageSize::LandscapeSixteenNine => "landscape_16_9",
EnqueueBytedanceSeedreamV4EditImageSize::Auto => "auto",
EnqueueBytedanceSeedreamV4EditImageSize::Auto2k => "auto_2K",
EnqueueBytedanceSeedreamV4EditImageSize::Auto4k => "auto_4K",
})
.map(|resolution| resolution.to_string());
let request = BytedanceSeedreamV4EditImageInput {
prompt: args.prompt.to_string(),
image_urls: args.image_urls,
// Optionals
num_images,
max_images,
image_size,
// Constants
enhance_prompt_mode: Some("standard".to_string()),
enable_safety_checker: Some(false),
};
let result = bytedance_seedream_v4_edit_image(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::image::edit::enqueue_bytedance_seedream_v4_edit_image_webhook::{enqueue_bytedance_seedream_v4_edit_image_webhook, EnqueueBytedanceSeedreamV4EditImageArgs, EnqueueBytedanceSeedreamV4EditImageMaxImages, EnqueueBytedanceSeedreamV4EditImageNumImages, EnqueueBytedanceSeedreamV4EditImageSize};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::{GHOST_IMAGE_URL, TREX_SKELETON_IMAGE_URL};
#[tokio::test]
#[ignore]
async fn test() -> AnyhowResult<()> {
// XXX: Don't commit secrets!
let secret = read_to_string("/Users/bt/Artcraft/credentials/fal_api_key.txt")?;
let api_key = FalApiKey::from_str(&secret);
let args = EnqueueBytedanceSeedreamV4EditImageArgs {
image_urls: vec![
GHOST_IMAGE_URL.to_string(),
TREX_SKELETON_IMAGE_URL.to_string(),
],
prompt: "add the ghost to the image of the t-rex skeleton, make it look spooky but friendly",
num_images: Some(EnqueueBytedanceSeedreamV4EditImageNumImages::Two),
max_images: Some(EnqueueBytedanceSeedreamV4EditImageMaxImages::Two),
image_size: Some(EnqueueBytedanceSeedreamV4EditImageSize::Auto2k),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_bytedance_seedream_v4_edit_image_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,142 @@
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::bytedance::seedream::bytedance_seedream_v4p5_edit_image::{bytedance_seedream_v4p5_edit_image, BytedanceSeedreamV4p5EditImageInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueBytedanceSeedreamV4p5EditImageArgs<'a, R: IntoUrl> {
// Request required
pub prompt: &'a str,
pub image_urls: Vec<String>,
// Optional args
pub num_images: Option<EnqueueBytedanceSeedreamV4p5EditImageNumImages>,
pub max_images: Option<EnqueueBytedanceSeedreamV4p5EditImageMaxImages>,
pub image_size: Option<EnqueueBytedanceSeedreamV4p5EditImageSize>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4p5EditImageNumImages {
One,
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4p5EditImageMaxImages {
One,
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4p5EditImageSize {
// Square
Square,
SquareHd,
// Tall
PortraitFourThree,
PortraitSixteenNine,
// Wide
LandscapeFourThree,
LandscapeSixteenNine,
// Auto
Auto2k,
Auto4k,
}
pub async fn enqueue_bytedance_seedream_v4p5_edit_image_webhook<R: IntoUrl>(
args: EnqueueBytedanceSeedreamV4p5EditImageArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let num_images = args.num_images
.map(|num_images| match num_images {
EnqueueBytedanceSeedreamV4p5EditImageNumImages::One => 1,
EnqueueBytedanceSeedreamV4p5EditImageNumImages::Two => 2,
EnqueueBytedanceSeedreamV4p5EditImageNumImages::Three => 3,
EnqueueBytedanceSeedreamV4p5EditImageNumImages::Four => 4,
});
let max_images = args.max_images
.map(|num_images| match num_images {
EnqueueBytedanceSeedreamV4p5EditImageMaxImages::One => 1,
EnqueueBytedanceSeedreamV4p5EditImageMaxImages::Two => 2,
EnqueueBytedanceSeedreamV4p5EditImageMaxImages::Three => 3,
EnqueueBytedanceSeedreamV4p5EditImageMaxImages::Four => 4,
});
let image_size = args.image_size
.map(|image_size| match image_size {
EnqueueBytedanceSeedreamV4p5EditImageSize::Square => "square",
EnqueueBytedanceSeedreamV4p5EditImageSize::SquareHd => "square_hd",
EnqueueBytedanceSeedreamV4p5EditImageSize::PortraitFourThree => "portrait_4_3",
EnqueueBytedanceSeedreamV4p5EditImageSize::PortraitSixteenNine => "portrait_16_9",
EnqueueBytedanceSeedreamV4p5EditImageSize::LandscapeFourThree => "landscape_4_3",
EnqueueBytedanceSeedreamV4p5EditImageSize::LandscapeSixteenNine => "landscape_16_9",
EnqueueBytedanceSeedreamV4p5EditImageSize::Auto2k => "auto_2K",
EnqueueBytedanceSeedreamV4p5EditImageSize::Auto4k => "auto_4K",
})
.map(|resolution| resolution.to_string());
let request = BytedanceSeedreamV4p5EditImageInput {
prompt: args.prompt.to_string(),
image_urls: args.image_urls,
// Optionals
num_images,
max_images,
image_size,
// Constants
enable_safety_checker: Some(false),
seed: None,
};
let result = bytedance_seedream_v4p5_edit_image(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::image::edit::enqueue_bytedance_seedream_v4p5_edit_image_webhook::{enqueue_bytedance_seedream_v4p5_edit_image_webhook, EnqueueBytedanceSeedreamV4p5EditImageArgs, EnqueueBytedanceSeedreamV4p5EditImageMaxImages, EnqueueBytedanceSeedreamV4p5EditImageNumImages, EnqueueBytedanceSeedreamV4p5EditImageSize};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::{GHOST_IMAGE_URL, TREX_SKELETON_IMAGE_URL};
#[tokio::test]
#[ignore]
async fn test() -> AnyhowResult<()> {
// XXX: Don't commit secrets!
//let secret = read_to_string("/Users/bt/Artcraft/credentials/fal_api_key.txt")?;
let secret = read_to_string("/home/bt/Artcraft/credentials/fal_api_key.txt")?;
let api_key = FalApiKey::from_str(&secret);
let args = EnqueueBytedanceSeedreamV4p5EditImageArgs {
image_urls: vec![
GHOST_IMAGE_URL.to_string(),
TREX_SKELETON_IMAGE_URL.to_string(),
],
prompt: "add the ghost to the image of the t-rex skeleton, make it look spooky but friendly",
num_images: Some(EnqueueBytedanceSeedreamV4p5EditImageNumImages::Two),
max_images: Some(EnqueueBytedanceSeedreamV4p5EditImageMaxImages::Two),
image_size: Some(EnqueueBytedanceSeedreamV4p5EditImageSize::Auto2k),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_bytedance_seedream_v4p5_edit_image_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,147 @@
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::nano_banana_pro::nano_banana_pro_image_edit::{nano_banana_pro_image_edit, NanoBananaProImageEditInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueNanoBananaProEditImageArgs<'a, R: IntoUrl> {
// Request required
pub prompt: &'a str,
pub image_urls: Vec<String>,
pub num_images: EnqueueNanoBananaProEditImageNumImages,
// Optional args
pub resolution: Option<EnqueueNanoBananaProEditImageResolution>,
pub aspect_ratio: Option<EnqueueNanoBananaProEditImageAspectRatio>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueNanoBananaProEditImageNumImages {
One,
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueNanoBananaProEditImageResolution {
OneK,
TwoK,
FourK,
}
/// 21:9, 16:9, 3:2, 4:3, 5:4, 1:1, 4:5, 3:4, 2:3, 9:16
/// Default is "1:1"
#[derive(Copy, Clone, Debug)]
pub enum EnqueueNanoBananaProEditImageAspectRatio {
// Square
OneByOne,
// Wide
FiveByFour,
FourByThree,
ThreeByTwo,
SixteenByNine,
TwentyOneByNine,
// Tall
FourByFive,
ThreeByFour,
TwoByThree,
NineBySixteen, // NB: No NineByTwentyOne ?
}
pub async fn enqueue_nano_banana_pro_image_edit_webhook<R: IntoUrl>(
args: EnqueueNanoBananaProEditImageArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let num_images = match args.num_images {
EnqueueNanoBananaProEditImageNumImages::One => 1,
EnqueueNanoBananaProEditImageNumImages::Two => 2,
EnqueueNanoBananaProEditImageNumImages::Three => 3,
EnqueueNanoBananaProEditImageNumImages::Four => 4,
};
let resolution = args.resolution
.map(|resolution| match resolution {
EnqueueNanoBananaProEditImageResolution::OneK => "1K",
EnqueueNanoBananaProEditImageResolution::TwoK => "2K",
EnqueueNanoBananaProEditImageResolution::FourK => "4K",
})
.map(|resolution| resolution.to_string());
let aspect_ratio = args.aspect_ratio
.map(|aspect_ratio| match aspect_ratio {
// Square
EnqueueNanoBananaProEditImageAspectRatio::OneByOne => "1:1",
// Wide
EnqueueNanoBananaProEditImageAspectRatio::FiveByFour => "5:4",
EnqueueNanoBananaProEditImageAspectRatio::FourByThree => "4:3",
EnqueueNanoBananaProEditImageAspectRatio::ThreeByTwo => "3:2",
EnqueueNanoBananaProEditImageAspectRatio::SixteenByNine => "16:9",
EnqueueNanoBananaProEditImageAspectRatio::TwentyOneByNine => "21:9",
// Tall
EnqueueNanoBananaProEditImageAspectRatio::FourByFive => "4:5",
EnqueueNanoBananaProEditImageAspectRatio::ThreeByFour => "3:4",
EnqueueNanoBananaProEditImageAspectRatio::TwoByThree => "2:3",
EnqueueNanoBananaProEditImageAspectRatio::NineBySixteen => "9:16",
})
.map(|aspect_ratio| aspect_ratio.to_string());
let request = NanoBananaProImageEditInput {
prompt: args.prompt.to_string(),
image_urls: args.image_urls,
num_images: Some(num_images),
// Optionals
aspect_ratio,
resolution,
// Constants
output_format: Some("png".to_string()),
};
let result = nano_banana_pro_image_edit(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::image::edit::enqueue_nano_banana_pro_edit_image_webhook::{enqueue_nano_banana_pro_image_edit_webhook, EnqueueNanoBananaProEditImageArgs, EnqueueNanoBananaProEditImageAspectRatio, EnqueueNanoBananaProEditImageNumImages, EnqueueNanoBananaProEditImageResolution};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::{ERNEST_SCARED_STUPID_IMAGE_URL, GHOST_IMAGE_URL, TREX_SKELETON_IMAGE_URL};
#[tokio::test]
#[ignore]
async fn test() -> AnyhowResult<()> {
// XXX: Don't commit secrets!
let secret = read_to_string("/Users/bt/Artcraft/credentials/fal_api_key.txt")?;
let api_key = FalApiKey::from_str(&secret);
let args = EnqueueNanoBananaProEditImageArgs {
image_urls: vec![
GHOST_IMAGE_URL.to_string(),
TREX_SKELETON_IMAGE_URL.to_string(),
ERNEST_SCARED_STUPID_IMAGE_URL.to_string(),
],
prompt: "add the ghost and scared man to the image of the t-rex skeleton, make it look spooky but friendly",
num_images: EnqueueNanoBananaProEditImageNumImages::Two,
aspect_ratio: Some(EnqueueNanoBananaProEditImageAspectRatio::SixteenByNine),
resolution: Some(EnqueueNanoBananaProEditImageResolution::TwoK),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_nano_banana_pro_image_edit_webhook(args).await?;
Ok(())
}
}
@@ -1,5 +1,8 @@
pub mod enqueue_bytedance_seedream_v4_edit_image_webhook;
pub mod enqueue_bytedance_seedream_v4p5_edit_image_webhook;
pub mod enqueue_flux_pro_kontext_max_edit_webhook;
pub mod enqueue_gemini_25_flash_edit_webhook;
pub mod enqueue_gpt_image_1_edit_image_webhook;
pub mod enqueue_nano_banana_pro_edit_image_webhook;
pub mod enqueue_qwen_image_edit_webhook;
pub mod enqueue_seededit_v3_edit_webhook;
@@ -6,3 +6,4 @@ pub mod enqueue_flux_pro_11_ultra_text_to_image_webhook;
pub mod enqueue_gpt_image_1_text_to_image_webhook;
pub mod infill;
pub mod remove_background_rembg_webhook;
pub mod text;
@@ -0,0 +1,137 @@
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::bytedance::seedream::bytedance_seedream_v4_text_to_image::BytedanceSeedreamV4TextToImageInput;
use fal::prelude::fal_ai::bytedance::seedream::bytedance_seedream_v4_text_to_image::bytedance_seedream_v4_text_to_image;
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueBytedanceSeedreamV4TextToImageArgs<'a, R: IntoUrl> {
// Request required
pub prompt: &'a str,
// Optional args
pub num_images: Option<EnqueueBytedanceSeedreamV4TextToImageNumImages>,
pub max_images: Option<EnqueueBytedanceSeedreamV4TextToImageMaxImages>,
pub image_size: Option<EnqueueBytedanceSeedreamV4TextToImageSize>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4TextToImageNumImages {
One,
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4TextToImageMaxImages {
One,
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4TextToImageSize {
// Square
Square,
SquareHd,
// Tall
PortraitFourThree,
PortraitSixteenNine,
// Wide
LandscapeFourThree,
LandscapeSixteenNine,
// Auto
Auto,
Auto2k,
Auto4k,
}
pub async fn enqueue_bytedance_seedream_v4_text_to_image_webhook<R: IntoUrl>(
args: EnqueueBytedanceSeedreamV4TextToImageArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let num_images = args.num_images
.map(|num_images| match num_images {
EnqueueBytedanceSeedreamV4TextToImageNumImages::One => 1,
EnqueueBytedanceSeedreamV4TextToImageNumImages::Two => 2,
EnqueueBytedanceSeedreamV4TextToImageNumImages::Three => 3,
EnqueueBytedanceSeedreamV4TextToImageNumImages::Four => 4,
});
let max_images = args.max_images
.map(|num_images| match num_images {
EnqueueBytedanceSeedreamV4TextToImageMaxImages::One => 1,
EnqueueBytedanceSeedreamV4TextToImageMaxImages::Two => 2,
EnqueueBytedanceSeedreamV4TextToImageMaxImages::Three => 3,
EnqueueBytedanceSeedreamV4TextToImageMaxImages::Four => 4,
});
let image_size = args.image_size
.map(|image_size| match image_size {
EnqueueBytedanceSeedreamV4TextToImageSize::Square => "square",
EnqueueBytedanceSeedreamV4TextToImageSize::SquareHd => "square_hd",
EnqueueBytedanceSeedreamV4TextToImageSize::PortraitFourThree => "portrait_4_3",
EnqueueBytedanceSeedreamV4TextToImageSize::PortraitSixteenNine => "portrait_16_9",
EnqueueBytedanceSeedreamV4TextToImageSize::LandscapeFourThree => "landscape_4_3",
EnqueueBytedanceSeedreamV4TextToImageSize::LandscapeSixteenNine => "landscape_16_9",
EnqueueBytedanceSeedreamV4TextToImageSize::Auto => "auto",
EnqueueBytedanceSeedreamV4TextToImageSize::Auto2k => "auto_2K",
EnqueueBytedanceSeedreamV4TextToImageSize::Auto4k => "auto_4K",
})
.map(|resolution| resolution.to_string());
let request = BytedanceSeedreamV4TextToImageInput {
prompt: args.prompt.to_string(),
// Optionals
num_images,
max_images,
image_size,
// Constants
enhance_prompt_mode: Some("standard".to_string()),
enable_safety_checker: Some(false),
};
let result = bytedance_seedream_v4_text_to_image(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::image::text::enqueue_bytedance_seedream_v4_text_to_image_webhook::{enqueue_bytedance_seedream_v4_text_to_image_webhook, EnqueueBytedanceSeedreamV4TextToImageArgs, EnqueueBytedanceSeedreamV4TextToImageMaxImages, EnqueueBytedanceSeedreamV4TextToImageNumImages, EnqueueBytedanceSeedreamV4TextToImageSize};
use errors::AnyhowResult;
use std::fs::read_to_string;
#[tokio::test]
#[ignore]
async fn test() -> AnyhowResult<()> {
// XXX: Don't commit secrets!
let secret = read_to_string("/Users/bt/Artcraft/credentials/fal_api_key.txt")?;
let api_key = FalApiKey::from_str(&secret);
let args = EnqueueBytedanceSeedreamV4TextToImageArgs {
prompt: "an anime girl is riding a t-rex in the forest",
num_images: Some(EnqueueBytedanceSeedreamV4TextToImageNumImages::Two),
max_images: Some(EnqueueBytedanceSeedreamV4TextToImageMaxImages::Two),
image_size: Some(EnqueueBytedanceSeedreamV4TextToImageSize::LandscapeSixteenNine),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_bytedance_seedream_v4_text_to_image_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,134 @@
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::bytedance::seedream::bytedance_seedream_v4p5_text_to_image::{bytedance_seedream_v4p5_text_to_image, BytedanceSeedreamV4p5TextToImageInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueBytedanceSeedreamV4p5TextToImageArgs<'a, R: IntoUrl> {
// Request required
pub prompt: &'a str,
// Optional args
pub num_images: Option<EnqueueBytedanceSeedreamV4p5TextToImageNumImages>,
pub max_images: Option<EnqueueBytedanceSeedreamV4p5TextToImageMaxImages>,
pub image_size: Option<EnqueueBytedanceSeedreamV4p5TextToImageSize>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4p5TextToImageNumImages {
One,
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4p5TextToImageMaxImages {
One,
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueBytedanceSeedreamV4p5TextToImageSize {
// Square
Square,
SquareHd,
// Tall
PortraitFourThree,
PortraitSixteenNine,
// Wide
LandscapeFourThree,
LandscapeSixteenNine,
// Auto
Auto2k,
Auto4k,
}
pub async fn enqueue_bytedance_seedream_v4p5_text_to_image_webhook<R: IntoUrl>(
args: EnqueueBytedanceSeedreamV4p5TextToImageArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let num_images = args.num_images
.map(|num_images| match num_images {
EnqueueBytedanceSeedreamV4p5TextToImageNumImages::One => 1,
EnqueueBytedanceSeedreamV4p5TextToImageNumImages::Two => 2,
EnqueueBytedanceSeedreamV4p5TextToImageNumImages::Three => 3,
EnqueueBytedanceSeedreamV4p5TextToImageNumImages::Four => 4,
});
let max_images = args.max_images
.map(|num_images| match num_images {
EnqueueBytedanceSeedreamV4p5TextToImageMaxImages::One => 1,
EnqueueBytedanceSeedreamV4p5TextToImageMaxImages::Two => 2,
EnqueueBytedanceSeedreamV4p5TextToImageMaxImages::Three => 3,
EnqueueBytedanceSeedreamV4p5TextToImageMaxImages::Four => 4,
});
let image_size = args.image_size
.map(|image_size| match image_size {
EnqueueBytedanceSeedreamV4p5TextToImageSize::Square => "square",
EnqueueBytedanceSeedreamV4p5TextToImageSize::SquareHd => "square_hd",
EnqueueBytedanceSeedreamV4p5TextToImageSize::PortraitFourThree => "portrait_4_3",
EnqueueBytedanceSeedreamV4p5TextToImageSize::PortraitSixteenNine => "portrait_16_9",
EnqueueBytedanceSeedreamV4p5TextToImageSize::LandscapeFourThree => "landscape_4_3",
EnqueueBytedanceSeedreamV4p5TextToImageSize::LandscapeSixteenNine => "landscape_16_9",
EnqueueBytedanceSeedreamV4p5TextToImageSize::Auto2k => "auto_2K",
EnqueueBytedanceSeedreamV4p5TextToImageSize::Auto4k => "auto_4K",
})
.map(|resolution| resolution.to_string());
let request = BytedanceSeedreamV4p5TextToImageInput {
prompt: args.prompt.to_string(),
// Optionals
num_images,
max_images,
image_size,
// Constants
enable_safety_checker: Some(false),
seed: None,
};
let result = bytedance_seedream_v4p5_text_to_image(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::image::text::enqueue_bytedance_seedream_v4p5_text_to_image_webhook::{enqueue_bytedance_seedream_v4p5_text_to_image_webhook, EnqueueBytedanceSeedreamV4p5TextToImageArgs, EnqueueBytedanceSeedreamV4p5TextToImageMaxImages, EnqueueBytedanceSeedreamV4p5TextToImageNumImages, EnqueueBytedanceSeedreamV4p5TextToImageSize};
use errors::AnyhowResult;
use std::fs::read_to_string;
#[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 = EnqueueBytedanceSeedreamV4p5TextToImageArgs {
prompt: "an anime girl is riding a t-rex in the forest",
num_images: Some(EnqueueBytedanceSeedreamV4p5TextToImageNumImages::Two),
max_images: Some(EnqueueBytedanceSeedreamV4p5TextToImageMaxImages::Two),
image_size: Some(EnqueueBytedanceSeedreamV4p5TextToImageSize::LandscapeSixteenNine),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_bytedance_seedream_v4p5_text_to_image_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,139 @@
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::nano_banana_pro::nano_banana_pro_text_to_image::{nano_banana_pro_text_to_image, NanoBananaProTextToImageInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueNanoBananaProTextToImageArgs<'a, R: IntoUrl> {
// Request required
pub prompt: &'a str,
pub num_images: EnqueueNanoBananaProTextToImageNumImages,
// Optional args
pub resolution: Option<EnqueueNanoBananaProTextToImageResolution>,
pub aspect_ratio: Option<EnqueueNanoBananaProTextToImageAspectRatio>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueNanoBananaProTextToImageNumImages {
One,
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueNanoBananaProTextToImageResolution {
OneK,
TwoK,
FourK,
}
/// 21:9, 16:9, 3:2, 4:3, 5:4, 1:1, 4:5, 3:4, 2:3, 9:16
/// Default is "1:1"
#[derive(Copy, Clone, Debug)]
pub enum EnqueueNanoBananaProTextToImageAspectRatio {
// Square
OneByOne,
// Wide
FiveByFour,
FourByThree,
ThreeByTwo,
SixteenByNine,
TwentyOneByNine,
// Tall
FourByFive,
ThreeByFour,
TwoByThree,
NineBySixteen, // NB: No NineByTwentyOne ?
}
pub async fn enqueue_nano_banana_pro_text_to_image_webhook<R: IntoUrl>(
args: EnqueueNanoBananaProTextToImageArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let num_images = match args.num_images {
EnqueueNanoBananaProTextToImageNumImages::One => 1,
EnqueueNanoBananaProTextToImageNumImages::Two => 2,
EnqueueNanoBananaProTextToImageNumImages::Three => 3,
EnqueueNanoBananaProTextToImageNumImages::Four => 4,
};
let resolution = args.resolution
.map(|resolution| match resolution {
EnqueueNanoBananaProTextToImageResolution::OneK => "1K",
EnqueueNanoBananaProTextToImageResolution::TwoK => "2K",
EnqueueNanoBananaProTextToImageResolution::FourK => "4K",
})
.map(|resolution| resolution.to_string());
let aspect_ratio = args.aspect_ratio
.map(|aspect_ratio| match aspect_ratio {
// Square
EnqueueNanoBananaProTextToImageAspectRatio::OneByOne => "1:1",
// Wide
EnqueueNanoBananaProTextToImageAspectRatio::FiveByFour => "5:4",
EnqueueNanoBananaProTextToImageAspectRatio::FourByThree => "4:3",
EnqueueNanoBananaProTextToImageAspectRatio::ThreeByTwo => "3:2",
EnqueueNanoBananaProTextToImageAspectRatio::SixteenByNine => "16:9",
EnqueueNanoBananaProTextToImageAspectRatio::TwentyOneByNine => "21:9",
// Tall
EnqueueNanoBananaProTextToImageAspectRatio::FourByFive => "4:5",
EnqueueNanoBananaProTextToImageAspectRatio::ThreeByFour => "3:4",
EnqueueNanoBananaProTextToImageAspectRatio::TwoByThree => "2:3",
EnqueueNanoBananaProTextToImageAspectRatio::NineBySixteen => "9:16",
})
.map(|aspect_ratio| aspect_ratio.to_string());
let request = NanoBananaProTextToImageInput {
prompt: args.prompt.to_string(),
num_images: Some(num_images),
// Optionals
aspect_ratio,
resolution,
// Constants
output_format: Some("png".to_string()),
};
let result = nano_banana_pro_text_to_image(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::image::text::enqueue_nano_banana_pro_text_to_image_webhook::{enqueue_nano_banana_pro_text_to_image_webhook, EnqueueNanoBananaProTextToImageArgs, EnqueueNanoBananaProTextToImageAspectRatio, EnqueueNanoBananaProTextToImageNumImages, EnqueueNanoBananaProTextToImageResolution};
use errors::AnyhowResult;
use std::fs::read_to_string;
#[tokio::test]
#[ignore]
async fn test() -> AnyhowResult<()> {
// XXX: Don't commit secrets!
let secret = read_to_string("/Users/bt/Artcraft/credentials/fal_api_key.txt")?;
let api_key = FalApiKey::from_str(&secret);
let args = EnqueueNanoBananaProTextToImageArgs {
prompt: "an anime girl riding on the back of a t-rex",
num_images: EnqueueNanoBananaProTextToImageNumImages::One,
aspect_ratio: Some(EnqueueNanoBananaProTextToImageAspectRatio::SixteenByNine),
resolution: Some(EnqueueNanoBananaProTextToImageResolution::TwoK),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_nano_banana_pro_text_to_image_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,3 @@
pub mod enqueue_bytedance_seedream_v4_text_to_image_webhook;
pub mod enqueue_bytedance_seedream_v4p5_text_to_image_webhook;
pub mod enqueue_nano_banana_pro_text_to_image_webhook;
@@ -0,0 +1,70 @@
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::minimax::hailuo::hailuo_v2p3_fast_pro_image_to_video::{hailuo_v2p3_fast_pro_image_to_video, HailuoV2p3FastProImageToVideoInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueHailuoV2p3FastProImageToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
pub image_url: String,
// Optional args
pub prompt_optimizer: Option<bool>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
pub async fn enqueue_hailuo_v2p3_fast_pro_image_to_video_webhook<R: IntoUrl>(
args: EnqueueHailuoV2p3FastProImageToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let prompt_optimizer = args.prompt_optimizer.unwrap_or(true);
let request = HailuoV2p3FastProImageToVideoInput {
prompt: args.prompt,
image_url: args.image_url,
// Optionals
prompt_optimizer: Some(prompt_optimizer),
};
let result = hailuo_v2p3_fast_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_hailuo_v2p3_fast_pro_image_to_video_webhook::{enqueue_hailuo_v2p3_fast_pro_image_to_video_webhook, EnqueueHailuoV2p3FastProImageToVideoArgs};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::TREX_SKELETON_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 = EnqueueHailuoV2p3FastProImageToVideoArgs {
image_url: TREX_SKELETON_IMAGE_URL.to_string(),
prompt: "the t-rex skeleton gets off the podium and begins walking to the camera. the camera orbits slightly. The t-rex gets close and then bites.".to_string(),
prompt_optimizer: Some(true),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_hailuo_v2p3_fast_pro_image_to_video_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,70 @@
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::minimax::hailuo::hailuo_v2p3_pro_image_to_video::{hailuo_v2p3_pro_image_to_video, HailuoV2p3ProImageToVideoInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueHailuoV2p3ProImageToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
pub image_url: String,
// Optional args
pub prompt_optimizer: Option<bool>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
pub async fn enqueue_hailuo_v2p3_pro_image_to_video_webhook<R: IntoUrl>(
args: EnqueueHailuoV2p3ProImageToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let prompt_optimizer = args.prompt_optimizer.unwrap_or(true);
let request = HailuoV2p3ProImageToVideoInput {
prompt: args.prompt,
image_url: args.image_url,
// Optionals
prompt_optimizer: Some(prompt_optimizer),
};
let result = hailuo_v2p3_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_hailuo_v2p3_pro_image_to_video_webhook::{enqueue_hailuo_v2p3_pro_image_to_video_webhook, EnqueueHailuoV2p3ProImageToVideoArgs};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::TREX_SKELETON_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 = EnqueueHailuoV2p3ProImageToVideoArgs {
image_url: TREX_SKELETON_IMAGE_URL.to_string(),
prompt: "the t-rex skeleton gets off the podium and begins walking to the camera. the camera orbits slightly. The t-rex gets close and then bites.".to_string(),
prompt_optimizer: Some(true),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_hailuo_v2p3_pro_image_to_video_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,90 @@
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_5::kling_v2p5_turbo_pro_image_to_video::{kling_v2p5_turbo_pro_image_to_video, KlingV2p5TurboProImageToVideoInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueKlingV2p5TurboProImageToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
pub image_url: String,
// Optional args
pub tail_image_url: Option<String>,
pub negative_prompt: Option<String>,
pub duration: Option<EnqueueKlingV2p5TurboProImageToVideoDurationSeconds>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueKlingV2p5TurboProImageToVideoDurationSeconds {
Five,
Ten,
}
pub async fn enqueue_kling_v2p5_turbo_pro_image_to_video_webhook<R: IntoUrl>(
args: EnqueueKlingV2p5TurboProImageToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let duration = args.duration
.map(|resolution| match resolution {
EnqueueKlingV2p5TurboProImageToVideoDurationSeconds::Five => "5",
EnqueueKlingV2p5TurboProImageToVideoDurationSeconds::Ten => "10",
})
.map(|resolution| resolution.to_string());
let request = KlingV2p5TurboProImageToVideoInput {
prompt: args.prompt,
image_url: args.image_url,
// Optionals
duration,
tail_image_url: args.tail_image_url,
negative_prompt: args.negative_prompt,
// Constants
cfg_scale: None,
};
let result = kling_v2p5_turbo_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_v2p5_turbo_pro_image_to_video_webhook::{enqueue_kling_v2p5_turbo_pro_image_to_video_webhook, EnqueueKlingV2p5TurboProImageToVideoArgs, EnqueueKlingV2p5TurboProImageToVideoDurationSeconds};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::TREX_SKELETON_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 = EnqueueKlingV2p5TurboProImageToVideoArgs {
image_url: TREX_SKELETON_IMAGE_URL.to_string(),
prompt: "the t-rex skeleton gets off the podium and begins walking to the camera. the camera orbits slightly. The t-rex gets close and then bites.".to_string(),
negative_prompt: None,
tail_image_url: None,
duration: Some(EnqueueKlingV2p5TurboProImageToVideoDurationSeconds::Five),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_kling_v2p5_turbo_pro_image_to_video_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,86 @@
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::webhook::WebhookResponse;
use reqwest::IntoUrl;
use fal::endpoints::fal_ai::kling_video::v2_5::kling_v2p5_turbo_standard_image_to_video::{kling_v2p5_turbo_standard_image_to_video, KlingV2p5TurboStandardImageToVideoInput};
pub struct EnqueueKlingV2p5TurboStandardImageToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
pub image_url: String,
// Optional args
pub negative_prompt: Option<String>,
pub duration: Option<EnqueueKlingV2p5TurboStandardImageToVideoDurationSeconds>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueKlingV2p5TurboStandardImageToVideoDurationSeconds {
Five,
Ten,
}
pub async fn enqueue_kling_v2p5_turbo_standard_image_to_video_webhook<R: IntoUrl>(
args: EnqueueKlingV2p5TurboStandardImageToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let duration = args.duration
.map(|resolution| match resolution {
EnqueueKlingV2p5TurboStandardImageToVideoDurationSeconds::Five => "5",
EnqueueKlingV2p5TurboStandardImageToVideoDurationSeconds::Ten => "10",
})
.map(|resolution| resolution.to_string());
let request = KlingV2p5TurboStandardImageToVideoInput {
prompt: args.prompt,
image_url: args.image_url,
// Optionals
duration,
negative_prompt: args.negative_prompt,
// Constants
cfg_scale: None,
};
let result = kling_v2p5_turbo_standard_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 errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::TREX_SKELETON_IMAGE_URL;
use crate::requests::webhook::video::image::enqueue_kling_v2p5_turbo_standard_image_to_video_webhook::{enqueue_kling_v2p5_turbo_standard_image_to_video_webhook, EnqueueKlingV2p5TurboStandardImageToVideoArgs, EnqueueKlingV2p5TurboStandardImageToVideoDurationSeconds};
#[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 = EnqueueKlingV2p5TurboStandardImageToVideoArgs {
image_url: TREX_SKELETON_IMAGE_URL.to_string(),
prompt: "the t-rex skeleton gets off the podium and begins walking to the camera. the camera orbits slightly. The t-rex gets close and then bites.".to_string(),
negative_prompt: None,
duration: Some(EnqueueKlingV2p5TurboStandardImageToVideoDurationSeconds::Five),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_kling_v2p5_turbo_standard_image_to_video_webhook(args).await?;
Ok(())
}
}
@@ -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(())
}
}
@@ -0,0 +1,152 @@
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::pixverse::v5::pixverse_v5_image_to_video::{pixverse_v5_image_to_video, PixverseV5ImageToVideoInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueuePixverseV5ImageToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
pub image_url: String,
// Optional args
pub negative_prompt: Option<String>,
// NB: eight-second videos do not work with 1080P
pub duration: Option<EnqueuePixverseV5ImageToVideoDurationSeconds>,
pub aspect_ratio: Option<EnqueuePixverseV5ImageToVideoAspectRatio>,
pub resolution: Option<EnqueuePixverseV5ImageToVideoResolution>,
pub style: Option<EnqueuePixverseV5ImageToVideoStyle>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueuePixverseV5ImageToVideoDurationSeconds {
Five,
Eight,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueuePixverseV5ImageToVideoResolution {
ThreeSixtyP,
FiveFortyP,
SevenTwentyP,
TenEightyP,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueuePixverseV5ImageToVideoAspectRatio {
Square,
SixteenByNine,
FourByThree,
NineBySixteen,
ThreeByFour,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueuePixverseV5ImageToVideoStyle {
Anime,
Animation3d,
Clay,
Comic,
Cyberpunk,
}
pub async fn enqueue_pixverse_v5_image_to_video_webhook<R: IntoUrl>(
args: EnqueuePixverseV5ImageToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let duration = args.duration
.map(|resolution| match resolution {
EnqueuePixverseV5ImageToVideoDurationSeconds::Five => "5",
EnqueuePixverseV5ImageToVideoDurationSeconds::Eight=> "8",
})
.map(|s| s.to_string());
let aspect_ratio = args.aspect_ratio
.map(|aspect_ratio| match aspect_ratio {
EnqueuePixverseV5ImageToVideoAspectRatio::Square => "1:1",
EnqueuePixverseV5ImageToVideoAspectRatio::SixteenByNine => "16:9",
EnqueuePixverseV5ImageToVideoAspectRatio::FourByThree => "4:3",
EnqueuePixverseV5ImageToVideoAspectRatio::NineBySixteen => "9:16",
EnqueuePixverseV5ImageToVideoAspectRatio::ThreeByFour => "3:4",
})
.map(|s| s.to_string());
let resolution = args.resolution
.map(|resolution| match resolution {
EnqueuePixverseV5ImageToVideoResolution::ThreeSixtyP => "360p",
EnqueuePixverseV5ImageToVideoResolution::FiveFortyP => "540p",
EnqueuePixverseV5ImageToVideoResolution::SevenTwentyP => "720p",
EnqueuePixverseV5ImageToVideoResolution::TenEightyP => "1080p",
})
.map(|s| s.to_string());
let style = args.style
.map(|style| match style {
EnqueuePixverseV5ImageToVideoStyle::Anime => "anime",
EnqueuePixverseV5ImageToVideoStyle::Animation3d => "3d_animation",
EnqueuePixverseV5ImageToVideoStyle::Clay => "clay",
EnqueuePixverseV5ImageToVideoStyle::Comic => "comic",
EnqueuePixverseV5ImageToVideoStyle::Cyberpunk => "cyberpunk",
})
.map(|s| s.to_string());
let request = PixverseV5ImageToVideoInput {
prompt: args.prompt,
image_url: args.image_url,
// Optionals
duration,
negative_prompt: args.negative_prompt,
aspect_ratio,
resolution,
style,
// Constant
seed: None,
};
let result = pixverse_v5_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_pixverse_v5_image_to_video_webhook::{enqueue_pixverse_v5_image_to_video_webhook, EnqueuePixverseV5ImageToVideoArgs, EnqueuePixverseV5ImageToVideoAspectRatio, EnqueuePixverseV5ImageToVideoDurationSeconds, EnqueuePixverseV5ImageToVideoResolution, EnqueuePixverseV5ImageToVideoStyle};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::TREX_SKELETON_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 = EnqueuePixverseV5ImageToVideoArgs {
image_url: TREX_SKELETON_IMAGE_URL.to_string(),
prompt: "the t-rex skeleton gets off the podium and begins walking to the camera. the camera orbits slightly. The t-rex gets close and then bites.".to_string(),
negative_prompt: None,
duration: Some(EnqueuePixverseV5ImageToVideoDurationSeconds::Five),
style: Some(EnqueuePixverseV5ImageToVideoStyle::Cyberpunk),
aspect_ratio: Some(EnqueuePixverseV5ImageToVideoAspectRatio::FourByThree),
resolution: Some(EnqueuePixverseV5ImageToVideoResolution::TenEightyP),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_pixverse_v5_image_to_video_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,118 @@
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::sora::sora2::sora_2_image_to_video::{sora_2_image_to_video, Sora2ImageToVideoInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueSora2ImageToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
pub image_url: String,
// Optional args
pub resolution: Option<EnqueueSora2ImageToVideoResolution>,
pub duration: Option<EnqueueSora2ImageToVideoDurationSeconds>,
pub aspect_ratio: Option<EnqueueSora2ImageToVideoAspectRatio>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueSora2ImageToVideoDurationSeconds {
Four,
Eight,
Twelve,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueSora2ImageToVideoResolution {
Auto,
SevenTwentyP,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueSora2ImageToVideoAspectRatio {
Auto,
NineBySixteen,
SixteenByNine,
}
pub async fn enqueue_sora_2_image_to_video_webhook<R: IntoUrl>(
args: EnqueueSora2ImageToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let duration = args.duration
.map(|resolution| match resolution {
EnqueueSora2ImageToVideoDurationSeconds::Four => 4,
EnqueueSora2ImageToVideoDurationSeconds::Eight => 8,
EnqueueSora2ImageToVideoDurationSeconds::Twelve => 12,
});
let resolution = args.resolution
.map(|resolution| match resolution {
EnqueueSora2ImageToVideoResolution::Auto => "auto",
EnqueueSora2ImageToVideoResolution::SevenTwentyP => "720p",
})
.map(|resolution| resolution.to_string());
let aspect_ratio = args.aspect_ratio
.map(|aspect_ratio| match aspect_ratio {
EnqueueSora2ImageToVideoAspectRatio::Auto => "auto",
EnqueueSora2ImageToVideoAspectRatio::NineBySixteen => "9:16",
EnqueueSora2ImageToVideoAspectRatio::SixteenByNine => "16:9",
})
.map(|resolution| resolution.to_string());
let request = Sora2ImageToVideoInput {
prompt: args.prompt,
image_url: args.image_url,
// Optionals
duration,
resolution,
aspect_ratio,
// Constants
delete_video: Some(false),
};
let result = sora_2_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_sora_2_image_to_video_webhook::{enqueue_sora_2_image_to_video_webhook, EnqueueSora2ImageToVideoArgs, EnqueueSora2ImageToVideoAspectRatio, EnqueueSora2ImageToVideoDurationSeconds, EnqueueSora2ImageToVideoResolution};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::TREX_SKELETON_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 = EnqueueSora2ImageToVideoArgs {
image_url: TREX_SKELETON_IMAGE_URL.to_string(),
prompt: "the t-rex skeleton gets off the podium and begins walking to the camera. the camera orbits slightly. The t-rex gets close and then bites.".to_string(),
duration: Some(EnqueueSora2ImageToVideoDurationSeconds::Twelve),
aspect_ratio: Some(EnqueueSora2ImageToVideoAspectRatio::SixteenByNine),
resolution: Some(EnqueueSora2ImageToVideoResolution::SevenTwentyP),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_sora_2_image_to_video_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,120 @@
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::sora::sora2::sora_2_pro_image_to_video::{sora_2_pro_image_to_video, Sora2ProImageToVideoInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueSora2ProImageToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
pub image_url: String,
// Optional args
pub resolution: Option<EnqueueSora2ProImageToVideoResolution>,
pub duration: Option<EnqueueSora2ProImageToVideoDurationSeconds>,
pub aspect_ratio: Option<EnqueueSora2ProImageToVideoAspectRatio>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueSora2ProImageToVideoDurationSeconds {
Four,
Eight,
Twelve,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueSora2ProImageToVideoResolution {
Auto,
SevenTwentyP,
TenEightyP,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueSora2ProImageToVideoAspectRatio {
Auto,
NineBySixteen,
SixteenByNine,
}
pub async fn enqueue_sora_2_pro_image_to_video_webhook<R: IntoUrl>(
args: EnqueueSora2ProImageToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let duration = args.duration
.map(|resolution| match resolution {
EnqueueSora2ProImageToVideoDurationSeconds::Four => 4,
EnqueueSora2ProImageToVideoDurationSeconds::Eight => 8,
EnqueueSora2ProImageToVideoDurationSeconds::Twelve => 12,
});
let resolution = args.resolution
.map(|resolution| match resolution {
EnqueueSora2ProImageToVideoResolution::Auto => "auto",
EnqueueSora2ProImageToVideoResolution::SevenTwentyP => "720p",
EnqueueSora2ProImageToVideoResolution::TenEightyP => "1080p",
})
.map(|resolution| resolution.to_string());
let aspect_ratio = args.aspect_ratio
.map(|aspect_ratio| match aspect_ratio {
EnqueueSora2ProImageToVideoAspectRatio::Auto => "auto",
EnqueueSora2ProImageToVideoAspectRatio::NineBySixteen => "9:16",
EnqueueSora2ProImageToVideoAspectRatio::SixteenByNine => "16:9",
})
.map(|resolution| resolution.to_string());
let request = Sora2ProImageToVideoInput {
prompt: args.prompt,
image_url: args.image_url,
// Optionals
duration,
resolution,
aspect_ratio,
// Constants
delete_video: Some(false),
};
let result = sora_2_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_sora_2_pro_image_to_video_webhook::{enqueue_sora_2_pro_image_to_video_webhook, EnqueueSora2ProImageToVideoArgs, EnqueueSora2ProImageToVideoAspectRatio, EnqueueSora2ProImageToVideoDurationSeconds, EnqueueSora2ProImageToVideoResolution};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::TREX_SKELETON_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 = EnqueueSora2ProImageToVideoArgs {
image_url: TREX_SKELETON_IMAGE_URL.to_string(),
prompt: "the t-rex skeleton gets off the podium and begins walking to the camera. the camera orbits slightly. The t-rex gets close and then bites.".to_string(),
duration: Some(EnqueueSora2ProImageToVideoDurationSeconds::Twelve),
aspect_ratio: Some(EnqueueSora2ProImageToVideoAspectRatio::SixteenByNine),
resolution: Some(EnqueueSora2ProImageToVideoResolution::TenEightyP),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_sora_2_pro_image_to_video_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,129 @@
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::veo::veo3_1::veo_3p1_fast_first_last_frame_image_to_video::{veo_3p1_fast_first_last_frame_image_to_video, Veo3p1FastFirstLastFrameImageToVideoInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueVeo3p1FastFirstLastFrameImageToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
// Starting frame
pub first_frame_url: String,
// Ending frame
pub last_frame_url: String,
// Optional args
pub duration: Option<EnqueueVeo3p1FastFirstLastFrameImageToVideoDurationSeconds>,
pub aspect_ratio: Option<EnqueueVeo3p1FastFirstLastFrameImageToVideoAspectRatio>,
pub resolution: Option<EnqueueVeo3p1FastFirstLastFrameImageToVideoResolution>,
pub generate_audio: Option<bool>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1FastFirstLastFrameImageToVideoDurationSeconds {
Four,
Six,
Eight,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1FastFirstLastFrameImageToVideoAspectRatio {
Auto,
Square,
SixteenByNine,
NineBySixteen,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1FastFirstLastFrameImageToVideoResolution {
SevenTwentyP,
TenEightyP,
}
pub async fn enqueue_veo_3p1_fast_first_last_frame_image_to_video_webhook<R: IntoUrl>(
args: EnqueueVeo3p1FastFirstLastFrameImageToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let duration = args.duration
.map(|resolution| match resolution {
EnqueueVeo3p1FastFirstLastFrameImageToVideoDurationSeconds::Four => "4s",
EnqueueVeo3p1FastFirstLastFrameImageToVideoDurationSeconds::Six => "6s",
EnqueueVeo3p1FastFirstLastFrameImageToVideoDurationSeconds::Eight=> "8s",
})
.map(|s| s.to_string());
let aspect_ratio = args.aspect_ratio
.map(|aspect_ratio| match aspect_ratio {
EnqueueVeo3p1FastFirstLastFrameImageToVideoAspectRatio::Auto => "auto",
EnqueueVeo3p1FastFirstLastFrameImageToVideoAspectRatio::Square => "1:1",
EnqueueVeo3p1FastFirstLastFrameImageToVideoAspectRatio::SixteenByNine => "16:9",
EnqueueVeo3p1FastFirstLastFrameImageToVideoAspectRatio::NineBySixteen => "9:16",
})
.map(|s| s.to_string());
let resolution = args.resolution
.map(|resolution| match resolution {
EnqueueVeo3p1FastFirstLastFrameImageToVideoResolution::SevenTwentyP => "720p",
EnqueueVeo3p1FastFirstLastFrameImageToVideoResolution::TenEightyP => "1080p",
})
.map(|s| s.to_string());
let request = Veo3p1FastFirstLastFrameImageToVideoInput {
prompt: args.prompt,
first_frame_url: args.first_frame_url,
last_frame_url: args.last_frame_url,
generate_audio: args.generate_audio,
// Optionals
duration,
aspect_ratio,
resolution,
};
let result = veo_3p1_fast_first_last_frame_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_veo_3p1_fast_first_last_frame_image_to_video_webhook::{enqueue_veo_3p1_fast_first_last_frame_image_to_video_webhook, EnqueueVeo3p1FastFirstLastFrameImageToVideoArgs, EnqueueVeo3p1FastFirstLastFrameImageToVideoAspectRatio, EnqueueVeo3p1FastFirstLastFrameImageToVideoDurationSeconds, EnqueueVeo3p1FastFirstLastFrameImageToVideoResolution};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::{TALL_CORGI_SHIBA_TREASURE_OCEAN_URL, TALL_CORGI_SHIBA_TREASURE_SKY_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 = EnqueueVeo3p1FastFirstLastFrameImageToVideoArgs {
first_frame_url: TALL_CORGI_SHIBA_TREASURE_OCEAN_URL.to_string(),
last_frame_url: TALL_CORGI_SHIBA_TREASURE_SKY_URL.to_string(),
prompt: "There is a tiny ocean island with a corgi and shiba and treasure chest on it. The corgi and shiba are barking at the chest, when suddenly the island launches itself into the air. The camera tracks the island and follows it up high in the sky. The sun beams over the horizon. The dogs are happy and bark. The gold coins gleam in the sun.".to_string(),
duration: Some(EnqueueVeo3p1FastFirstLastFrameImageToVideoDurationSeconds::Six),
aspect_ratio: Some(EnqueueVeo3p1FastFirstLastFrameImageToVideoAspectRatio::NineBySixteen),
resolution: Some(EnqueueVeo3p1FastFirstLastFrameImageToVideoResolution::SevenTwentyP),
generate_audio: Some(true),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_veo_3p1_fast_first_last_frame_image_to_video_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,124 @@
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::veo::veo3_1::veo_3p1_fast_first_frame_image_to_video::{veo_3p1_fast_first_frame_image_to_video, Veo3p1FastFirstFrameImageToVideoInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueVeo3p1FastImageToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
// Starting frame
pub image_url: String,
// Optional args
pub duration: Option<EnqueueVeo3p1FastImageToVideoDurationSeconds>,
pub aspect_ratio: Option<EnqueueVeo3p1FastImageToVideoAspectRatio>,
pub resolution: Option<EnqueueVeo3p1FastImageToVideoResolution>,
pub generate_audio: Option<bool>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1FastImageToVideoDurationSeconds {
Four,
Six,
Eight,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1FastImageToVideoAspectRatio {
Auto,
Square,
SixteenByNine,
NineBySixteen,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1FastImageToVideoResolution {
SevenTwentyP,
TenEightyP,
}
pub async fn enqueue_veo_3p1_fast_image_to_video_webhook<R: IntoUrl>(
args: EnqueueVeo3p1FastImageToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let duration = args.duration
.map(|resolution| match resolution {
EnqueueVeo3p1FastImageToVideoDurationSeconds::Four => "4s",
EnqueueVeo3p1FastImageToVideoDurationSeconds::Six => "6s",
EnqueueVeo3p1FastImageToVideoDurationSeconds::Eight=> "8s",
})
.map(|s| s.to_string());
let aspect_ratio = args.aspect_ratio
.map(|aspect_ratio| match aspect_ratio {
EnqueueVeo3p1FastImageToVideoAspectRatio::Auto => "auto",
EnqueueVeo3p1FastImageToVideoAspectRatio::Square => "1:1",
EnqueueVeo3p1FastImageToVideoAspectRatio::SixteenByNine => "16:9",
EnqueueVeo3p1FastImageToVideoAspectRatio::NineBySixteen => "9:16",
})
.map(|s| s.to_string());
let resolution = args.resolution
.map(|resolution| match resolution {
EnqueueVeo3p1FastImageToVideoResolution::SevenTwentyP => "720p",
EnqueueVeo3p1FastImageToVideoResolution::TenEightyP => "1080p",
})
.map(|s| s.to_string());
let request = Veo3p1FastFirstFrameImageToVideoInput {
prompt: args.prompt,
image_url: args.image_url,
generate_audio: args.generate_audio,
// Optionals
duration,
aspect_ratio,
resolution,
};
let result = veo_3p1_fast_first_frame_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_veo_3p1_fast_image_to_video_webhook::{enqueue_veo_3p1_fast_image_to_video_webhook, EnqueueVeo3p1FastImageToVideoArgs, EnqueueVeo3p1FastImageToVideoAspectRatio, EnqueueVeo3p1FastImageToVideoDurationSeconds, EnqueueVeo3p1FastImageToVideoResolution};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::TALL_CORGI_SHIBA_TREASURE_OCEAN_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 = EnqueueVeo3p1FastImageToVideoArgs {
image_url: TALL_CORGI_SHIBA_TREASURE_OCEAN_URL.to_string(),
prompt: "There is a tiny ocean island with a corgi and shiba and treasure chest on it. The corgi and shiba are barking at the chest, when suddenly the island launches itself into the air. The camera tracks the island and follows it up high in the sky. The sun beams over the horizon. The dogs are happy and bark. The gold coins gleam in the sun.".to_string(),
duration: Some(EnqueueVeo3p1FastImageToVideoDurationSeconds::Four),
aspect_ratio: Some(EnqueueVeo3p1FastImageToVideoAspectRatio::SixteenByNine),
resolution: Some(EnqueueVeo3p1FastImageToVideoResolution::TenEightyP),
generate_audio: Some(true),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_veo_3p1_fast_image_to_video_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,129 @@
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::veo::veo3_1::veo_3p1_first_last_frame_image_to_video::{veo_3p1_first_last_frame_image_to_video, Veo3p1FirstLastFrameImageToVideoInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueVeo3p1FirstLastFrameImageToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
// Starting frame
pub first_frame_url: String,
// Ending frame
pub last_frame_url: String,
// Optional args
pub duration: Option<EnqueueVeo3p1FirstLastFrameImageToVideoDurationSeconds>,
pub aspect_ratio: Option<EnqueueVeo3p1FirstLastFrameImageToVideoAspectRatio>,
pub resolution: Option<EnqueueVeo3p1FirstLastFrameImageToVideoResolution>,
pub generate_audio: Option<bool>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1FirstLastFrameImageToVideoDurationSeconds {
Four,
Six,
Eight,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1FirstLastFrameImageToVideoAspectRatio {
Auto,
Square,
SixteenByNine,
NineBySixteen,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1FirstLastFrameImageToVideoResolution {
SevenTwentyP,
TenEightyP,
}
pub async fn enqueue_veo_3p1_first_last_frame_image_to_video_webhook<R: IntoUrl>(
args: EnqueueVeo3p1FirstLastFrameImageToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let duration = args.duration
.map(|resolution| match resolution {
EnqueueVeo3p1FirstLastFrameImageToVideoDurationSeconds::Four => "4s",
EnqueueVeo3p1FirstLastFrameImageToVideoDurationSeconds::Six => "6s",
EnqueueVeo3p1FirstLastFrameImageToVideoDurationSeconds::Eight=> "8s",
})
.map(|s| s.to_string());
let aspect_ratio = args.aspect_ratio
.map(|aspect_ratio| match aspect_ratio {
EnqueueVeo3p1FirstLastFrameImageToVideoAspectRatio::Auto => "auto",
EnqueueVeo3p1FirstLastFrameImageToVideoAspectRatio::Square => "1:1",
EnqueueVeo3p1FirstLastFrameImageToVideoAspectRatio::SixteenByNine => "16:9",
EnqueueVeo3p1FirstLastFrameImageToVideoAspectRatio::NineBySixteen => "9:16",
})
.map(|s| s.to_string());
let resolution = args.resolution
.map(|resolution| match resolution {
EnqueueVeo3p1FirstLastFrameImageToVideoResolution::SevenTwentyP => "720p",
EnqueueVeo3p1FirstLastFrameImageToVideoResolution::TenEightyP => "1080p",
})
.map(|s| s.to_string());
let request = Veo3p1FirstLastFrameImageToVideoInput {
prompt: args.prompt,
first_frame_url: args.first_frame_url,
last_frame_url: args.last_frame_url,
generate_audio: args.generate_audio,
// Optionals
duration,
aspect_ratio,
resolution,
};
let result = veo_3p1_first_last_frame_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_veo_3p1_first_last_frame_image_to_video_webhook::{enqueue_veo_3p1_first_last_frame_image_to_video_webhook, EnqueueVeo3p1FirstLastFrameImageToVideoArgs, EnqueueVeo3p1FirstLastFrameImageToVideoAspectRatio, EnqueueVeo3p1FirstLastFrameImageToVideoDurationSeconds, EnqueueVeo3p1FirstLastFrameImageToVideoResolution};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::{TALL_CORGI_SHIBA_TREASURE_OCEAN_URL, TALL_CORGI_SHIBA_TREASURE_SKY_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 = EnqueueVeo3p1FirstLastFrameImageToVideoArgs {
first_frame_url: TALL_CORGI_SHIBA_TREASURE_OCEAN_URL.to_string(),
last_frame_url: TALL_CORGI_SHIBA_TREASURE_SKY_URL.to_string(),
prompt: "There is a tiny ocean island with a corgi and shiba and treasure chest on it. The corgi and shiba are barking at the chest, when suddenly the island launches itself into the air. The camera tracks the island and follows it up high in the sky. The sun beams over the horizon. The dogs are happy and bark. The gold coins gleam in the sun.".to_string(),
duration: Some(EnqueueVeo3p1FirstLastFrameImageToVideoDurationSeconds::Eight),
aspect_ratio: Some(EnqueueVeo3p1FirstLastFrameImageToVideoAspectRatio::NineBySixteen),
resolution: Some(EnqueueVeo3p1FirstLastFrameImageToVideoResolution::TenEightyP),
generate_audio: Some(true),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_veo_3p1_first_last_frame_image_to_video_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,124 @@
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::veo::veo3_1::veo_3p1_first_frame_image_to_video::{veo_3p1_first_frame_image_to_video, Veo3p1FirstFrameImageToVideoInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueVeo3p1ImageToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
// Starting frame
pub image_url: String,
// Optional args
pub duration: Option<EnqueueVeo3p1ImageToVideoDurationSeconds>,
pub aspect_ratio: Option<EnqueueVeo3p1ImageToVideoAspectRatio>,
pub resolution: Option<EnqueueVeo3p1ImageToVideoResolution>,
pub generate_audio: Option<bool>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1ImageToVideoDurationSeconds {
Four,
Six,
Eight,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1ImageToVideoAspectRatio {
Auto,
Square,
SixteenByNine,
NineBySixteen,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1ImageToVideoResolution {
SevenTwentyP,
TenEightyP,
}
pub async fn enqueue_veo_3p1_image_to_video_webhook<R: IntoUrl>(
args: EnqueueVeo3p1ImageToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let duration = args.duration
.map(|resolution| match resolution {
EnqueueVeo3p1ImageToVideoDurationSeconds::Four => "4s",
EnqueueVeo3p1ImageToVideoDurationSeconds::Six => "6s",
EnqueueVeo3p1ImageToVideoDurationSeconds::Eight=> "8s",
})
.map(|s| s.to_string());
let aspect_ratio = args.aspect_ratio
.map(|aspect_ratio| match aspect_ratio {
EnqueueVeo3p1ImageToVideoAspectRatio::Auto => "auto",
EnqueueVeo3p1ImageToVideoAspectRatio::Square => "1:1",
EnqueueVeo3p1ImageToVideoAspectRatio::SixteenByNine => "16:9",
EnqueueVeo3p1ImageToVideoAspectRatio::NineBySixteen => "9:16",
})
.map(|s| s.to_string());
let resolution = args.resolution
.map(|resolution| match resolution {
EnqueueVeo3p1ImageToVideoResolution::SevenTwentyP => "720p",
EnqueueVeo3p1ImageToVideoResolution::TenEightyP => "1080p",
})
.map(|s| s.to_string());
let request = Veo3p1FirstFrameImageToVideoInput {
prompt: args.prompt,
image_url: args.image_url,
generate_audio: args.generate_audio,
// Optionals
duration,
aspect_ratio,
resolution,
};
let result = veo_3p1_first_frame_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_veo_3p1_image_to_video_webhook::{enqueue_veo_3p1_image_to_video_webhook, EnqueueVeo3p1ImageToVideoArgs, EnqueueVeo3p1ImageToVideoAspectRatio, EnqueueVeo3p1ImageToVideoDurationSeconds, EnqueueVeo3p1ImageToVideoResolution};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::TALL_CORGI_SHIBA_TREASURE_OCEAN_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 = EnqueueVeo3p1ImageToVideoArgs {
image_url: TALL_CORGI_SHIBA_TREASURE_OCEAN_URL.to_string(),
prompt: "There is a tiny ocean island with a corgi and shiba and treasure chest on it. The corgi and shiba are barking at the chest, when suddenly the island launches itself into the air. The camera tracks the island and follows it up high in the sky. The sun beams over the horizon. The dogs are happy and bark. The gold coins gleam in the sun.".to_string(),
duration: Some(EnqueueVeo3p1ImageToVideoDurationSeconds::Eight),
aspect_ratio: Some(EnqueueVeo3p1ImageToVideoAspectRatio::NineBySixteen),
resolution: Some(EnqueueVeo3p1ImageToVideoResolution::TenEightyP),
generate_audio: Some(true),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_veo_3p1_image_to_video_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,12 @@
pub mod enqueue_hailuo_v2p3_fast_pro_image_to_video_webhook;
pub mod enqueue_hailuo_v2p3_pro_image_to_video_webhook;
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_v2p6_pro_image_to_video_webhook;
pub mod enqueue_pixverse_v5_image_to_video_webhook;
pub mod enqueue_sora_2_image_to_video_webhook;
pub mod enqueue_sora_2_pro_image_to_video_webhook;
pub mod enqueue_veo_3p1_fast_first_last_frame_image_to_video_webhook;
pub mod enqueue_veo_3p1_fast_image_to_video_webhook;
pub mod enqueue_veo_3p1_first_last_frame_image_to_video_webhook;
pub mod enqueue_veo_3p1_image_to_video_webhook;
@@ -5,4 +5,6 @@ pub mod enqueue_seedance_1_lite_image_to_video_webhook;
pub mod enqueue_seedance_1_pro_image_to_video_webhook;
pub mod enqueue_veo_2_image_to_video_webhook;
pub mod enqueue_veo_3_fast_image_to_video_webhook;
pub mod enqueue_veo_3_image_to_video_webhook;
pub mod enqueue_veo_3_image_to_video_webhook;
pub mod image;
pub mod text;
@@ -0,0 +1,66 @@
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::minimax::hailuo::hailuo_v2p3_pro_text_to_video::{hailuo_v2p3_pro_text_to_video, HailuoV2p3ProTextToVideoInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueHailuoV2p3ProTextToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
// Optional args
pub prompt_optimizer: Option<bool>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
pub async fn enqueue_hailuo_v2p3_pro_text_to_video_webhook<R: IntoUrl>(
args: EnqueueHailuoV2p3ProTextToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let prompt_optimizer = args.prompt_optimizer.unwrap_or(true);
let request = HailuoV2p3ProTextToVideoInput {
prompt: args.prompt,
// Optionals
prompt_optimizer: Some(prompt_optimizer),
};
let result = hailuo_v2p3_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 crate::requests::webhook::video::text::enqueue_hailuo_v2p3_pro_text_to_video_webhook::{enqueue_hailuo_v2p3_pro_text_to_video_webhook, EnqueueHailuoV2p3ProTextToVideoArgs};
use errors::AnyhowResult;
use std::fs::read_to_string;
#[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 = EnqueueHailuoV2p3ProTextToVideoArgs {
prompt: "a gray alien with big eyes dressed in an american flag tank top gives the peace symbol, it then barbecues some hot dogs on the grill".to_string(),
prompt_optimizer: Some(true),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_hailuo_v2p3_pro_text_to_video_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,100 @@
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_5::kling_v2p5_turbo_pro_text_to_video::{kling_v2p5_turbo_pro_text_to_video, KlingV2p5TurboProTextToVideoInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueKlingV2p5TurboProTextToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
// Optional args
pub negative_prompt: Option<String>,
pub duration: Option<EnqueueKlingV2p5TurboProTextToVideoDurationSeconds>,
pub aspect_ratio: Option<EnqueueKlingV2p5TurboProTextToVideoAspectRatio>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueKlingV2p5TurboProTextToVideoDurationSeconds {
Five,
Ten,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueKlingV2p5TurboProTextToVideoAspectRatio {
Square,
SixteenByNine,
NineBySixteen,
}
pub async fn enqueue_kling_v2p5_turbo_pro_text_to_video_webhook<R: IntoUrl>(
args: EnqueueKlingV2p5TurboProTextToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let duration = args.duration
.map(|resolution| match resolution {
EnqueueKlingV2p5TurboProTextToVideoDurationSeconds::Five => "5",
EnqueueKlingV2p5TurboProTextToVideoDurationSeconds::Ten => "10",
})
.map(|s| s.to_string());
let aspect_ratio = args.aspect_ratio
.map(|aspect| match aspect {
EnqueueKlingV2p5TurboProTextToVideoAspectRatio::Square => "1:1",
EnqueueKlingV2p5TurboProTextToVideoAspectRatio::SixteenByNine => "16:9",
EnqueueKlingV2p5TurboProTextToVideoAspectRatio::NineBySixteen => "9:16",
})
.map(|s| s.to_string());
let request = KlingV2p5TurboProTextToVideoInput {
prompt: args.prompt,
// Optionals
duration,
aspect_ratio,
negative_prompt: args.negative_prompt,
// Constants
cfg_scale: None,
};
let result = kling_v2p5_turbo_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 crate::requests::webhook::video::text::enqueue_kling_v2p5_turbo_pro_text_to_video_webhook::{enqueue_kling_v2p5_turbo_pro_text_to_video_webhook, EnqueueKlingV2p5TurboProTextToVideoArgs, EnqueueKlingV2p5TurboProTextToVideoAspectRatio, EnqueueKlingV2p5TurboProTextToVideoDurationSeconds};
use errors::AnyhowResult;
use std::fs::read_to_string;
#[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 = EnqueueKlingV2p5TurboProTextToVideoArgs {
prompt: "an owl flies by an abandoned castle at dusk. the camera tracks the flying owl. the castle stones are damp and gritty. there are lots of trees. fireflies dance over the fields".to_string(),
negative_prompt: None,
aspect_ratio: Some(EnqueueKlingV2p5TurboProTextToVideoAspectRatio::SixteenByNine),
duration: Some(EnqueueKlingV2p5TurboProTextToVideoDurationSeconds::Five),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_kling_v2p5_turbo_pro_text_to_video_webhook(args).await?;
Ok(())
}
}
@@ -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(())
}
}
@@ -0,0 +1,148 @@
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::pixverse::v5::pixverse_v5_text_to_video::{pixverse_v5_text_to_video, PixverseV5TextToVideoInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueuePixverseV5TextToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
// Optional args
pub negative_prompt: Option<String>,
// NB: eight-second videos do not work with 1080P
pub duration: Option<EnqueuePixverseV5TextToVideoDurationSeconds>,
pub aspect_ratio: Option<EnqueuePixverseV5TextToVideoAspectRatio>,
pub resolution: Option<EnqueuePixverseV5TextToVideoResolution>,
pub style: Option<EnqueuePixverseV5TextToVideoStyle>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueuePixverseV5TextToVideoDurationSeconds {
Five,
Eight,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueuePixverseV5TextToVideoResolution {
ThreeSixtyP,
FiveFortyP,
SevenTwentyP,
TenEightyP,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueuePixverseV5TextToVideoAspectRatio {
Square,
SixteenByNine,
FourByThree,
NineBySixteen,
ThreeByFour,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueuePixverseV5TextToVideoStyle {
Anime,
Animation3d,
Clay,
Comic,
Cyberpunk,
}
pub async fn enqueue_pixverse_v5_text_to_video_webhook<R: IntoUrl>(
args: EnqueuePixverseV5TextToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let duration = args.duration
.map(|resolution| match resolution {
EnqueuePixverseV5TextToVideoDurationSeconds::Five => "5",
EnqueuePixverseV5TextToVideoDurationSeconds::Eight=> "8",
})
.map(|s| s.to_string());
let aspect_ratio = args.aspect_ratio
.map(|aspect_ratio| match aspect_ratio {
EnqueuePixverseV5TextToVideoAspectRatio::Square => "1:1",
EnqueuePixverseV5TextToVideoAspectRatio::SixteenByNine => "16:9",
EnqueuePixverseV5TextToVideoAspectRatio::FourByThree => "4:3",
EnqueuePixverseV5TextToVideoAspectRatio::NineBySixteen => "9:16",
EnqueuePixverseV5TextToVideoAspectRatio::ThreeByFour => "3:4",
})
.map(|s| s.to_string());
let resolution = args.resolution
.map(|resolution| match resolution {
EnqueuePixverseV5TextToVideoResolution::ThreeSixtyP => "360p",
EnqueuePixverseV5TextToVideoResolution::FiveFortyP => "540p",
EnqueuePixverseV5TextToVideoResolution::SevenTwentyP => "720p",
EnqueuePixverseV5TextToVideoResolution::TenEightyP => "1080p",
})
.map(|s| s.to_string());
let style = args.style
.map(|style| match style {
EnqueuePixverseV5TextToVideoStyle::Anime => "anime",
EnqueuePixverseV5TextToVideoStyle::Animation3d => "3d_animation",
EnqueuePixverseV5TextToVideoStyle::Clay => "clay",
EnqueuePixverseV5TextToVideoStyle::Comic => "comic",
EnqueuePixverseV5TextToVideoStyle::Cyberpunk => "cyberpunk",
})
.map(|s| s.to_string());
let request = PixverseV5TextToVideoInput {
prompt: args.prompt,
// Optionals
duration,
negative_prompt: args.negative_prompt,
aspect_ratio,
resolution,
style,
// Constant
seed: None,
};
let result = pixverse_v5_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 crate::requests::webhook::video::text::enqueue_pixverse_v5_text_to_video_webhook::{enqueue_pixverse_v5_text_to_video_webhook, EnqueuePixverseV5TextToVideoArgs, EnqueuePixverseV5TextToVideoAspectRatio, EnqueuePixverseV5TextToVideoDurationSeconds, EnqueuePixverseV5TextToVideoResolution, EnqueuePixverseV5TextToVideoStyle};
use errors::AnyhowResult;
use std::fs::read_to_string;
#[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 = EnqueuePixverseV5TextToVideoArgs {
prompt: "an angry racoon shakes its fist at the garbage truck as it drives away, the camera orbits the racoon. the racoon sighs".to_string(),
negative_prompt: None,
duration: Some(EnqueuePixverseV5TextToVideoDurationSeconds::Eight),
style: Some(EnqueuePixverseV5TextToVideoStyle::Anime),
aspect_ratio: Some(EnqueuePixverseV5TextToVideoAspectRatio::FourByThree),
resolution: Some(EnqueuePixverseV5TextToVideoResolution::SevenTwentyP),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_pixverse_v5_text_to_video_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,116 @@
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::webhook::WebhookResponse;
use reqwest::IntoUrl;
use fal::endpoints::fal_ai::sora::sora2::sora_2_pro_text_to_video::{sora_2_pro_text_to_video, Sora2ProTextToVideoInput};
pub struct EnqueueSora2ProTextToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
// Optional args
pub resolution: Option<EnqueueSora2ProTextToVideoResolution>,
pub duration: Option<EnqueueSora2ProTextToVideoDurationSeconds>,
pub aspect_ratio: Option<EnqueueSora2ProTextToVideoAspectRatio>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueSora2ProTextToVideoDurationSeconds {
Four,
Eight,
Twelve,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueSora2ProTextToVideoResolution {
Auto,
SevenTwentyP,
TenEightyP,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueSora2ProTextToVideoAspectRatio {
Auto,
NineBySixteen,
SixteenByNine,
}
pub async fn enqueue_sora_2_pro_text_to_video_webhook<R: IntoUrl>(
args: EnqueueSora2ProTextToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let duration = args.duration
.map(|resolution| match resolution {
EnqueueSora2ProTextToVideoDurationSeconds::Four => 4,
EnqueueSora2ProTextToVideoDurationSeconds::Eight => 8,
EnqueueSora2ProTextToVideoDurationSeconds::Twelve => 12,
});
let resolution = args.resolution
.map(|resolution| match resolution {
EnqueueSora2ProTextToVideoResolution::Auto => "auto",
EnqueueSora2ProTextToVideoResolution::SevenTwentyP => "720p",
EnqueueSora2ProTextToVideoResolution::TenEightyP => "1080p",
})
.map(|resolution| resolution.to_string());
let aspect_ratio = args.aspect_ratio
.map(|aspect_ratio| match aspect_ratio {
EnqueueSora2ProTextToVideoAspectRatio::Auto => "auto",
EnqueueSora2ProTextToVideoAspectRatio::NineBySixteen => "9:16",
EnqueueSora2ProTextToVideoAspectRatio::SixteenByNine => "16:9",
})
.map(|resolution| resolution.to_string());
let request = Sora2ProTextToVideoInput {
prompt: args.prompt,
// Optionals
duration,
resolution,
aspect_ratio,
// Constants
delete_video: Some(false),
};
let result = sora_2_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_sora_2_pro_text_to_video_webhook::{enqueue_sora_2_pro_text_to_video_webhook, EnqueueSora2ProTextToVideoArgs, EnqueueSora2ProTextToVideoAspectRatio, EnqueueSora2ProTextToVideoDurationSeconds, EnqueueSora2ProTextToVideoResolution};
#[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 = EnqueueSora2ProTextToVideoArgs {
prompt: "a dinosaur turns to the camera and asks, 'do you have adequate car insurance?' it then stomps off and attacks a brontosaurus".to_string(),
duration: Some(EnqueueSora2ProTextToVideoDurationSeconds::Eight),
aspect_ratio: Some(EnqueueSora2ProTextToVideoAspectRatio::NineBySixteen),
resolution: Some(EnqueueSora2ProTextToVideoResolution::SevenTwentyP),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_sora_2_pro_text_to_video_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,114 @@
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::sora::sora2::sora_2_text_to_video::{sora_2_text_to_video, Sora2TextToVideoInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueSora2TextToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
// Optional args
pub resolution: Option<EnqueueSora2TextToVideoResolution>,
pub duration: Option<EnqueueSora2TextToVideoDurationSeconds>,
pub aspect_ratio: Option<EnqueueSora2TextToVideoAspectRatio>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueSora2TextToVideoDurationSeconds {
Four,
Eight,
Twelve,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueSora2TextToVideoResolution {
Auto,
SevenTwentyP,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueSora2TextToVideoAspectRatio {
Auto,
NineBySixteen,
SixteenByNine,
}
pub async fn enqueue_sora_2_text_to_video_webhook<R: IntoUrl>(
args: EnqueueSora2TextToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let duration = args.duration
.map(|resolution| match resolution {
EnqueueSora2TextToVideoDurationSeconds::Four => 4,
EnqueueSora2TextToVideoDurationSeconds::Eight => 8,
EnqueueSora2TextToVideoDurationSeconds::Twelve => 12,
});
let resolution = args.resolution
.map(|resolution| match resolution {
EnqueueSora2TextToVideoResolution::Auto => "auto",
EnqueueSora2TextToVideoResolution::SevenTwentyP => "720p",
})
.map(|resolution| resolution.to_string());
let aspect_ratio = args.aspect_ratio
.map(|aspect_ratio| match aspect_ratio {
EnqueueSora2TextToVideoAspectRatio::Auto => "auto",
EnqueueSora2TextToVideoAspectRatio::NineBySixteen => "9:16",
EnqueueSora2TextToVideoAspectRatio::SixteenByNine => "16:9",
})
.map(|resolution| resolution.to_string());
let request = Sora2TextToVideoInput {
prompt: args.prompt,
// Optionals
duration,
resolution,
aspect_ratio,
// Constants
delete_video: Some(false),
};
let result = sora_2_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 crate::requests::webhook::video::text::enqueue_sora_2_text_to_video_webhook::{enqueue_sora_2_text_to_video_webhook, EnqueueSora2TextToVideoArgs, EnqueueSora2TextToVideoAspectRatio, EnqueueSora2TextToVideoDurationSeconds, EnqueueSora2TextToVideoResolution};
use errors::AnyhowResult;
use std::fs::read_to_string;
#[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 = EnqueueSora2TextToVideoArgs {
prompt: "a dinosaur turns to the camera and asks, 'do you have adequate car insurance?' it then stomps off and attacks a brontosaurus".to_string(),
duration: Some(EnqueueSora2TextToVideoDurationSeconds::Eight),
aspect_ratio: Some(EnqueueSora2TextToVideoAspectRatio::NineBySixteen),
resolution: Some(EnqueueSora2TextToVideoResolution::SevenTwentyP),
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_sora_2_text_to_video_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,130 @@
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::veo::veo3_1::veo_3p1_fast_text_to_video::{veo_3p1_fast_text_to_video, Veo3p1FastTextToVideoInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueVeo3p1FastTextToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
// Optional args
pub duration: Option<EnqueueVeo3p1FastTextToVideoDurationSeconds>,
pub aspect_ratio: Option<EnqueueVeo3p1FastTextToVideoAspectRatio>,
pub resolution: Option<EnqueueVeo3p1FastTextToVideoResolution>,
pub generate_audio: Option<bool>,
pub enhance_prompt: Option<bool>,
pub negative_prompt: Option<String>,
pub seed: Option<i64>,
pub auto_fix: Option<bool>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1FastTextToVideoDurationSeconds {
Four,
Six,
Eight,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1FastTextToVideoAspectRatio {
Auto,
Square,
SixteenByNine,
NineBySixteen,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1FastTextToVideoResolution {
SevenTwentyP,
TenEightyP,
}
pub async fn enqueue_veo_3p1_fast_text_to_video_webhook<R: IntoUrl>(
args: EnqueueVeo3p1FastTextToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let duration = args.duration
.map(|resolution| match resolution {
EnqueueVeo3p1FastTextToVideoDurationSeconds::Four => "4s",
EnqueueVeo3p1FastTextToVideoDurationSeconds::Six => "6s",
EnqueueVeo3p1FastTextToVideoDurationSeconds::Eight=> "8s",
})
.map(|s| s.to_string());
let aspect_ratio = args.aspect_ratio
.map(|aspect_ratio| match aspect_ratio {
EnqueueVeo3p1FastTextToVideoAspectRatio::Auto => "auto",
EnqueueVeo3p1FastTextToVideoAspectRatio::Square => "1:1",
EnqueueVeo3p1FastTextToVideoAspectRatio::SixteenByNine => "16:9",
EnqueueVeo3p1FastTextToVideoAspectRatio::NineBySixteen => "9:16",
})
.map(|s| s.to_string());
let resolution = args.resolution
.map(|resolution| match resolution {
EnqueueVeo3p1FastTextToVideoResolution::SevenTwentyP => "720p",
EnqueueVeo3p1FastTextToVideoResolution::TenEightyP => "1080p",
})
.map(|s| s.to_string());
let request = Veo3p1FastTextToVideoInput {
prompt: args.prompt,
// Optionals
duration,
aspect_ratio,
resolution,
negative_prompt: args.negative_prompt,
generate_audio: args.generate_audio,
enhance_prompt: args.enhance_prompt,
seed: args.seed,
auto_fix: args.auto_fix,
};
let result = veo_3p1_fast_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 crate::requests::webhook::video::text::enqueue_veo_3p1_fast_text_to_video_webhook::{enqueue_veo_3p1_fast_text_to_video_webhook, EnqueueVeo3p1FastTextToVideoArgs, EnqueueVeo3p1FastTextToVideoAspectRatio, EnqueueVeo3p1FastTextToVideoDurationSeconds, EnqueueVeo3p1FastTextToVideoResolution};
use errors::AnyhowResult;
use std::fs::read_to_string;
#[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 = EnqueueVeo3p1FastTextToVideoArgs {
prompt: "An alien space ship hovers over new york city. it looks ominous, ready to attack. suddenly, it drops a bunch of ping pong balls on the city".to_string(),
duration: Some(EnqueueVeo3p1FastTextToVideoDurationSeconds::Eight),
aspect_ratio: Some(EnqueueVeo3p1FastTextToVideoAspectRatio::SixteenByNine),
resolution: Some(EnqueueVeo3p1FastTextToVideoResolution::TenEightyP),
generate_audio: Some(true),
negative_prompt: None,
enhance_prompt: Some(true),
auto_fix: Some(true),
seed: None,
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_veo_3p1_fast_text_to_video_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,130 @@
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::veo::veo3_1::veo_3p1_text_to_video::{veo_3p1_text_to_video, Veo3p1TextToVideoInput};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueVeo3p1TextToVideoArgs<'a, R: IntoUrl> {
// Request required
pub prompt: String,
// Optional args
pub duration: Option<EnqueueVeo3p1TextToVideoDurationSeconds>,
pub aspect_ratio: Option<EnqueueVeo3p1TextToVideoAspectRatio>,
pub resolution: Option<EnqueueVeo3p1TextToVideoResolution>,
pub generate_audio: Option<bool>,
pub enhance_prompt: Option<bool>,
pub negative_prompt: Option<String>,
pub seed: Option<i64>,
pub auto_fix: Option<bool>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1TextToVideoDurationSeconds {
Four,
Six,
Eight,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1TextToVideoAspectRatio {
Auto,
Square,
SixteenByNine,
NineBySixteen,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueVeo3p1TextToVideoResolution {
SevenTwentyP,
TenEightyP,
}
pub async fn enqueue_veo_3p1_text_to_video_webhook<R: IntoUrl>(
args: EnqueueVeo3p1TextToVideoArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let duration = args.duration
.map(|resolution| match resolution {
EnqueueVeo3p1TextToVideoDurationSeconds::Four => "4s",
EnqueueVeo3p1TextToVideoDurationSeconds::Six => "6s",
EnqueueVeo3p1TextToVideoDurationSeconds::Eight=> "8s",
})
.map(|s| s.to_string());
let aspect_ratio = args.aspect_ratio
.map(|aspect_ratio| match aspect_ratio {
EnqueueVeo3p1TextToVideoAspectRatio::Auto => "auto",
EnqueueVeo3p1TextToVideoAspectRatio::Square => "1:1",
EnqueueVeo3p1TextToVideoAspectRatio::SixteenByNine => "16:9",
EnqueueVeo3p1TextToVideoAspectRatio::NineBySixteen => "9:16",
})
.map(|s| s.to_string());
let resolution = args.resolution
.map(|resolution| match resolution {
EnqueueVeo3p1TextToVideoResolution::SevenTwentyP => "720p",
EnqueueVeo3p1TextToVideoResolution::TenEightyP => "1080p",
})
.map(|s| s.to_string());
let request = Veo3p1TextToVideoInput {
prompt: args.prompt,
// Optionals
duration,
aspect_ratio,
resolution,
negative_prompt: args.negative_prompt,
generate_audio: args.generate_audio,
enhance_prompt: args.enhance_prompt,
seed: args.seed,
auto_fix: args.auto_fix,
};
let result = veo_3p1_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 crate::requests::webhook::video::text::enqueue_veo_3p1_text_to_video_webhook::{enqueue_veo_3p1_text_to_video_webhook, EnqueueVeo3p1TextToVideoArgs, EnqueueVeo3p1TextToVideoAspectRatio, EnqueueVeo3p1TextToVideoDurationSeconds, EnqueueVeo3p1TextToVideoResolution};
use errors::AnyhowResult;
use std::fs::read_to_string;
#[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 = EnqueueVeo3p1TextToVideoArgs {
prompt: "An alien space ship hovers over new york city. it looks ominous, ready to attack. suddenly, it drops a bunch of ping pong balls on the city".to_string(),
duration: Some(EnqueueVeo3p1TextToVideoDurationSeconds::Eight),
aspect_ratio: Some(EnqueueVeo3p1TextToVideoAspectRatio::SixteenByNine),
resolution: Some(EnqueueVeo3p1TextToVideoResolution::TenEightyP),
generate_audio: Some(true),
negative_prompt: None,
enhance_prompt: Some(true),
auto_fix: Some(true),
seed: None,
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_veo_3p1_text_to_video_webhook(args).await?;
Ok(())
}
}
@@ -0,0 +1,8 @@
pub mod enqueue_hailuo_v2p3_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;
pub mod enqueue_pixverse_v5_text_to_video_webhook;
pub mod enqueue_sora_2_pro_text_to_video_webhook;
pub mod enqueue_sora_2_text_to_video_webhook;
pub mod enqueue_veo_3p1_fast_text_to_video_webhook;
pub mod enqueue_veo_3p1_text_to_video_webhook;
@@ -1,6 +1,7 @@
pub mod aspect_ratio;
pub mod baggage;
pub mod file_id;
pub mod video_generation_mode;
pub mod post_id;
pub mod request_id;
pub mod sentry_trace;
@@ -0,0 +1,27 @@
/// The video generation mode selector.
#[derive(Copy, Clone, Debug)]
pub enum VideoGenerationMode {
/// Supposedly the "NSFW" mode.
Spicy,
Fun,
Normal,
/// This might be the only mode that allows for a custom text prompt
Custom,
}
impl VideoGenerationMode {
/// This is the value for `--mode` in video generation chats.
pub fn as_api_mode_arg(&self) -> &'static str {
match self {
Self::Spicy => "extremely-spicy-or-crazy",
Self::Fun => "extremely-crazy",
Self::Normal => "normal",
Self::Custom => "custom",
}
}
}
@@ -92,6 +92,8 @@ mod tests {
cookies: cookies.as_str(),
}).await?;
let prompt = "A dinosaur on stilts walking on the beach";
//let websocket = GrokWrappedWebsocket::new(websocket);
let mut websocket = GrokWebsocket::new(websocket);
@@ -106,7 +108,7 @@ mod tests {
let result = prompt_websocket_image_with_retry(PromptWebsocketImageWithRetryArgs {
websocket: &mut websocket,
prompt: "a dog riding a motorcycle",
prompt,
aspect_ratio: ClientMessageAspectRatio::WideThreeByTwo,
cookies: &cookies,
}).await?;
@@ -152,9 +154,19 @@ mod tests {
match message {
WebsocketServerMessage::Image(image) => {
println!("IMAGE: {:?}", image.percentage_complete);
if let Some(percent) = image.percentage_complete {
if percent > 90.0 {
println!("Image: {:?}", image);
}
}
}
WebsocketServerMessage::Json(json) => {
println!("JSON : {:?}", json.percentage_complete);
if let Some(percent) = json.percentage_complete {
if percent > 90.0 {
println!("Image: {:?}", json);
}
}
}
WebsocketServerMessage::Unknown(unknown) => {
//let typ = unknown.get("type");
@@ -2,6 +2,7 @@ use crate::credentials::grok_full_credentials::GrokFullCredentials;
use crate::datatypes::api::aspect_ratio::AspectRatio;
use crate::datatypes::api::file_id::FileId;
use crate::datatypes::api::post_id::PostId;
use crate::datatypes::api::video_generation_mode::VideoGenerationMode;
use crate::datatypes::file_upload_spec::FileUploadSpec;
use crate::error::grok_error::GrokError;
use crate::error::grok_generic_api_error::GrokGenericApiError;
@@ -27,6 +28,9 @@ pub struct UploadImageAndGenerateVideo<'a, P: AsRef<Path>> {
/// Aspect ratio for the video.
pub aspect_ratio: Option<AspectRatio>,
/// Mode to generate the video: normal, fun, spicy, etc.
pub mode: Option<VideoGenerationMode>,
/// Wait for the full video to be generated before returning
/// By default, the endpoint stays open for 30-ish seconds while
/// the video generates and streams back JSON progress updates.
@@ -116,6 +120,7 @@ pub async fn upload_image_and_generate_video<P: AsRef<Path>>(args: UploadImageAn
media_type: VideoMediaPostType::UserUploadedImage,
cookie: args.full_credentials.cookies.as_str(),
prompt: args.prompt,
mode: args.mode,
aspect_ratio: args.aspect_ratio,
request_timeout: args.individual_request_timeout,
baggage: &args.full_credentials.client_secrets.baggage,
@@ -178,6 +183,7 @@ pub async fn upload_image_and_generate_video<P: AsRef<Path>>(args: UploadImageAn
#[cfg(test)]
mod tests {
use crate::credentials::grok_full_credentials::GrokFullCredentials;
use crate::datatypes::api::aspect_ratio::AspectRatio;
use crate::datatypes::file_upload_spec::FileUploadSpec;
use crate::recipes::request_client_secrets::{request_client_secrets, RequestClientSecretsArgs};
use crate::recipes::upload_image_and_generate_video::{upload_image_and_generate_video, UploadImageAndGenerateVideo};
@@ -185,7 +191,6 @@ mod tests {
use crate::test_utils::setup_test_logging::setup_test_logging;
use errors::AnyhowResult;
use log::LevelFilter;
use crate::datatypes::api::aspect_ratio::AspectRatio;
// Result: GrokUploadFileResponse { file_metadata_id:
// Some("acdee48f-9d6f-4bc6-9d06-fcc97dd4418a"), file_uri:
// Some("users/85980643-ffab-4984-a3de-59a608c47d7f/acdee48f-9d6f-4bc6-9d06-fcc97dd4418a/content") }
@@ -220,6 +225,7 @@ mod tests {
file: FileUploadSpec::Path(image_path),
prompt: maybe_prompt,
aspect_ratio: Some(AspectRatio::Square),
mode: None,
individual_request_timeout: None,
wait_for_generation: false,
}).await?;
@@ -1,6 +1,7 @@
use crate::credentials::grok_client_secrets::GrokClientSecrets;
use crate::credentials::grok_full_credentials::GrokFullCredentials;
use crate::datatypes::api::aspect_ratio::AspectRatio;
use crate::datatypes::api::video_generation_mode::VideoGenerationMode;
use crate::datatypes::file_upload_spec::FileUploadSpec;
use crate::error::grok_client_error::GrokClientError;
use crate::error::grok_error::GrokError;
@@ -30,6 +31,9 @@ pub struct UploadImageAndGenerateVideoWithRetry<'a, P: AsRef<Path>> {
/// Aspect ratio for the video.
pub aspect_ratio: Option<AspectRatio>,
/// Mode to generate the video: normal, fun, spicy, etc.
pub mode: Option<VideoGenerationMode>,
/// Wait for the full video to be generated before returning
/// By default, the endpoint stays open for 30-ish seconds while
/// the video generates and streams back JSON progress updates.
@@ -116,6 +120,7 @@ pub async fn upload_image_and_generate_video_with_retry<P: AsRef<Path>>(
media_type: VideoMediaPostType::UserUploadedImage,
cookie: current_full_credentials_ref.cookies.as_str(),
prompt: args.prompt,
mode: args.mode,
aspect_ratio: args.aspect_ratio,
request_timeout: args.individual_request_timeout,
baggage: &current_full_credentials_ref.client_secrets.baggage,
@@ -271,6 +276,7 @@ pub async fn upload_image_and_generate_video_with_retry<P: AsRef<Path>>(
mod tests {
use crate::credentials::grok_full_credentials::GrokFullCredentials;
use crate::datatypes::api::aspect_ratio::AspectRatio;
use crate::datatypes::api::video_generation_mode::VideoGenerationMode;
use crate::datatypes::file_upload_spec::FileUploadSpec;
use crate::recipes::request_client_secrets::{request_client_secrets, RequestClientSecretsArgs};
use crate::recipes::upload_image_and_generate_video_with_retry::{upload_image_and_generate_video_with_retry, UploadImageAndGenerateVideoWithRetry};
@@ -310,7 +316,8 @@ mod tests {
credentials: &credentials,
file: FileUploadSpec::Path(image_path),
prompt: maybe_prompt,
aspect_ratio: Some(AspectRatio::Square),
mode: Some(VideoGenerationMode::Custom),
aspect_ratio: Some(AspectRatio::TallTwoByThree),
individual_request_timeout: None,
wait_for_generation: false,
}).await?;
@@ -0,0 +1,45 @@
curl 'https://grok.com/rest/app-chat/conversations/new' \
-H 'accept: */*' \
-H 'accept-language: en-US,en;q=0.9' \
-H 'baggage: sentry-environment=production,sentry-public_key=b311e0f2690c81f25e2c4cf6d4f7ce1c,sentry-trace_id=7798e88fd61243ba8985ca9f589f5113,sentry-org_id=4508179396558848,sentry-transaction=%2F%3Aslug*%3F,sentry-sampled=false,sentry-sample_rand=0.01740155041905489,sentry-sample_rate=0' \
-H 'cache-control: no-cache' \
-H 'content-type: application/json' \
-b '_ga=GA1.1.1232202746.1760710013; i18nextLng=en; sso=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiOGU3MDFiNzctOTdkNC00ZjM0LWExOTctOWFmMDU1MzY3NDAwIn0.-a6x0InxbGzfTVfUlrdzxskxCnvMDI8lC90z4wHeGIk; sso-rw=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiOGU3MDFiNzctOTdkNC00ZjM0LWExOTctOWFmMDU1MzY3NDAwIn0.-a6x0InxbGzfTVfUlrdzxskxCnvMDI8lC90z4wHeGIk; stblid=b3331fc1-45d7-466b-83df-67427c0b2367; x-userid=85980643-ffab-4984-a3de-59a608c47d7f; mp_ea93da913ddb66b6372b89d97b1029ac_mixpanel=%7B%22distinct_id%22%3A%2285980643-ffab-4984-a3de-59a608c47d7f%22%2C%22%24device_id%22%3A%2279ce237a-a0f3-4913-bf4b-519ac8a98263%22%2C%22%24initial_referrer%22%3A%22%24direct%22%2C%22%24initial_referring_domain%22%3A%22%24direct%22%2C%22__mps%22%3A%7B%7D%2C%22__mpso%22%3A%7B%7D%2C%22__mpus%22%3A%7B%7D%2C%22__mpa%22%3A%7B%7D%2C%22__mpu%22%3A%7B%7D%2C%22__mpr%22%3A%5B%5D%2C%22__mpap%22%3A%5B%5D%2C%22%24user_id%22%3A%2285980643-ffab-4984-a3de-59a608c47d7f%22%7D; cf_clearance=5QPOzLWH8eEniaDlJR23k9VB4XjRPHdR.kfVR15BRkI-1764645588-1.2.1.1-WBy8wpvS9.Q.ofWBIMTLHDrKRIPt0Xrn5kAQ6I7xf4u0JSbB.E4CRd.fK6kEZo8OTXMAdt.F0YkoLJzB0TufxM79dMu63TKLmorKB.gSgUWJcea1eQcLJ1WG80uhv4VCMrSJ_HHAaq6fqiNNvS7pArgMT4tvoaQXShfDuV8ivYsRp31LYMgNnRFdtiCiJ5mxhf7uUMpSS_UbvCSaYe7CysUr472alMjEYUd.QhKpb8E; _ga_8FEWB057YH=GS2.1.s1764645588$o22$g1$t1764646543$j57$l0$h0' \
-H 'origin: https://grok.com' \
-H 'pragma: no-cache' \
-H 'priority: u=1, i' \
-H 'referer: https://grok.com/imagine/post/463eb5f6-7485-495a-a344-70ab4fe454a9' \
-H 'sec-ch-ua: "Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "macOS"' \
-H 'sec-fetch-dest: empty' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-site: same-origin' \
-H 'sentry-trace: 7798e88fd61243ba8985ca9f589f5113-889cac2356ac270b-0' \
-H 'traceparent: 00-9698441276035e5f4414a5c7b7cde4e7-043b158b0070e175-00' \
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36' \
-H 'x-statsig-id: eVTlFkyAcCo5RWxUQOUfzewYmzWMb/GbAFj4n2ymSal+UQwbGGxtFMSDrd+DdsVB0EaFp33Dd+aDMEmMn9Ay0MCCa8Bqeg' \
-H 'x-xai-request-id: ac5e2fc3-daed-4967-a9ff-1d12b60ee0e1' \
--data-raw '{"temporary":true,"modelName":"grok-3","message":"https://imagine-public.x.ai/imagine-public/images/463eb5f6-7485-495a-a344-70ab4fe454a9.png --mode=extremely-crazy","toolOverrides":{"videoGen":true},"responseMetadata":{"modelConfigOverride":{"modelMap":{"videoGenModelConfig":{"parentPostId":"463eb5f6-7485-495a-a344-70ab4fe454a9","aspectRatio":"2:3","videoLength":6}}}}}'
--data-raw
{
"temporary":true,
"modelName":"grok-3",
"message":"https://imagine-public.x.ai/imagine-public/images/463eb5f6-7485-495a-a344-70ab4fe454a9.png --mode=extremely-crazy",
"toolOverrides": {
"videoGen":true
},
"responseMetadata": {
"modelConfigOverride": {
"modelMap": {
"videoGenModelConfig": {
"parentPostId":"463eb5f6-7485-495a-a344-70ab4fe454a9",
"aspectRatio": "2:3",
"videoLength":6
}
}
}
}
}
@@ -0,0 +1,23 @@
curl 'https://grok.com/rest/app-chat/conversations/new' \
-H 'accept: */*' \
-H 'accept-language: en-US,en;q=0.9' \
-H 'baggage: sentry-environment=production,sentry-public_key=b311e0f2690c81f25e2c4cf6d4f7ce1c,sentry-trace_id=7798e88fd61243ba8985ca9f589f5113,sentry-org_id=4508179396558848,sentry-transaction=%2F%3Aslug*%3F,sentry-sampled=false,sentry-sample_rand=0.01740155041905489,sentry-sample_rate=0' \
-H 'cache-control: no-cache' \
-H 'content-type: application/json' \
-b '_ga=GA1.1.1232202746.1760710013; i18nextLng=en; sso=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiOGU3MDFiNzctOTdkNC00ZjM0LWExOTctOWFmMDU1MzY3NDAwIn0.-a6x0InxbGzfTVfUlrdzxskxCnvMDI8lC90z4wHeGIk; sso-rw=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiOGU3MDFiNzctOTdkNC00ZjM0LWExOTctOWFmMDU1MzY3NDAwIn0.-a6x0InxbGzfTVfUlrdzxskxCnvMDI8lC90z4wHeGIk; stblid=b3331fc1-45d7-466b-83df-67427c0b2367; x-userid=85980643-ffab-4984-a3de-59a608c47d7f; mp_ea93da913ddb66b6372b89d97b1029ac_mixpanel=%7B%22distinct_id%22%3A%2285980643-ffab-4984-a3de-59a608c47d7f%22%2C%22%24device_id%22%3A%2279ce237a-a0f3-4913-bf4b-519ac8a98263%22%2C%22%24initial_referrer%22%3A%22%24direct%22%2C%22%24initial_referring_domain%22%3A%22%24direct%22%2C%22__mps%22%3A%7B%7D%2C%22__mpso%22%3A%7B%7D%2C%22__mpus%22%3A%7B%7D%2C%22__mpa%22%3A%7B%7D%2C%22__mpu%22%3A%7B%7D%2C%22__mpr%22%3A%5B%5D%2C%22__mpap%22%3A%5B%5D%2C%22%24user_id%22%3A%2285980643-ffab-4984-a3de-59a608c47d7f%22%7D; cf_clearance=5QPOzLWH8eEniaDlJR23k9VB4XjRPHdR.kfVR15BRkI-1764645588-1.2.1.1-WBy8wpvS9.Q.ofWBIMTLHDrKRIPt0Xrn5kAQ6I7xf4u0JSbB.E4CRd.fK6kEZo8OTXMAdt.F0YkoLJzB0TufxM79dMu63TKLmorKB.gSgUWJcea1eQcLJ1WG80uhv4VCMrSJ_HHAaq6fqiNNvS7pArgMT4tvoaQXShfDuV8ivYsRp31LYMgNnRFdtiCiJ5mxhf7uUMpSS_UbvCSaYe7CysUr472alMjEYUd.QhKpb8E; _ga_8FEWB057YH=GS2.1.s1764645588$o22$g1$t1764646543$j57$l0$h0' \
-H 'origin: https://grok.com' \
-H 'pragma: no-cache' \
-H 'priority: u=1, i' \
-H 'referer: https://grok.com/imagine/post/463eb5f6-7485-495a-a344-70ab4fe454a9' \
-H 'sec-ch-ua: "Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "macOS"' \
-H 'sec-fetch-dest: empty' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-site: same-origin' \
-H 'sentry-trace: 7798e88fd61243ba8985ca9f589f5113-ac16ba34e7a9e3c2-0' \
-H 'traceparent: 00-017b734e99d0585d4e05bf0376ef9ffb-c5854dfb0968df83-00' \
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36' \
-H 'x-statsig-id: 8dxtnsQI+KKxzeTcyG2XRWSQE70E53kTiNBwF+QuwSH22YSTkOTlnEwLJVcL/k3JWIkNL/XNm7U/U87VShlyvfCIJ01k8g' \
-H 'x-xai-request-id: c2eab60f-859f-4963-8ef8-b5eefaaf5966' \
--data-raw '{"temporary":true,"modelName":"grok-3","message":"https://imagine-public.x.ai/imagine-public/images/463eb5f6-7485-495a-a344-70ab4fe454a9.png --mode=normal","toolOverrides":{"videoGen":true},"responseMetadata":{"modelConfigOverride":{"modelMap":{"videoGenModelConfig":{"parentPostId":"463eb5f6-7485-495a-a344-70ab4fe454a9","aspectRatio":"2:3","videoLength":6}}}}}'
@@ -0,0 +1,46 @@
curl 'https://grok.com/rest/app-chat/conversations/new' \
-H 'accept: */*' \
-H 'accept-language: en-US,en;q=0.9' \
-H 'baggage: sentry-environment=production,sentry-public_key=b311e0f2690c81f25e2c4cf6d4f7ce1c,sentry-trace_id=277d6351c5063fd659b51b77b50bb453,sentry-org_id=4508179396558848,sentry-sampled=false,sentry-sample_rand=0.9765826569629004,sentry-sample_rate=0' \
-H 'cache-control: no-cache' \
-H 'content-type: application/json' \
-b '_ga=GA1.1.1232202746.1760710013; i18nextLng=en; sso=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiOGU3MDFiNzctOTdkNC00ZjM0LWExOTctOWFmMDU1MzY3NDAwIn0.-a6x0InxbGzfTVfUlrdzxskxCnvMDI8lC90z4wHeGIk; sso-rw=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiOGU3MDFiNzctOTdkNC00ZjM0LWExOTctOWFmMDU1MzY3NDAwIn0.-a6x0InxbGzfTVfUlrdzxskxCnvMDI8lC90z4wHeGIk; stblid=b3331fc1-45d7-466b-83df-67427c0b2367; x-userid=85980643-ffab-4984-a3de-59a608c47d7f; mp_ea93da913ddb66b6372b89d97b1029ac_mixpanel=%7B%22distinct_id%22%3A%2285980643-ffab-4984-a3de-59a608c47d7f%22%2C%22%24device_id%22%3A%2279ce237a-a0f3-4913-bf4b-519ac8a98263%22%2C%22%24initial_referrer%22%3A%22%24direct%22%2C%22%24initial_referring_domain%22%3A%22%24direct%22%2C%22__mps%22%3A%7B%7D%2C%22__mpso%22%3A%7B%7D%2C%22__mpus%22%3A%7B%7D%2C%22__mpa%22%3A%7B%7D%2C%22__mpu%22%3A%7B%7D%2C%22__mpr%22%3A%5B%5D%2C%22__mpap%22%3A%5B%5D%2C%22%24user_id%22%3A%2285980643-ffab-4984-a3de-59a608c47d7f%22%7D; cf_clearance=5QPOzLWH8eEniaDlJR23k9VB4XjRPHdR.kfVR15BRkI-1764645588-1.2.1.1-WBy8wpvS9.Q.ofWBIMTLHDrKRIPt0Xrn5kAQ6I7xf4u0JSbB.E4CRd.fK6kEZo8OTXMAdt.F0YkoLJzB0TufxM79dMu63TKLmorKB.gSgUWJcea1eQcLJ1WG80uhv4VCMrSJ_HHAaq6fqiNNvS7pArgMT4tvoaQXShfDuV8ivYsRp31LYMgNnRFdtiCiJ5mxhf7uUMpSS_UbvCSaYe7CysUr472alMjEYUd.QhKpb8E; _ga_8FEWB057YH=GS2.1.s1764645588$o22$g1$t1764645617$j31$l0$h0' \
-H 'origin: https://grok.com' \
-H 'pragma: no-cache' \
-H 'priority: u=1, i' \
-H 'referer: https://grok.com/imagine/post/6136f31a-4aaf-48e0-ab86-fe9871feca91' \
-H 'sec-ch-ua: "Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "macOS"' \
-H 'sec-fetch-dest: empty' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-site: same-origin' \
-H 'sentry-trace: 277d6351c5063fd659b51b77b50bb453-928bfb8d1221fde1-0' \
-H 'traceparent: 00-b0bd9846c2990e253ecca887fdfba8a2-c415282f4b74bf60-00' \
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36' \
-H 'x-statsig-id: HjOCcSvnF01eIgszJ4J4qot//FLrCJb8Zz+f+AvBLs4ZNmt8fwsKc6PkyrjkEaImt9npwBpAUCrYQeeYTG/5jRWOKfLdHQ' \
-H 'x-xai-request-id: d5ac2ce6-ed77-4a5d-8905-613a498035d3' \
--data-raw '{"temporary":true,"modelName":"grok-3","message":"https://imagine-public.x.ai/imagine-public/images/6136f31a-4aaf-48e0-ab86-fe9871feca91.png --mode=extremely-spicy-or-crazy","toolOverrides":{"videoGen":true},"responseMetadata":{"modelConfigOverride":{"modelMap":{"videoGenModelConfig":{"parentPostId":"6136f31a-4aaf-48e0-ab86-fe9871feca91","aspectRatio":"2:3","videoLength":6}}}}}'
--data-raw
{
"temporary":true,
"modelName":"grok-3",
"message":"https://imagine-public.x.ai/imagine-public/images/6136f31a-4aaf-48e0-ab86-fe9871feca91.png --mode=extremely-spicy-or-crazy",
"toolOverrides": {
"videoGen":true
},
"responseMetadata": {
"modelConfigOverride": {
"modelMap": {
"videoGenModelConfig": {
"parentPostId": "6136f31a-4aaf-48e0-ab86-fe9871feca91",
"aspectRatio": "2:3",
"videoLength":6
}
}
}
}
}
@@ -6,6 +6,7 @@ use crate::datatypes::api::sentry_trace::SentryTrace;
use crate::datatypes::api::svg_path_data::SvgPathData;
use crate::datatypes::api::user_id::UserId;
use crate::datatypes::api::verification_token::VerificationToken;
use crate::datatypes::api::video_generation_mode::VideoGenerationMode;
use crate::datatypes::api::xsid_numbers::XsidNumbers;
use crate::error::categorize_grok_http_error::categorize_grok_http_error;
use crate::error::grok_client_error::GrokClientError;
@@ -33,6 +34,7 @@ pub struct GrokVideoGenChatConversationBuilder<'a> {
pub file_id: &'a FileId,
pub media_type: VideoMediaPostType,
pub prompt: Option<&'a str>,
pub mode: Option<VideoGenerationMode>,
pub aspect_ratio: Option<AspectRatio>,
pub cookie: &'a str,
@@ -232,12 +234,23 @@ impl <'a> GrokVideoGenChatConversationBuilder<'a> {
VideoMediaPostType::Video => unimplemented!("implement for videos"),
};
let mut prompt = format!("{media_url} --mode=normal");
let mode_string = self.mode
.unwrap_or(VideoGenerationMode::Normal)
.as_api_mode_arg();
let mut prompt = format!("{media_url} --mode={mode_string}");
if let Some(user_prompt) = self.prompt {
prompt = format!("{media_url} {user_prompt} --mode=custom");
// If a text prompt is set, mode seems to typically be "custom".
let mode_string = self.mode
.unwrap_or(VideoGenerationMode::Custom)
.as_api_mode_arg();
prompt = format!("{media_url} {user_prompt} --mode={mode_string}");
}
info!("Grok video prompt: {prompt}");
let aspect_ratio = match self.aspect_ratio {
Some(AspectRatio::Square) => VideoGenAspectRatio::Square,
Some(AspectRatio::WideThreeByTwo) => VideoGenAspectRatio::WideThreeByTwo,
@@ -351,6 +364,7 @@ mod tests {
file_id: &file_id,
media_type: VideoMediaPostType::UserUploadedImage,
prompt: maybe_prompt,
mode: Some(VideoGenerationMode::Custom),
aspect_ratio: Some(AspectRatio::TallTwoByThree),
cookie: cookies.as_str(),
@@ -414,6 +428,7 @@ mod tests {
file_id: &file_id,
media_type: VideoMediaPostType::UserUploadedImage,
prompt: maybe_prompt,
mode: None,
aspect_ratio: Some(AspectRatio::Square),
cookie: cookies.as_str(),
@@ -35,3 +35,12 @@ pub const TALL_MOCHI_WITH_GLASSES_GLASSES_MASK_IMAGE_URL : &str = "https://cdn-2
// media token: m_77cpdyaby60z0qv9g6tv67gw2a1337
pub const TREX_SKELETON_IMAGE_URL : &str = "https://cdn-2.fakeyou.com/media/f/4/j/5/3/f4j53296sc35wqs3csgw4j4vvjf5yyxe/image_f4j53296sc35wqs3csgw4j4vvjf5yyxe.png";
// media token: m_zyh17gn6prfp4xs6z76mqkz9k0sr0j
pub const TALL_CORGI_SHIBA_TREASURE_OCEAN_URL: &str = "https://cdn-2.fakeyou.com/media/j/z/7/2/p/jz72pgwb6fegem74pr36yy88hsshwx4m/artcraft_jz72pgwb6fegem74pr36yy88hsshwx4m.png";
// media token: m_a9c4g43nw87y6mebjammrqz849c5xe
pub const WIDE_CORGI_SHIBA_TREASURE_OCEAN_URL: &str = "https://cdn-2.fakeyou.com/media/v/a/g/g/a/vaggan4137tqsz173432cjjg33xkrxpc/artcraft_vaggan4137tqsz173432cjjg33xkrxpc.png";
// media token: m_ytkp3tk2ptvr03p75fwqvend0m3qsg
pub const TALL_CORGI_SHIBA_TREASURE_SKY_URL: &str = "https://cdn-2.fakeyou.com/media/a/4/s/x/x/a4sxxecwenrbta5kx5jk34dp2z9apxqv/artcraft_a4sxxecwenrbta5kx5jk34dp2z9apxqv.png";
+3
View File
@@ -213,6 +213,7 @@ endpoints_fal-ai_sana = []
endpoints_fal-ai_sd15-depth-controlnet = []
endpoints_fal-ai_sdxl-controlnet-union = []
endpoints_fal-ai_skyreels-i2v = []
endpoints_fal-ai_sora = []
endpoints_fal-ai_stable-audio = []
endpoints_fal-ai_stable-cascade = []
endpoints_fal-ai_stable-diffusion-v15 = []
@@ -230,7 +231,9 @@ endpoints_fal-ai_topaz = []
endpoints_fal-ai_transpixar = []
endpoints_fal-ai_trellis = []
endpoints_fal-ai_triposr = []
endpoints_fal-ai_veo = []
endpoints_fal-ai_veo2 = []
endpoints_fal-ai_veo3 = []
endpoints_fal-ai_video-prompt-generator = []
endpoints_fal-ai_video-upscaler = []
endpoints_fal-ai_vidu = []
+15 -1
View File
@@ -25,4 +25,18 @@ pub mod seedance;
feature = "endpoints_fal-ai_bytedance"
)))
)]
pub mod seededit;
pub mod seededit;
#[cfg(any(
feature = "endpoints",
feature = "endpoints_fal-ai",
feature = "endpoints_fal-ai_bytedance"
))]
#[cfg_attr(
docsrs,
doc(cfg(any(
feature = "endpoints",
feature = "endpoints_fal-ai",
feature = "endpoints_fal-ai_bytedance"
)))
)]
pub mod seedream;
@@ -0,0 +1,52 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct BytedanceSeedreamV4EditImageInput {
pub prompt: String,
pub image_urls: Vec<String>,
/// Supports a custom height/width (which we didn't implement) OR an enum value -
/// square_hd, square, portrait_4_3, portrait_16_9, landscape_4_3, landscape_16_9, auto, auto_2K, auto_4K
#[serde(skip_serializing_if = "Option::is_none")]
pub image_size: Option<String>,
/// Number of generations
/// 1 - 4
#[serde(skip_serializing_if = "Option::is_none")]
pub num_images: Option<u8>,
/// 1 - 4
/// If set to a number greater than one, enables multi-image generation.
/// The model will potentially return up to max_images images every generation,
/// and in total, num_images generations will be carried out. In total, the number
/// of images generated will be between num_images and max_images*num_images.
/// Default value: 1
#[serde(skip_serializing_if = "Option::is_none")]
pub max_images: Option<u8>,
/// Possible enum values: standard, fast (default "standard")
#[serde(skip_serializing_if = "Option::is_none")]
pub enhance_prompt_mode: Option<String>,
/// Defaults to true
#[serde(skip_serializing_if = "Option::is_none")]
pub enable_safety_checker: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BytedanceSeedreamV4EditImageOutput {
pub images: Vec<ImageFile>,
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct ImageFile {
/// The URL where the file can be downloaded from.
pub url: String,
}
pub fn bytedance_seedream_v4_edit_image(
params: BytedanceSeedreamV4EditImageInput,
) -> FalRequest<BytedanceSeedreamV4EditImageInput, BytedanceSeedreamV4EditImageOutput> {
FalRequest::new("fal-ai/bytedance/seedream/v4/edit", params)
}
@@ -0,0 +1,50 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct BytedanceSeedreamV4TextToImageInput {
pub prompt: String,
/// Supports a custom height/width (which we didn't implement) OR an enum value -
/// square_hd, square, portrait_4_3, portrait_16_9, landscape_4_3, landscape_16_9, auto, auto_2K, auto_4K
#[serde(skip_serializing_if = "Option::is_none")]
pub image_size: Option<String>,
/// Number of generations
/// 1 - 4
#[serde(skip_serializing_if = "Option::is_none")]
pub num_images: Option<u8>,
/// 1 - 4
/// If set to a number greater than one, enables multi-image generation.
/// The model will potentially return up to max_images images every generation,
/// and in total, num_images generations will be carried out. In total, the number
/// of images generated will be between num_images and max_images*num_images.
/// Default value: 1
#[serde(skip_serializing_if = "Option::is_none")]
pub max_images: Option<u8>,
/// Possible enum values: standard, fast (default "standard")
#[serde(skip_serializing_if = "Option::is_none")]
pub enhance_prompt_mode: Option<String>,
/// Defaults to true
#[serde(skip_serializing_if = "Option::is_none")]
pub enable_safety_checker: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BytedanceSeedreamV4TextToImageOutput {
pub images: Vec<ImageFile>,
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct ImageFile {
/// The URL where the file can be downloaded from.
pub url: String,
}
pub fn bytedance_seedream_v4_text_to_image(
params: BytedanceSeedreamV4TextToImageInput,
) -> FalRequest<BytedanceSeedreamV4TextToImageInput, BytedanceSeedreamV4TextToImageOutput> {
FalRequest::new("fal-ai/bytedance/seedream/v4/text-to-image", params)
}
@@ -0,0 +1,51 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct BytedanceSeedreamV4p5EditImageInput {
pub prompt: String,
pub image_urls: Vec<String>,
/// Supports a custom height/width (which we didn't implement) OR an enum value -
/// square_hd, square, portrait_4_3, portrait_16_9, landscape_4_3, landscape_16_9, auto_2K, auto_4K (no more "auto")
#[serde(skip_serializing_if = "Option::is_none")]
pub image_size: Option<String>,
/// Number of generations
/// 1 - 4
#[serde(skip_serializing_if = "Option::is_none")]
pub num_images: Option<u8>,
/// 1 - 4
/// If set to a number greater than one, enables multi-image generation.
/// The model will potentially return up to max_images images every generation,
/// and in total, num_images generations will be carried out. In total, the number
/// of images generated will be between num_images and max_images*num_images.
/// Default value: 1
#[serde(skip_serializing_if = "Option::is_none")]
pub max_images: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
pub seed: Option<i64>,
/// Defaults to true
#[serde(skip_serializing_if = "Option::is_none")]
pub enable_safety_checker: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BytedanceSeedreamV4p5EditImageOutput {
pub images: Vec<ImageFile>,
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct ImageFile {
/// The URL where the file can be downloaded from.
pub url: String,
}
pub fn bytedance_seedream_v4p5_edit_image(
params: BytedanceSeedreamV4p5EditImageInput,
) -> FalRequest<BytedanceSeedreamV4p5EditImageInput, BytedanceSeedreamV4p5EditImageOutput> {
FalRequest::new("fal-ai/bytedance/seedream/v4.5/edit", params)
}
@@ -0,0 +1,49 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct BytedanceSeedreamV4p5TextToImageInput {
pub prompt: String,
/// Supports a custom height/width (which we didn't implement) OR an enum value -
/// square_hd, square, portrait_4_3, portrait_16_9, landscape_4_3, landscape_16_9, auto_2K, auto_4K (no more auto)
#[serde(skip_serializing_if = "Option::is_none")]
pub image_size: Option<String>,
/// Number of generations
/// 1 - 4
#[serde(skip_serializing_if = "Option::is_none")]
pub num_images: Option<u8>,
/// 1 - 4
/// If set to a number greater than one, enables multi-image generation.
/// The model will potentially return up to max_images images every generation,
/// and in total, num_images generations will be carried out. In total, the number
/// of images generated will be between num_images and max_images*num_images.
/// Default value: 1
#[serde(skip_serializing_if = "Option::is_none")]
pub max_images: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
pub seed: Option<i64>,
/// Defaults to true
#[serde(skip_serializing_if = "Option::is_none")]
pub enable_safety_checker: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BytedanceSeedreamV4p5TextToImageOutput {
pub images: Vec<ImageFile>,
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct ImageFile {
/// The URL where the file can be downloaded from.
pub url: String,
}
pub fn bytedance_seedream_v4p5_text_to_image(
params: BytedanceSeedreamV4p5TextToImageInput,
) -> FalRequest<BytedanceSeedreamV4p5TextToImageInput, BytedanceSeedreamV4p5TextToImageOutput> {
FalRequest::new("fal-ai/bytedance/seedream/v4.5/text-to-image", params)
}
@@ -0,0 +1,4 @@
pub mod bytedance_seedream_v4_edit_image;
pub mod bytedance_seedream_v4_text_to_image;
pub mod bytedance_seedream_v4p5_edit_image;
pub mod bytedance_seedream_v4p5_text_to_image;
@@ -54,3 +54,31 @@ pub mod v1_6;
)))
)]
pub mod v2_1;
#[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_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,45 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct KlingV2p5TurboProImageToVideoInput {
pub prompt: String,
/// Starting frame
pub image_url: String,
/// Optional ending frame
#[serde(skip_serializing_if = "Option::is_none")]
pub tail_image_url: Option<String>,
/// 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 KlingV2p5TurboProImageToVideoOutput {
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_v2p5_turbo_pro_image_to_video(
params: KlingV2p5TurboProImageToVideoInput,
) -> FalRequest<KlingV2p5TurboProImageToVideoInput, KlingV2p5TurboProImageToVideoOutput> {
FalRequest::new("fal-ai/kling-video/v2.5-turbo/pro/image-to-video", params)
}
@@ -0,0 +1,42 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct KlingV2p5TurboProTextToVideoInput {
pub prompt: String,
/// Aspect ratio
/// Possible enum values: "16:9", "9:16", "1:1"
pub aspect_ratio: Option<String>,
/// 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 KlingV2p5TurboProTextToVideoOutput {
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_v2p5_turbo_pro_text_to_video(
params: KlingV2p5TurboProTextToVideoInput,
) -> FalRequest<KlingV2p5TurboProTextToVideoInput, KlingV2p5TurboProTextToVideoOutput> {
FalRequest::new("fal-ai/kling-video/v2.5-turbo/pro/text-to-video", params)
}
@@ -0,0 +1,41 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct KlingV2p5TurboStandardImageToVideoInput {
pub prompt: String,
/// Starting frame
pub image_url: String,
/// 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 KlingV2p5TurboStandardImageToVideoOutput {
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_v2p5_turbo_standard_image_to_video(
params: KlingV2p5TurboStandardImageToVideoInput,
) -> FalRequest<KlingV2p5TurboStandardImageToVideoInput, KlingV2p5TurboStandardImageToVideoOutput> {
FalRequest::new("fal-ai/kling-video/v2.5-turbo/standard/image-to-video", params)
}
@@ -0,0 +1,3 @@
pub mod kling_v2p5_turbo_pro_image_to_video;
pub mod kling_v2p5_turbo_pro_text_to_video;
pub mod kling_v2p5_turbo_standard_image_to_video;
@@ -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;
@@ -0,0 +1,30 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct HailuoV2p3FastProImageToVideoInput {
pub prompt: String,
/// Starting frame
pub image_url: String,
/// Default value: true
#[serde(skip_serializing_if = "Option::is_none")]
pub prompt_optimizer: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct HailuoV2p3FastProImageToVideoOutput {
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 hailuo_v2p3_fast_pro_image_to_video(
params: HailuoV2p3FastProImageToVideoInput,
) -> FalRequest<HailuoV2p3FastProImageToVideoInput, HailuoV2p3FastProImageToVideoOutput> {
FalRequest::new("fal-ai/minimax/hailuo-2.3-fast/pro/image-to-video", params)
}
@@ -0,0 +1,30 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct HailuoV2p3ProImageToVideoInput {
pub prompt: String,
/// Starting frame
pub image_url: String,
/// Default value: true
#[serde(skip_serializing_if = "Option::is_none")]
pub prompt_optimizer: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct HailuoV2p3ProImageToVideoOutput {
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 hailuo_v2p3_pro_image_to_video(
params: HailuoV2p3ProImageToVideoInput,
) -> FalRequest<HailuoV2p3ProImageToVideoInput, HailuoV2p3ProImageToVideoOutput> {
FalRequest::new("fal-ai/minimax/hailuo-2.3/pro/image-to-video", params)
}
@@ -0,0 +1,27 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct HailuoV2p3ProTextToVideoInput {
pub prompt: String,
/// Default value: true
#[serde(skip_serializing_if = "Option::is_none")]
pub prompt_optimizer: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct HailuoV2p3ProTextToVideoOutput {
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 hailuo_v2p3_pro_text_to_video(
params: HailuoV2p3ProTextToVideoInput,
) -> FalRequest<HailuoV2p3ProTextToVideoInput, HailuoV2p3ProTextToVideoOutput> {
FalRequest::new("fal-ai/minimax/hailuo-2.3/pro/text-to-video", params)
}
@@ -0,0 +1,3 @@
pub mod hailuo_v2p3_pro_image_to_video;
pub mod hailuo_v2p3_pro_text_to_video;
pub mod hailuo_v2p3_fast_pro_image_to_video;
@@ -75,6 +75,20 @@ pub mod video_01_live;
)))
)]
pub mod video_01_subject_reference;
#[cfg(any(
feature = "endpoints",
feature = "endpoints_fal-ai",
feature = "endpoints_fal-ai_minimax"
))]
#[cfg_attr(
docsrs,
doc(cfg(any(
feature = "endpoints",
feature = "endpoints_fal-ai",
feature = "endpoints_fal-ai_minimax"
)))
)]
pub mod hailuo;
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct File {
+29
View File
@@ -1930,6 +1930,20 @@ pub mod sdxl_controlnet_union;
)))
)]
pub mod skyreels_i2v;
#[cfg(any(
feature = "endpoints",
feature = "endpoints_fal-ai",
feature = "endpoints_fal-ai_sora"
))]
#[cfg_attr(
docsrs,
doc(cfg(any(
feature = "endpoints",
feature = "endpoints_fal-ai",
feature = "endpoints_fal-ai_sora"
)))
)]
pub mod sora;
#[cfg(any(
feature = "endpoints",
feature = "endpoints_fal-ai",
@@ -2196,6 +2210,20 @@ pub mod veo2;
)))
)]
pub mod veo3;
#[cfg(any(
feature = "endpoints",
feature = "endpoints_fal-ai",
feature = "endpoints_fal-ai_veo"
))]
#[cfg_attr(
docsrs,
doc(cfg(any(
feature = "endpoints",
feature = "endpoints_fal-ai",
feature = "endpoints_fal-ai_veo"
)))
)]
pub mod veo;
#[cfg(any(
feature = "endpoints",
feature = "endpoints_fal-ai",
@@ -2408,3 +2436,4 @@ pub mod yue;
pub mod zonos;
pub mod qwen_image_edit;
pub mod nano_banana_pro;
@@ -0,0 +1,2 @@
pub mod nano_banana_pro_text_to_image;
pub mod nano_banana_pro_image_edit;
@@ -0,0 +1,55 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct NanoBananaProImageEditInput {
pub prompt: String,
pub image_urls: Vec<String>,
/// Eg. "16:9", "1:1", and a ton of other options. So many options.
#[serde(skip_serializing_if = "Option::is_none")]
pub aspect_ratio: Option<String>,
/// Eg. "1K", "2K", "4K"
#[serde(skip_serializing_if = "Option::is_none")]
pub resolution: Option<String>,
/// 1 - 4
#[serde(skip_serializing_if = "Option::is_none")]
pub num_images: Option<u8>,
/// "jpeg", "png", "webp"
#[serde(skip_serializing_if = "Option::is_none")]
pub output_format: Option<String>,
}
/*
{
"prompt": "make a photo of the man driving the car down the california coastline",
"num_images": 3,
"aspect_ratio": "16:9",
"output_format": "png",
"image_urls": [
"https://storage.googleapis.com/falserverless/example_inputs/nano-banana-edit-input.png",
"https://storage.googleapis.com/falserverless/example_inputs/nano-banana-edit-input-2.png"
],
"resolution": "1K"
}
*/
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct ImageFile {
/// The URL where the file can be downloaded from.
pub url: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct NanoBananaProImageEditOutput {
pub images: Vec<ImageFile>,
}
pub fn nano_banana_pro_image_edit(
params: NanoBananaProImageEditInput,
) -> FalRequest<NanoBananaProImageEditInput, NanoBananaProImageEditOutput> {
FalRequest::new("fal-ai/nano-banana-pro/edit", params)
}
@@ -0,0 +1,39 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct NanoBananaProTextToImageInput {
pub prompt: String,
/// Eg. "16:9", "1:1", and a ton of other options. So many options.
#[serde(skip_serializing_if = "Option::is_none")]
pub aspect_ratio: Option<String>,
/// Eg. "1K", "2K", "4K"
#[serde(skip_serializing_if = "Option::is_none")]
pub resolution: Option<String>,
/// 1 - 4
#[serde(skip_serializing_if = "Option::is_none")]
pub num_images: Option<u8>,
/// "jpeg", "png", "webp"
#[serde(skip_serializing_if = "Option::is_none")]
pub output_format: Option<String>,
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct ImageFile {
/// The URL where the file can be downloaded from.
pub url: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct NanoBananaProTextToImageOutput {
pub images: Vec<ImageFile>,
}
pub fn nano_banana_pro_text_to_image(
params: NanoBananaProTextToImageInput,
) -> FalRequest<NanoBananaProTextToImageInput, NanoBananaProTextToImageOutput> {
FalRequest::new("fal-ai/nano-banana-pro", params)
}
@@ -12,3 +12,17 @@
)))
)]
pub mod v3_5;
#[cfg(any(
feature = "endpoints",
feature = "endpoints_fal-ai",
feature = "endpoints_fal-ai_pixverse"
))]
#[cfg_attr(
docsrs,
doc(cfg(any(
feature = "endpoints",
feature = "endpoints_fal-ai",
feature = "endpoints_fal-ai_pixverse"
)))
)]
pub mod v5;
@@ -0,0 +1,2 @@
pub mod pixverse_v5_image_to_video;
pub mod pixverse_v5_text_to_video;
@@ -0,0 +1,56 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct PixverseV5ImageToVideoInput {
pub prompt: String,
/// Starting frame
pub image_url: String,
/// Resolution
/// Possible enum values: 360p, 540p, 720p, 1080p
/// Default is 720p
#[serde(skip_serializing_if = "Option::is_none")]
pub resolution: Option<String>,
/// The aspect ratio of the generated video
/// Default value: "16:9"
/// Possible enum values: 16:9, 4:3, 1:1, 3:4, 9:16
#[serde(skip_serializing_if = "Option::is_none")]
pub aspect_ratio: Option<String>,
/// Optional negative prompt
#[serde(skip_serializing_if = "Option::is_none")]
pub negative_prompt: Option<String>,
/// Duration in seconds
/// Options: "5", "8"
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<String>,
/// Optional style
/// Possible enum values: anime, 3d_animation, clay, comic, cyberpunk
#[serde(skip_serializing_if = "Option::is_none")]
pub style: Option<String>,
/// Optional seed
#[serde(skip_serializing_if = "Option::is_none")]
pub seed: Option<i64>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct PixverseV5ImageToVideoOutput {
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 pixverse_v5_image_to_video(
params: PixverseV5ImageToVideoInput,
) -> FalRequest<PixverseV5ImageToVideoInput, PixverseV5ImageToVideoOutput> {
FalRequest::new("fal-ai/pixverse/v5/image-to-video", params)
}
@@ -0,0 +1,53 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct PixverseV5TextToVideoInput {
pub prompt: String,
/// Resolution
/// Possible enum values: 360p, 540p, 720p, 1080p
/// Default is 720p
#[serde(skip_serializing_if = "Option::is_none")]
pub resolution: Option<String>,
/// The aspect ratio of the generated video
/// Default value: "16:9"
/// Possible enum values: 16:9, 4:3, 1:1, 3:4, 9:16
#[serde(skip_serializing_if = "Option::is_none")]
pub aspect_ratio: Option<String>,
/// Optional negative prompt
#[serde(skip_serializing_if = "Option::is_none")]
pub negative_prompt: Option<String>,
/// Duration in seconds
/// Options: "5", "8"
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<String>,
/// Optional style
/// Possible enum values: anime, 3d_animation, clay, comic, cyberpunk
#[serde(skip_serializing_if = "Option::is_none")]
pub style: Option<String>,
/// Optional seed
#[serde(skip_serializing_if = "Option::is_none")]
pub seed: Option<i64>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct PixverseV5TextToVideoOutput {
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 pixverse_v5_text_to_video(
params: PixverseV5TextToVideoInput,
) -> FalRequest<PixverseV5TextToVideoInput, PixverseV5TextToVideoOutput> {
FalRequest::new("fal-ai/pixverse/v5/text-to-video", params)
}
+1
View File
@@ -0,0 +1 @@
pub mod sora2;
@@ -0,0 +1,4 @@
pub mod sora_2_image_to_video;
pub mod sora_2_pro_image_to_video;
pub mod sora_2_pro_text_to_video;
pub mod sora_2_text_to_video;
@@ -0,0 +1,48 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Sora2ImageToVideoInput {
pub prompt: String,
/// Starting frame
pub image_url: String,
/// Possible enum values: auto, 720p
/// Default value auto
#[serde(skip_serializing_if = "Option::is_none")]
pub resolution: Option<String>,
/// Possible enum values: auto, 9:16, 16:9
/// Default value "auto"
#[serde(skip_serializing_if = "Option::is_none")]
pub aspect_ratio: Option<String>,
/// Duration in seconds
/// Possible enum values: 4, 8, 12
/// Default value 4
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<u8>,
/// Whether to delete the video after generation for privacy reasons.
/// If True, the video cannot be used for remixing and will be permanently deleted.
/// Default value: true
#[serde(skip_serializing_if = "Option::is_none")]
pub delete_video: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Sora2ImageToVideoOutput {
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 sora_2_image_to_video(
params: Sora2ImageToVideoInput,
) -> FalRequest<Sora2ImageToVideoInput, Sora2ImageToVideoOutput> {
FalRequest::new("fal-ai/sora-2/image-to-video", params)
}
@@ -0,0 +1,48 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Sora2ProImageToVideoInput {
pub prompt: String,
/// Starting frame
pub image_url: String,
/// Possible enum values: auto, 720p, 1080p
/// Default value auto
#[serde(skip_serializing_if = "Option::is_none")]
pub resolution: Option<String>,
/// Possible enum values: auto, 9:16, 16:9
/// Default value "auto"
#[serde(skip_serializing_if = "Option::is_none")]
pub aspect_ratio: Option<String>,
/// Duration in seconds
/// Possible enum values: 4, 8, 12
/// Default value 4
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<u8>,
/// Whether to delete the video after generation for privacy reasons.
/// If True, the video cannot be used for remixing and will be permanently deleted.
/// Default value: true
#[serde(skip_serializing_if = "Option::is_none")]
pub delete_video: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Sora2ProImageToVideoOutput {
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 sora_2_pro_image_to_video(
params: Sora2ProImageToVideoInput,
) -> FalRequest<Sora2ProImageToVideoInput, Sora2ProImageToVideoOutput> {
FalRequest::new("fal-ai/sora-2/image-to-video/pro", params)
}
@@ -0,0 +1,45 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Sora2ProTextToVideoInput {
pub prompt: String,
/// Possible enum values: auto, 720p, 1080p
/// Default value auto
#[serde(skip_serializing_if = "Option::is_none")]
pub resolution: Option<String>,
/// Possible enum values: auto, 9:16, 16:9
/// Default value "auto"
#[serde(skip_serializing_if = "Option::is_none")]
pub aspect_ratio: Option<String>,
/// Duration in seconds
/// Possible enum values: 4, 8, 12
/// Default value 4
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<u8>,
/// Whether to delete the video after generation for privacy reasons.
/// If True, the video cannot be used for remixing and will be permanently deleted.
/// Default value: true
#[serde(skip_serializing_if = "Option::is_none")]
pub delete_video: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Sora2ProTextToVideoOutput {
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 sora_2_pro_text_to_video(
params: Sora2ProTextToVideoInput,
) -> FalRequest<Sora2ProTextToVideoInput, Sora2ProTextToVideoOutput> {
FalRequest::new("fal-ai/sora-2/text-to-video/pro", params)
}
@@ -0,0 +1,45 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Sora2TextToVideoInput {
pub prompt: String,
/// Possible enum values: 720p
/// Default value 720p
#[serde(skip_serializing_if = "Option::is_none")]
pub resolution: Option<String>,
/// Possible enum values: auto, 9:16, 16:9
/// Default value "auto"
#[serde(skip_serializing_if = "Option::is_none")]
pub aspect_ratio: Option<String>,
/// Duration in seconds
/// Possible enum values: 4, 8, 12
/// Default value 4
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<u8>,
/// Whether to delete the video after generation for privacy reasons.
/// If True, the video cannot be used for remixing and will be permanently deleted.
/// Default value: true
#[serde(skip_serializing_if = "Option::is_none")]
pub delete_video: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Sora2TextToVideoOutput {
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 sora_2_text_to_video(
params: Sora2TextToVideoInput,
) -> FalRequest<Sora2TextToVideoInput, Sora2TextToVideoOutput> {
FalRequest::new("fal-ai/sora-2/text-to-video", params)
}
+1
View File
@@ -0,0 +1 @@
pub mod veo3_1;
@@ -0,0 +1,6 @@
pub mod veo_3p1_fast_first_frame_image_to_video;
pub mod veo_3p1_fast_first_last_frame_image_to_video;
pub mod veo_3p1_fast_text_to_video;
pub mod veo_3p1_first_frame_image_to_video;
pub mod veo_3p1_first_last_frame_image_to_video;
pub mod veo_3p1_text_to_video;
@@ -0,0 +1,47 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Veo3p1FastFirstFrameImageToVideoInput {
pub prompt: String,
/// Starting frame
pub image_url: String,
/// Possible enum values: auto, 9:16, 16:9, 1:1
/// Default value "16:9"
#[serde(skip_serializing_if = "Option::is_none")]
pub aspect_ratio: Option<String>,
/// Duration in seconds
/// Possible enum values: 4s, 6s, 8s
/// Default value 8s
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<String>,
/// Generate audio
/// Default value "true"
#[serde(skip_serializing_if = "Option::is_none")]
pub generate_audio: Option<bool>,
/// Possible enum values: 720p, 1080p
/// Default value 720p
#[serde(skip_serializing_if = "Option::is_none")]
pub resolution: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Veo3p1FastFirstFrameImageToVideoOutput {
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 veo_3p1_fast_first_frame_image_to_video(
params: Veo3p1FastFirstFrameImageToVideoInput,
) -> FalRequest<Veo3p1FastFirstFrameImageToVideoInput, Veo3p1FastFirstFrameImageToVideoOutput> {
FalRequest::new("fal-ai/veo3.1/fast/image-to-video", params)
}
@@ -0,0 +1,50 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Veo3p1FastFirstLastFrameImageToVideoInput {
pub prompt: String,
/// Starting frame
pub first_frame_url: String,
/// Ending frame
pub last_frame_url: String,
/// Duration in seconds
/// Possible enum values: 4s, 6s, 8s
/// Default value 8s
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<String>,
/// Possible enum values: auto, 9:16, 16:9, 1:1
/// Default value "auto"
#[serde(skip_serializing_if = "Option::is_none")]
pub aspect_ratio: Option<String>,
/// Possible enum values: 720p, 1080p
/// Default value 720p
#[serde(skip_serializing_if = "Option::is_none")]
pub resolution: Option<String>,
/// Generate audio
/// Defaults to "true"
#[serde(skip_serializing_if = "Option::is_none")]
pub generate_audio: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Veo3p1FastFirstLastFrameImageToVideoOutput {
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 veo_3p1_fast_first_last_frame_image_to_video(
params: Veo3p1FastFirstLastFrameImageToVideoInput,
) -> FalRequest<Veo3p1FastFirstLastFrameImageToVideoInput, Veo3p1FastFirstLastFrameImageToVideoOutput> {
FalRequest::new("fal-ai/veo3.1/fast/first-last-frame-to-video", params)
}
@@ -0,0 +1,58 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Veo3p1FastTextToVideoInput {
pub prompt: String,
/// Possible enum values: 9:16, 16:9, 1:1
/// Default value "16:9"
#[serde(skip_serializing_if = "Option::is_none")]
pub aspect_ratio: Option<String>,
/// Duration in seconds
/// Possible enum values: 4s, 6s, 8s
/// Default value 8s
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub negative_prompt: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub enhance_prompt: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub seed: Option<i64>,
/// Whether to automatically attempt to fix prompts that fail content policy or other validation checks by rewriting them
/// Default value: true
#[serde(skip_serializing_if = "Option::is_none")]
pub auto_fix: Option<bool>,
/// Possible enum values: 720p, 1080p
/// Default value 720p
#[serde(skip_serializing_if = "Option::is_none")]
pub resolution: Option<String>,
/// Generate audio
/// Default value "true"
#[serde(skip_serializing_if = "Option::is_none")]
pub generate_audio: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Veo3p1FastTextToVideoOutput {
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 veo_3p1_fast_text_to_video(
params: Veo3p1FastTextToVideoInput,
) -> FalRequest<Veo3p1FastTextToVideoInput, Veo3p1FastTextToVideoOutput> {
FalRequest::new("fal-ai/veo3.1/fast", params)
}
@@ -0,0 +1,47 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Veo3p1FirstFrameImageToVideoInput {
pub prompt: String,
/// Starting frame
pub image_url: String,
/// Possible enum values: 9:16, 16:9 (NB: This differs from first-frame/last-frame)
/// Default value "16:9"
#[serde(skip_serializing_if = "Option::is_none")]
pub aspect_ratio: Option<String>,
/// Duration in seconds
/// Possible enum values: 4s, 6s, 8s
/// Default value 8s
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<String>,
/// Generate audio
/// Default value "true"
#[serde(skip_serializing_if = "Option::is_none")]
pub generate_audio: Option<bool>,
/// Possible enum values: 720p, 1080p
/// Default value 720p
#[serde(skip_serializing_if = "Option::is_none")]
pub resolution: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Veo3p1FirstFrameImageToVideoOutput {
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 veo_3p1_first_frame_image_to_video(
params: Veo3p1FirstFrameImageToVideoInput,
) -> FalRequest<Veo3p1FirstFrameImageToVideoInput, Veo3p1FirstFrameImageToVideoOutput> {
FalRequest::new("fal-ai/veo3.1/image-to-video", params)
}
@@ -0,0 +1,50 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Veo3p1FirstLastFrameImageToVideoInput {
pub prompt: String,
/// Starting frame
pub first_frame_url: String,
/// Ending frame
pub last_frame_url: String,
/// Duration in seconds
/// Possible enum values: 4s, 6s, 8s
/// Default value 8s
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<String>,
/// Possible enum values: auto, 9:16, 16:9, 1:1
/// Default value "auto"
#[serde(skip_serializing_if = "Option::is_none")]
pub aspect_ratio: Option<String>,
/// Possible enum values: 720p, 1080p
/// Default value 720p
#[serde(skip_serializing_if = "Option::is_none")]
pub resolution: Option<String>,
/// Generate audio
/// Defaults to "true"
#[serde(skip_serializing_if = "Option::is_none")]
pub generate_audio: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Veo3p1FirstLastFrameImageToVideoOutput {
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 veo_3p1_first_last_frame_image_to_video(
params: Veo3p1FirstLastFrameImageToVideoInput,
) -> FalRequest<Veo3p1FirstLastFrameImageToVideoInput, Veo3p1FirstLastFrameImageToVideoOutput> {
FalRequest::new("fal-ai/veo3.1/first-last-frame-to-video", params)
}
@@ -0,0 +1,58 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Veo3p1TextToVideoInput {
pub prompt: String,
/// Possible enum values: 9:16, 16:9, 1:1
/// Default value "16:9"
#[serde(skip_serializing_if = "Option::is_none")]
pub aspect_ratio: Option<String>,
/// Duration in seconds
/// Possible enum values: 4s, 6s, 8s
/// Default value 8s
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub negative_prompt: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub enhance_prompt: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub seed: Option<i64>,
/// Whether to automatically attempt to fix prompts that fail content policy or other validation checks by rewriting them
/// Default value: true
#[serde(skip_serializing_if = "Option::is_none")]
pub auto_fix: Option<bool>,
/// Possible enum values: 720p, 1080p
/// Default value 720p
#[serde(skip_serializing_if = "Option::is_none")]
pub resolution: Option<String>,
/// Generate audio
/// Default value "true"
#[serde(skip_serializing_if = "Option::is_none")]
pub generate_audio: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Veo3p1TextToVideoOutput {
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 veo_3p1_text_to_video(
params: Veo3p1TextToVideoInput,
) -> FalRequest<Veo3p1TextToVideoInput, Veo3p1TextToVideoOutput> {
FalRequest::new("fal-ai/veo3.1", params)
}