mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-09 19:41:32 +00:00
pixverse v5
This commit is contained in:
1 parent
97c48c79fb
commit
c73a4470e7
8 files changed
+429
-2
No files matched your search
+152
@@ -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(())
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
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_kling_v2p6_pro_image_to_video_webhook;
|
||||
pub mod enqueue_pixverse_v5_image_to_video_webhook;
|
||||
+148
@@ -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(())
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod enqueue_kling_v2p5_turbo_pro_text_to_video_webhook;
|
||||
pub mod enqueue_kling_v2p6_pro_text_to_video_webhook;
|
||||
pub mod enqueue_kling_v2p6_pro_text_to_video_webhook;
|
||||
pub mod enqueue_pixverse_v5_text_to_video_webhook;
|
||||
@@ -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;
|
||||
+56
@@ -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)
|
||||
}
|
||||
+53
@@ -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)
|
||||
}
|
||||
Reference in new issue
Block a user