mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-04 01:18:34 +00:00
don't need the queue pieces for now
This commit is contained in:
1 parent
29294365ce
commit
facf8a3df2
13 files changed
+4
-580
No files matched your search
@@ -1,4 +1,5 @@
|
||||
use crate::error::classify_fal_error::classify_fal_error;
|
||||
use crate::error::fal_error::FalError;
|
||||
use std::error::Error;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
@@ -37,8 +38,8 @@ impl Display for FalErrorPlus {
|
||||
|
||||
impl Error for FalErrorPlus {}
|
||||
|
||||
impl From<crate::error::fal_error::FalError> for FalErrorPlus {
|
||||
fn from(err: crate::error::fal_error::FalError) -> Self {
|
||||
impl From<FalError> for FalErrorPlus {
|
||||
fn from(err: FalError) -> Self {
|
||||
classify_fal_error(err)
|
||||
}
|
||||
}
|
||||
@@ -60,19 +61,3 @@ impl From<reqwest::Error> for FalErrorPlus {
|
||||
FalErrorPlus::ReqwestError(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Temporary: support conversion from the vendored fal crate's FalError.
|
||||
// This can be removed once all `requests/queue/*` and `utils/*` files are migrated off fal::.
|
||||
impl From<fal::FalError> for FalErrorPlus {
|
||||
fn from(err: fal::FalError) -> Self {
|
||||
// Convert the vendored FalError into our local FalError, then classify it.
|
||||
let local_err = match err {
|
||||
fal::FalError::RequestError(e) => crate::error::fal_error::FalError::RequestError(e),
|
||||
fal::FalError::SerializeError(e) => crate::error::fal_error::FalError::SerializeError(e),
|
||||
fal::FalError::Other(s) => crate::error::fal_error::FalError::Other(s),
|
||||
// ImageError and StreamError don't exist in our local FalError; stringify them.
|
||||
other => crate::error::fal_error::FalError::Other(format!("{}", other)),
|
||||
};
|
||||
classify_fal_error(local_err)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
pub mod api;
|
||||
pub mod http;
|
||||
pub mod queue;
|
||||
pub mod traits;
|
||||
pub mod webhook;
|
||||
@@ -1,68 +0,0 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::model::enqueued_request::EnqueuedRequest;
|
||||
use fal::endpoints::fal_ai::hunyuan3d::v2::v2;
|
||||
use fal::endpoints::fal_ai::hunyuan3d::v2::Hunyuan3DInput;
|
||||
use fal_client::file_to_base64_url::file_to_base64_url;
|
||||
use futures::StreamExt;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
pub struct Hunyuan2Args<'a, P: AsRef<Path>> {
|
||||
pub image_path: P,
|
||||
pub api_key: &'a FalApiKey,
|
||||
}
|
||||
|
||||
pub async fn enqueue_hunyuan2_image_to_3d<P: AsRef<Path>>(args: Hunyuan2Args<'_, P>) -> Result<EnqueuedRequest, FalErrorPlus> {
|
||||
let image_url = file_to_base64_url(args.image_path)?;
|
||||
|
||||
let request = Hunyuan3DInput {
|
||||
input_image_url: image_url,
|
||||
textured_mesh: Some(true),
|
||||
guidance_scale: None,
|
||||
num_inference_steps: None,
|
||||
octree_resolution: None,
|
||||
seed: None,
|
||||
};
|
||||
|
||||
let result = v2(request)
|
||||
.with_api_key(&args.api_key.0)
|
||||
.queue()
|
||||
.await;
|
||||
|
||||
let result = match result {
|
||||
Ok(result) => result,
|
||||
Err(err) => return Err(FalErrorPlus::from(err)),
|
||||
};
|
||||
|
||||
Ok(EnqueuedRequest::from_queue_response(&result)?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::requests::queue::enqueue_hunyuan2_image_to_3d::{enqueue_hunyuan2_image_to_3d, Hunyuan2Args};
|
||||
use errors::AnyhowResult;
|
||||
use std::fs::read_to_string;
|
||||
use test_utils::test_file_path::test_file_path;
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test() -> AnyhowResult<()> {
|
||||
let image = test_file_path("test_data/image/juno.jpg")?;
|
||||
|
||||
// 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 = Hunyuan2Args {
|
||||
image_path: image,
|
||||
api_key: &api_key,
|
||||
};
|
||||
|
||||
let result = enqueue_hunyuan2_image_to_3d(args).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::model::enqueued_request::EnqueuedRequest;
|
||||
use fal::endpoints::fal_ai::flux_pro::v1_1_ultra::v1_1_ultra;
|
||||
use fal::endpoints::fal_ai::flux_pro::v1_1_ultra::FluxProUltraTextToImageInput;
|
||||
use futures::StreamExt;
|
||||
use std::io::Write;
|
||||
|
||||
pub struct FluxPro11UltraTextToImageArgs<'a> {
|
||||
pub prompt: &'a str,
|
||||
pub api_key: &'a FalApiKey,
|
||||
// TODO: Size parameter
|
||||
}
|
||||
|
||||
pub async fn enqueue_flux_pro_11_ultra_text_to_image(args: FluxPro11UltraTextToImageArgs<'_>) -> Result<EnqueuedRequest, FalErrorPlus> {
|
||||
let request = FluxProUltraTextToImageInput {
|
||||
prompt: args.prompt.to_string(),
|
||||
// Maybe expose
|
||||
aspect_ratio: None, // Default is "16:9"
|
||||
num_images: Some(1), // Default is 1
|
||||
seed: None,
|
||||
raw: Some(true), // Generate less processed, more natural-looking images. Default is false.
|
||||
// Maybe abstract
|
||||
enable_safety_checker: Some(false),
|
||||
safety_tolerance: Some("5".to_string()), // 1 is most strict, 5 is most permissive
|
||||
// Constants
|
||||
output_format: Some("png".to_string()),
|
||||
sync_mode: None, // Synchronous / slow
|
||||
};
|
||||
|
||||
let result = v1_1_ultra(request)
|
||||
.with_api_key(&args.api_key.0)
|
||||
.queue()
|
||||
.await;
|
||||
|
||||
let result = match result {
|
||||
Ok(result) => result,
|
||||
Err(err) => return Err(FalErrorPlus::from(err)),
|
||||
};
|
||||
|
||||
Ok(EnqueuedRequest::from_queue_response(&result)?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::requests::queue::image_gen::enqueue_flux_pro_11_ultra_text_to_image::{enqueue_flux_pro_11_ultra_text_to_image, FluxPro11UltraTextToImageArgs};
|
||||
use errors::AnyhowResult;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_flux_pro() -> 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 = FluxPro11UltraTextToImageArgs {
|
||||
prompt: "a corgi smiles at the camera, inside retro video game store, lots of sci-fi props from Cowboy Bebop, photorealistic",
|
||||
api_key: &api_key,
|
||||
};
|
||||
|
||||
let result = enqueue_flux_pro_11_ultra_text_to_image(args).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
-62
@@ -1,62 +0,0 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::model::enqueued_request::EnqueuedRequest;
|
||||
use fal::endpoints::fal_ai::recraft_v3::recraft_v3;
|
||||
use fal::endpoints::fal_ai::recraft_v3::ImageSizeProperty;
|
||||
use fal::endpoints::fal_ai::recraft_v3::TextToImageInput;
|
||||
use futures::StreamExt;
|
||||
use std::io::Write;
|
||||
|
||||
pub struct Recraft3TextToImageArgs<'a> {
|
||||
pub prompt: &'a str,
|
||||
pub api_key: &'a FalApiKey,
|
||||
// TODO: Size parameter
|
||||
}
|
||||
|
||||
pub async fn enqueue_recraft3_text_to_image(args: Recraft3TextToImageArgs<'_>) -> Result<EnqueuedRequest, FalErrorPlus> {
|
||||
let request = TextToImageInput {
|
||||
image_size: Some(ImageSizeProperty::SquareHd),
|
||||
prompt: args.prompt.to_string(),
|
||||
style: None, // eg. "realistic_image"
|
||||
style_id: None, // LoRA.
|
||||
colors: None, // Preferable colors. We can offer this later.
|
||||
};
|
||||
|
||||
let result = recraft_v3(request)
|
||||
.with_api_key(&args.api_key.0)
|
||||
.queue()
|
||||
.await;
|
||||
|
||||
let result = match result {
|
||||
Ok(result) => result,
|
||||
Err(err) => return Err(FalErrorPlus::from(err)),
|
||||
};
|
||||
|
||||
Ok(EnqueuedRequest::from_queue_response(&result)?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::requests::queue::image_gen::enqueue_recraft3_text_to_image::{enqueue_recraft3_text_to_image, Recraft3TextToImageArgs};
|
||||
use errors::AnyhowResult;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_recraft3() -> 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 = Recraft3TextToImageArgs {
|
||||
prompt: "a corgi looks out over the water",
|
||||
api_key: &api_key,
|
||||
};
|
||||
|
||||
let result = enqueue_recraft3_text_to_image(args).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
pub mod enqueue_flux_pro_11_ultra_text_to_image;
|
||||
pub mod enqueue_recraft3_text_to_image;
|
||||
@@ -1,4 +0,0 @@
|
||||
pub mod enqueue_hunyuan2_image_to_3d;
|
||||
pub mod image_gen;
|
||||
pub mod remove_background_rembg;
|
||||
pub mod video_gen;
|
||||
@@ -1,74 +0,0 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use fal::endpoints::fal_ai::imageutils::rembg::RemoveBackgroundInput;
|
||||
use fal::prelude::fal_ai::imageutils::rembg::rembg;
|
||||
use fal::prelude::*;
|
||||
use fal_client::file_to_base64_url::file_to_base64_url;
|
||||
use futures::StreamExt;
|
||||
use std::path::Path;
|
||||
use url::Url;
|
||||
|
||||
pub struct RemBgResponse {
|
||||
pub image_url: Url,
|
||||
}
|
||||
|
||||
/// remove background using `fal_ai/imageutils/rembg`
|
||||
pub async fn remove_background_rembg<P: AsRef<Path>>(image_path: P, api_key: &FalApiKey) -> Result<RemBgResponse, FalErrorPlus> {
|
||||
let image_url = file_to_base64_url(image_path)?;
|
||||
|
||||
let request = RemoveBackgroundInput {
|
||||
image_url,
|
||||
crop_to_bbox: None,
|
||||
sync_mode: None
|
||||
};
|
||||
|
||||
let result = rembg(request)
|
||||
.with_api_key(&api_key.0)
|
||||
.queue()
|
||||
.await;
|
||||
|
||||
let result = match result {
|
||||
Ok(result) => result,
|
||||
Err(err) => return Err(FalErrorPlus::from(err)),
|
||||
};
|
||||
|
||||
let mut stream = result.stream(true).await?;
|
||||
|
||||
while let Some(status) = stream.next().await {
|
||||
let status = status?;
|
||||
if status.status == Status::Completed {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let output = result.response().await?;
|
||||
|
||||
let url = Url::parse(&output.image.url)?;
|
||||
|
||||
Ok(RemBgResponse {
|
||||
image_url: url,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::requests::queue::remove_background_rembg::remove_background_rembg;
|
||||
use errors::AnyhowResult;
|
||||
use std::fs::read_to_string;
|
||||
use test_utils::test_file_path::test_file_path;
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_remove_background_rembg() -> AnyhowResult<()> {
|
||||
let image = test_file_path("test_data/image/juno.jpg")?;
|
||||
|
||||
// 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 result = remove_background_rembg(image, &api_key).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
-101
@@ -1,101 +0,0 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::model::enqueued_request::EnqueuedRequest;
|
||||
use fal::endpoints::fal_ai::kling_video::v1_6::pro::image_to_video::{image_to_video, ProImageToVideoRequest};
|
||||
use fal_client::file_to_base64_url::file_to_base64_url;
|
||||
use futures::StreamExt;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
pub struct Kling16ProArgs<'a, P: AsRef<Path>> {
|
||||
pub image_path: P,
|
||||
pub prompt: &'a str,
|
||||
pub api_key: &'a FalApiKey,
|
||||
pub duration: Kling16ProDuration,
|
||||
pub aspect_ratio: Kling16ProAspectRatio,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Kling16ProDuration {
|
||||
Default,
|
||||
FiveSeconds,
|
||||
TenSeconds,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Kling16ProAspectRatio {
|
||||
Square, // 1:1
|
||||
WideSixteenNine, // 16:9
|
||||
TallNineSixteen, // 9:16
|
||||
}
|
||||
|
||||
pub async fn enqueue_kling_16_pro_image_to_video<P: AsRef<Path>>(args: Kling16ProArgs<'_, P>) -> Result<EnqueuedRequest, FalErrorPlus> {
|
||||
let image_url = file_to_base64_url(args.image_path)?;
|
||||
|
||||
let duration = match args.duration{
|
||||
Kling16ProDuration::Default => None,
|
||||
Kling16ProDuration::FiveSeconds => Some("5".to_string()), // Gross...
|
||||
Kling16ProDuration::TenSeconds => Some("10".to_string()),
|
||||
};
|
||||
|
||||
let aspect_ratio = match args.aspect_ratio {
|
||||
Kling16ProAspectRatio::Square => Some("1:1".to_string()),
|
||||
Kling16ProAspectRatio::WideSixteenNine => Some("16:9".to_string()),
|
||||
Kling16ProAspectRatio::TallNineSixteen => Some("9:16".to_string()),
|
||||
};
|
||||
|
||||
let request = ProImageToVideoRequest {
|
||||
image_url,
|
||||
prompt: args.prompt.to_string(),
|
||||
aspect_ratio,
|
||||
duration,
|
||||
// Maybe expose these later
|
||||
cfg_scale: None,
|
||||
negative_prompt: None,
|
||||
tail_image_url: None,
|
||||
};
|
||||
|
||||
let result = image_to_video(request)
|
||||
.with_api_key(&args.api_key.0)
|
||||
.queue()
|
||||
.await;
|
||||
|
||||
let result = match result {
|
||||
Ok(result) => result,
|
||||
Err(err) => return Err(FalErrorPlus::from(err)),
|
||||
};
|
||||
|
||||
Ok(EnqueuedRequest::from_queue_response(&result)?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::requests::queue::video_gen::enqueue_kling_16_pro_image_to_video::{enqueue_kling_16_pro_image_to_video, Kling16ProArgs, Kling16ProAspectRatio, Kling16ProDuration};
|
||||
use errors::AnyhowResult;
|
||||
use std::fs::read_to_string;
|
||||
use test_utils::test_file_path::test_file_path;
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_kling16_video() -> AnyhowResult<()> {
|
||||
let image = test_file_path("test_data/image/juno.jpg")?;
|
||||
|
||||
// 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 = Kling16ProArgs {
|
||||
image_path: image,
|
||||
prompt: "a corgi looks out over the water",
|
||||
api_key: &api_key,
|
||||
duration: Kling16ProDuration::Default,
|
||||
aspect_ratio: Kling16ProAspectRatio::Square,
|
||||
};
|
||||
|
||||
let result = enqueue_kling_16_pro_image_to_video(args).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::model::enqueued_request::EnqueuedRequest;
|
||||
use fal::endpoints::fal_ai::minimax::image_to_video::image_to_video;
|
||||
use fal::endpoints::fal_ai::minimax::image_to_video::ImageToVideoRequest;
|
||||
use fal_client::file_to_base64_url::file_to_base64_url;
|
||||
use futures::StreamExt;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
pub struct Minimax01Args<'a, P: AsRef<Path>> {
|
||||
pub image_path: P,
|
||||
pub prompt: &'a str,
|
||||
pub api_key: &'a FalApiKey,
|
||||
}
|
||||
|
||||
pub async fn enqueue_minimax_01_image_to_video<P: AsRef<Path>>(args: Minimax01Args<'_, P>) -> Result<EnqueuedRequest, FalErrorPlus> {
|
||||
let image_url = file_to_base64_url(args.image_path)?;
|
||||
|
||||
let request = ImageToVideoRequest {
|
||||
image_url,
|
||||
prompt: args.prompt.to_string(),
|
||||
prompt_optimizer: None,
|
||||
};
|
||||
|
||||
let result = image_to_video(request)
|
||||
.with_api_key(&args.api_key.0)
|
||||
.queue()
|
||||
.await;
|
||||
|
||||
let result = match result {
|
||||
Ok(result) => result,
|
||||
Err(err) => return Err(FalErrorPlus::from(err)),
|
||||
};
|
||||
|
||||
Ok(EnqueuedRequest::from_queue_response(&result)?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::requests::queue::video_gen::enqueue_minimax_01_image_to_video::{enqueue_minimax_01_image_to_video, Minimax01Args};
|
||||
use errors::AnyhowResult;
|
||||
use std::fs::read_to_string;
|
||||
use test_utils::test_file_path::test_file_path;
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_minimax_video() -> AnyhowResult<()> {
|
||||
let image = test_file_path("test_data/image/juno.jpg")?;
|
||||
|
||||
// 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 = Minimax01Args {
|
||||
image_path: image,
|
||||
prompt: "a dog jumps into the water",
|
||||
api_key: &api_key,
|
||||
};
|
||||
|
||||
let result = enqueue_minimax_01_image_to_video(args).await?;
|
||||
|
||||
println!("Request ID: {:?}", result.request_id);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
pub mod enqueue_kling_16_pro_image_to_video;
|
||||
pub mod enqueue_minimax_01_image_to_video;
|
||||
@@ -1,3 +1,2 @@
|
||||
pub mod clone_queue_payload;
|
||||
pub mod clone_queue_response;
|
||||
pub mod queue_status_checker;
|
||||
pub mod clone_queue_response;
|
||||
@@ -1,109 +0,0 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::model::enqueued_request::EnqueuedRequest;
|
||||
use crate::model::fal_endpoint::FalEndpoint;
|
||||
use anyhow::anyhow;
|
||||
use fal::endpoints::fal_ai::flux_pro::v1_1_ultra::Output;
|
||||
use fal::endpoints::fal_ai::hunyuan3d::v2::ObjectOutput;
|
||||
use fal::endpoints::fal_ai::kling_video::v1_6::pro::effects::I2VOutput;
|
||||
use fal::endpoints::fal_ai::minimax::image_to_video::VideoOutput;
|
||||
use fal::endpoints::fal_ai::recraft_v3::TextToImageOutput;
|
||||
use fal::prelude::QueueResponse;
|
||||
use fal::queue::{Queue, QueueStatus};
|
||||
use reqwest::Client;
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
pub struct QueueStatusChecker {
|
||||
api_key: FalApiKey,
|
||||
}
|
||||
|
||||
impl QueueStatusChecker {
|
||||
pub fn new(api_key: FalApiKey) -> Self {
|
||||
Self { api_key }
|
||||
}
|
||||
|
||||
pub async fn check_status(&self, request: &EnqueuedRequest) -> Result<QueueStatus, FalErrorPlus> {
|
||||
match &request.fal_endpoint {
|
||||
FalEndpoint::FluxProUltraTextToImage => {
|
||||
let queue = self.make_queue::<Output>(&request);
|
||||
let status = queue.status(false).await?;
|
||||
Ok(status)
|
||||
}
|
||||
FalEndpoint::Hunyuan3d2Base => {
|
||||
let queue = self.make_queue::<ObjectOutput>(&request);
|
||||
let status = queue.status(false).await?;
|
||||
Ok(status)
|
||||
}
|
||||
FalEndpoint::Kling16ImageToVideo => {
|
||||
let queue = self.make_queue::<I2VOutput>(&request);
|
||||
let status = queue.status(false).await?;
|
||||
Ok(status)
|
||||
}
|
||||
FalEndpoint::Minimax01ImageToVideo => {
|
||||
let queue = self.make_queue::<VideoOutput>(&request); // Assuming Minimax uses the same output type
|
||||
let status = queue.status(false).await?;
|
||||
Ok(status)
|
||||
}
|
||||
FalEndpoint::RecraftV3TextToImage => {
|
||||
let queue = self.make_queue::<TextToImageOutput>(&request);
|
||||
let status = queue.status(false).await?;
|
||||
Ok(status)
|
||||
}
|
||||
FalEndpoint::Other(endpoint) => {
|
||||
Err(FalErrorPlus::UnhandledEndpoint(format!("Unsupported endpoint: {}", endpoint)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_download_url(&self, request: &EnqueuedRequest) -> Result<String, FalErrorPlus> {
|
||||
match &request.fal_endpoint {
|
||||
FalEndpoint::FluxProUltraTextToImage => {
|
||||
let queue = self.make_queue::<Output>(&request);
|
||||
let response = queue.response().await?;
|
||||
// TODO(bt,2025-05-26): Handle multiple images
|
||||
Ok(response.images.first()
|
||||
.ok_or_else(|| FalErrorPlus::AnyhowError(anyhow!("No images returned")))?
|
||||
.url.clone())
|
||||
}
|
||||
FalEndpoint::Hunyuan3d2Base => {
|
||||
let queue = self.make_queue::<ObjectOutput>(&request);
|
||||
let response = queue.response().await?;
|
||||
Ok(response.model_mesh.url)
|
||||
}
|
||||
FalEndpoint::Kling16ImageToVideo => {
|
||||
let queue = self.make_queue::<I2VOutput>(&request);
|
||||
let response = queue.response().await?;
|
||||
Ok(response.video.url)
|
||||
}
|
||||
FalEndpoint::Minimax01ImageToVideo => {
|
||||
let queue = self.make_queue::<VideoOutput>(&request); // Assuming Minimax uses the same output type
|
||||
let response = queue.response().await?;
|
||||
Ok(response.video.url)
|
||||
}
|
||||
FalEndpoint::RecraftV3TextToImage => {
|
||||
let queue = self.make_queue::<TextToImageOutput>(&request);
|
||||
let response = queue.response().await?;
|
||||
Ok(response.images.first()
|
||||
.ok_or_else(|| FalErrorPlus::AnyhowError(anyhow!("No images returned")))?
|
||||
.url.clone())
|
||||
}
|
||||
FalEndpoint::Other(endpoint) => {
|
||||
Err(FalErrorPlus::UnhandledEndpoint(format!("Unsupported endpoint: {}", endpoint)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_queue<T: DeserializeOwned>(&self, request: &EnqueuedRequest) -> Queue<T> {
|
||||
let client = Client::new();
|
||||
let endpoint = request.fal_endpoint.url();
|
||||
|
||||
let payload = QueueResponse {
|
||||
request_id: request.request_id.0.clone(),
|
||||
response_url: request.response_url.clone(),
|
||||
status_url: request.status_url.clone(),
|
||||
cancel_url: request.cancel_url.clone(),
|
||||
};
|
||||
|
||||
Queue::new(client, endpoint, self.api_key.0.clone(), payload)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user