more fal endpoints

This commit is contained in:
Brandon Thomas committed 2025-08-28 00:09:34 -04:00
1 parent 92b68d3f9d
commit 04c2c524d7
10 files changed
+240 -1

No files matched your search

@@ -57,6 +57,8 @@ pub async fn enqueue_seedance_1_lite_image_to_video_webhook<U: IntoUrl, T: IntoU
// TODO: Add these later
camera_fixed: None,
seed: -1,
// Static
enable_safety_checker: Some(false),
};
let result = image_to_video(request)
@@ -0,0 +1,101 @@
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::seedance::v1::pro::image_to_video::{seedance_v1_pro_image_to_video, SeedanceImageToVideoProRequest};
use fal::webhook::WebhookResponse;
use reqwest::IntoUrl;
pub struct Seedance1ProArgs<'a, U: IntoUrl, V: IntoUrl> {
pub image_url: U,
pub webhook_url: V,
pub prompt: &'a str,
pub api_key: &'a FalApiKey,
pub camera_fixed: bool,
pub duration: Seedance1ProDuration,
pub resolution: Seedance1ProResolution,
pub seed: Option<u32>,
}
#[derive(Copy, Clone, Debug)]
pub enum Seedance1ProDuration {
FiveSeconds,
TenSeconds,
TwelveSeconds,
}
#[derive(Copy, Clone, Debug)]
pub enum Seedance1ProResolution {
FourEightyP, // 480p
SevenTwentyP, // 720p
TenEightyP, // 1080p
}
pub async fn enqueue_seedance_1_pro_image_to_video_webhook<U: IntoUrl, V: IntoUrl>(
args: Seedance1ProArgs<'_, U, V>
) -> Result<WebhookResponse, FalErrorPlus> {
let duration = match args.duration {
Seedance1ProDuration::FiveSeconds => Some("5".to_string()),
Seedance1ProDuration::TenSeconds => Some("10".to_string()),
Seedance1ProDuration::TwelveSeconds => Some("12".to_string()),
};
let resolution = match args.resolution {
Seedance1ProResolution::FourEightyP => Some("480p".to_string()),
Seedance1ProResolution::SevenTwentyP => Some("720p".to_string()),
Seedance1ProResolution::TenEightyP => Some("1080p".to_string()),
};
let image_url = args.image_url.as_str().to_string();
let request = SeedanceImageToVideoProRequest {
image_url,
prompt: args.prompt.to_string(),
duration,
resolution,
// TODO: Add these later
camera_fixed: None,
// Static
enable_safety_checker: Some(false),
};
let result = seedance_v1_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::enqueue_seedance_1_pro_image_to_video_webhook::{enqueue_seedance_1_pro_image_to_video_webhook, Seedance1ProArgs, Seedance1ProDuration, Seedance1ProResolution};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::TALL_MOCHI_WITH_GLASSES_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 = Seedance1ProArgs {
image_url: TALL_MOCHI_WITH_GLASSES_IMAGE_URL,
prompt: "shiba in glasses runs to the lake and stands by the shore",
api_key: &api_key,
camera_fixed: false,
duration: Seedance1ProDuration::FiveSeconds,
resolution: Seedance1ProResolution::SevenTwentyP,
seed: None,
webhook_url: "https://example.com/webhook",
};
let result = enqueue_seedance_1_pro_image_to_video_webhook(args).await?;
Ok(())
}
}
@@ -2,6 +2,7 @@ pub mod enqueue_kling_16_pro_image_to_video_webhook;
pub mod enqueue_kling_21_master_image_to_video_webhook;
pub mod enqueue_kling_21_pro_image_to_video_webhook;
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;
@@ -26,6 +26,9 @@ pub struct ImageToVideoRequest {
pub prompt: String,
pub seed: i32,
#[serde(skip_serializing_if = "Option::is_none")]
pub enable_safety_checker: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize, Default)]
@@ -11,4 +11,5 @@
feature = "endpoints_fal-ai_bytedance"
)))
)]
pub mod lite;
pub mod lite;
pub mod pro;
@@ -0,0 +1,62 @@
#[allow(unused_imports)]
use crate::prelude::*;
#[allow(unused_imports)]
use serde::{Deserialize, Serialize};
#[allow(unused_imports)]
use std::collections::HashMap;
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct SeedanceImageToVideoProRequest {
pub prompt: String,
pub image_url: String,
/// The resolution of the generated video frame
#[serde(skip_serializing_if = "Option::is_none")]
pub resolution: Option<String>,
/// The duration of the generated video in seconds
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub camera_fixed: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub enable_safety_checker: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct I2VOutput {
/// The generated video
/// {"url":"https://v2.fal.media/files/36087878b0c1435bb75c19b64b7db178_output.mp4"}
pub video: File,
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct File {
/// The URL where the file can be downloaded from.
pub url: String,
// /// The mime type of the file.
// /// "image/png"
// #[serde(skip_serializing_if = "Option::is_none")]
// pub content_type: Option<String>,
// /// File data
// #[serde(skip_serializing_if = "Option::is_none")]
// pub file_data: Option<String>,
// /// The name of the file. It will be auto-generated if not provided.
// /// "z9RV14K95DvU.png"
// #[serde(skip_serializing_if = "Option::is_none")]
// pub file_name: Option<String>,
// /// The size of the file in bytes.
// /// 4404019
// #[serde(skip_serializing_if = "Option::is_none")]
// pub file_size: Option<i64>,
}
pub fn seedance_v1_pro_image_to_video(
params: SeedanceImageToVideoProRequest,
) -> FalRequest<SeedanceImageToVideoProRequest, I2VOutput> {
FalRequest::new("fal-ai/bytedance/seedance/v1/pro/image-to-video", params)
}
@@ -0,0 +1 @@
pub mod image_to_video;
@@ -0,0 +1,53 @@
use crate::prelude::{Deserialize, FalRequest, Serialize};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Gemini25FlashImageEditInput {
pub prompt: String,
pub image_urls: Vec<String>,
/// 1 - 4
#[serde(skip_serializing_if = "Option::is_none")]
pub num_images: Option<u8>,
/// "jpeg" or "png"
#[serde(skip_serializing_if = "Option::is_none")]
pub output_format: Option<String>,
/// Resolution, eg. "720p"
#[serde(skip_serializing_if = "Option::is_none")]
pub resolution: Option<String>,
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct File {
/// The URL where the file can be downloaded from.
pub url: String,
// /// The mime type of the file.
// /// "image/png"
// #[serde(skip_serializing_if = "Option::is_none")]
// pub content_type: Option<String>,
// /// File data
// #[serde(skip_serializing_if = "Option::is_none")]
// pub file_data: Option<String>,
// /// The name of the file. It will be auto-generated if not provided.
// /// "z9RV14K95DvU.png"
// #[serde(skip_serializing_if = "Option::is_none")]
// pub file_name: Option<String>,
// /// The size of the file in bytes.
// /// 4404019
// #[serde(skip_serializing_if = "Option::is_none")]
// pub file_size: Option<i64>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Gemini25FlashImageEditOutput {
pub images: Vec<File>,
}
pub fn gemini_25_flash_image_edit(
params: Gemini25FlashImageEditInput,
) -> FalRequest<Gemini25FlashImageEditInput, Gemini25FlashImageEditOutput> {
FalRequest::new("fal-ai/gemini-25-flash-image/edit", params)
}
@@ -0,0 +1 @@
pub mod edit;
+14
View File
@@ -893,6 +893,20 @@ pub mod fooocus;
feature = "endpoints_fal-ai_gemini-flash-edit"
)))
)]
pub mod gemini_25_flash_image;
#[cfg(any(
feature = "endpoints",
feature = "endpoints_fal-ai",
feature = "endpoints_fal-ai_gemini-flash-edit"
))]
#[cfg_attr(
docsrs,
doc(cfg(any(
feature = "endpoints",
feature = "endpoints_fal-ai",
feature = "endpoints_fal-ai_gemini-flash-edit"
)))
)]
pub mod gemini_flash_edit;
#[cfg(any(
feature = "endpoints",