This commit is contained in:
Brandon Thomas committed 2026-05-07 21:37:49 -04:00
1 parent f13c219470
commit ebfd12fec2
17 files changed
+409 -265

No files matched your search

@@ -1,3 +1,6 @@
use std::fmt::Debug;
use std::sync::Arc;
use crate::client::router_fal_client::RouterFalClient;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::errors::provider_error::ProviderError;
@@ -13,14 +16,18 @@ pub async fn execute_fal_kling_1_6_pro(
plan: &PlanFalKling16Pro,
fal_client: &RouterFalClient,
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
let request = Kling1p6ProRequest {
image_url: plan.image_url.clone(),
end_frame_image_url: plan.end_image_url.clone(),
prompt: plan.prompt.clone(),
duration: plan.duration,
aspect_ratio: plan.aspect_ratio,
};
let outbound_request: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = Kling1p6ProArgs {
request: Kling1p6ProRequest {
image_url: plan.image_url.clone(),
end_frame_image_url: plan.end_image_url.clone(),
prompt: plan.prompt.clone(),
duration: plan.duration,
aspect_ratio: plan.aspect_ratio,
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
@@ -32,5 +39,6 @@ pub async fn execute_fal_kling_1_6_pro(
Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload {
request_id: webhook_response.request_id,
gateway_request_id: webhook_response.gateway_request_id,
maybe_outbound_request: Some(outbound_request),
}))
}
@@ -1,3 +1,6 @@
use std::fmt::Debug;
use std::sync::Arc;
use crate::client::router_fal_client::RouterFalClient;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::errors::provider_error::ProviderError;
@@ -13,13 +16,17 @@ pub async fn execute_fal_kling_2_1_master(
plan: &PlanFalKling21Master,
fal_client: &RouterFalClient,
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
let request = Kling2p1MasterRequest {
image_url: plan.image_url.clone(),
prompt: plan.prompt.clone(),
duration: plan.duration,
aspect_ratio: plan.aspect_ratio,
};
let outbound_request: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = Kling2p1MasterArgs {
request: Kling2p1MasterRequest {
image_url: plan.image_url.clone(),
prompt: plan.prompt.clone(),
duration: plan.duration,
aspect_ratio: plan.aspect_ratio,
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
@@ -31,5 +38,6 @@ pub async fn execute_fal_kling_2_1_master(
Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload {
request_id: webhook_response.request_id,
gateway_request_id: webhook_response.gateway_request_id,
maybe_outbound_request: Some(outbound_request),
}))
}
@@ -1,3 +1,6 @@
use std::fmt::Debug;
use std::sync::Arc;
use crate::client::router_fal_client::RouterFalClient;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::errors::provider_error::ProviderError;
@@ -13,14 +16,18 @@ pub async fn execute_fal_kling_2_1_pro(
plan: &PlanFalKling21Pro,
fal_client: &RouterFalClient,
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
let request = Kling2p1ProRequest {
image_url: plan.image_url.clone(),
end_frame_image_url: plan.end_image_url.clone(),
prompt: plan.prompt.clone(),
duration: plan.duration,
aspect_ratio: plan.aspect_ratio,
};
let outbound_request: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = Kling2p1ProArgs {
request: Kling2p1ProRequest {
image_url: plan.image_url.clone(),
end_frame_image_url: plan.end_image_url.clone(),
prompt: plan.prompt.clone(),
duration: plan.duration,
aspect_ratio: plan.aspect_ratio,
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
@@ -32,5 +39,6 @@ pub async fn execute_fal_kling_2_1_pro(
Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload {
request_id: webhook_response.request_id,
gateway_request_id: webhook_response.gateway_request_id,
maybe_outbound_request: Some(outbound_request),
}))
}
@@ -1,3 +1,6 @@
use std::fmt::Debug;
use std::sync::Arc;
use crate::client::router_fal_client::RouterFalClient;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::errors::provider_error::ProviderError;
@@ -22,33 +25,37 @@ pub async fn execute_fal_kling_2_5_turbo_pro(
plan: &PlanFalKling2p5TurboPro,
fal_client: &RouterFalClient,
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
let webhook_response = match &plan.mode {
let (webhook_response, outbound_request) = match &plan.mode {
FalKling2p5TurboProMode::TextToVideo => {
let request = EnqueueKlingV2p5TurboProTextToVideoRequest {
prompt: plan.prompt.clone(),
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration.map(to_t2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio),
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueKlingV2p5TurboProTextToVideoArgs {
request: EnqueueKlingV2p5TurboProTextToVideoRequest {
prompt: plan.prompt.clone(),
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration.map(to_t2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio),
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_kling_v2p5_turbo_pro_text_to_video_webhook(args).await
(enqueue_kling_v2p5_turbo_pro_text_to_video_webhook(args).await, outbound)
}
FalKling2p5TurboProMode::ImageToVideo { image_url, end_image_url } => {
let request = EnqueueKlingV2p5TurboProImageToVideoRequest {
prompt: plan.prompt.clone(),
image_url: image_url.clone(),
tail_image_url: end_image_url.clone(),
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration.map(to_i2v_duration),
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueKlingV2p5TurboProImageToVideoArgs {
request: EnqueueKlingV2p5TurboProImageToVideoRequest {
prompt: plan.prompt.clone(),
image_url: image_url.clone(),
tail_image_url: end_image_url.clone(),
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration.map(to_i2v_duration),
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_kling_v2p5_turbo_pro_image_to_video_webhook(args).await
(enqueue_kling_v2p5_turbo_pro_image_to_video_webhook(args).await, outbound)
}
};
@@ -58,6 +65,7 @@ pub async fn execute_fal_kling_2_5_turbo_pro(
Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload {
request_id: webhook_response.request_id,
gateway_request_id: webhook_response.gateway_request_id,
maybe_outbound_request: Some(outbound_request),
}))
}
@@ -1,3 +1,6 @@
use std::fmt::Debug;
use std::sync::Arc;
use crate::client::router_fal_client::RouterFalClient;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::errors::provider_error::ProviderError;
@@ -21,34 +24,38 @@ pub async fn execute_fal_kling_2_6_pro(
plan: &PlanFalKling2p6Pro,
fal_client: &RouterFalClient,
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
let webhook_response = match &plan.mode {
let (webhook_response, outbound_request) = match &plan.mode {
FalKling2p6ProMode::TextToVideo => {
let request = EnqueueKlingV2p6ProTextToVideoRequest {
prompt: plan.prompt.clone(),
generate_audio: plan.generate_audio,
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration.map(to_t2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio),
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueKlingV2p6ProTextToVideoArgs {
request: EnqueueKlingV2p6ProTextToVideoRequest {
prompt: plan.prompt.clone(),
generate_audio: plan.generate_audio,
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration.map(to_t2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio),
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_kling_v2p6_pro_text_to_video_webhook(args).await
(enqueue_kling_v2p6_pro_text_to_video_webhook(args).await, outbound)
}
FalKling2p6ProMode::ImageToVideo { image_url } => {
let request = EnqueueKlingV2p6ProImageToVideoRequest {
prompt: plan.prompt.clone(),
image_url: image_url.clone(),
generate_audio: plan.generate_audio,
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration.map(to_i2v_duration),
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueKlingV2p6ProImageToVideoArgs {
request: EnqueueKlingV2p6ProImageToVideoRequest {
prompt: plan.prompt.clone(),
image_url: image_url.clone(),
generate_audio: plan.generate_audio,
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration.map(to_i2v_duration),
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_kling_v2p6_pro_image_to_video_webhook(args).await
(enqueue_kling_v2p6_pro_image_to_video_webhook(args).await, outbound)
}
};
@@ -58,6 +65,7 @@ pub async fn execute_fal_kling_2_6_pro(
Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload {
request_id: webhook_response.request_id,
gateway_request_id: webhook_response.gateway_request_id,
maybe_outbound_request: Some(outbound_request),
}))
}
@@ -1,3 +1,6 @@
use std::fmt::Debug;
use std::sync::Arc;
use crate::client::router_fal_client::RouterFalClient;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::errors::provider_error::ProviderError;
@@ -22,38 +25,42 @@ pub async fn execute_fal_kling_3p0_pro(
plan: &PlanFalKling3p0Pro,
fal_client: &RouterFalClient,
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
let webhook_response = match &plan.mode {
let (webhook_response, outbound_request) = match &plan.mode {
FalKling3p0Mode::TextToVideo => {
let request = EnqueueKling3p0ProTextToVideoRequest {
prompt: plan.prompt.clone(),
generate_audio: plan.generate_audio,
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration.map(to_t2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio),
shot_type: None,
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueKling3p0ProTextToVideoArgs {
request: EnqueueKling3p0ProTextToVideoRequest {
prompt: plan.prompt.clone(),
generate_audio: plan.generate_audio,
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration.map(to_t2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio),
shot_type: None,
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_kling_3p0_pro_text_to_video_webhook(args).await
(enqueue_kling_3p0_pro_text_to_video_webhook(args).await, outbound)
}
FalKling3p0Mode::ImageToVideo { image_url, end_image_url } => {
let request = EnqueueKling3p0ProImageToVideoRequest {
prompt: plan.prompt.clone(),
image_url: image_url.clone(),
end_image_url: end_image_url.clone(),
generate_audio: plan.generate_audio,
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration.map(to_i2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio),
shot_type: None,
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueKling3p0ProImageToVideoArgs {
request: EnqueueKling3p0ProImageToVideoRequest {
prompt: plan.prompt.clone(),
image_url: image_url.clone(),
end_image_url: end_image_url.clone(),
generate_audio: plan.generate_audio,
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration.map(to_i2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio),
shot_type: None,
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_kling_3p0_pro_image_to_video_webhook(args).await
(enqueue_kling_3p0_pro_image_to_video_webhook(args).await, outbound)
}
};
@@ -63,6 +70,7 @@ pub async fn execute_fal_kling_3p0_pro(
Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload {
request_id: webhook_response.request_id,
gateway_request_id: webhook_response.gateway_request_id,
maybe_outbound_request: Some(outbound_request),
}))
}
@@ -1,3 +1,6 @@
use std::fmt::Debug;
use std::sync::Arc;
use crate::client::router_fal_client::RouterFalClient;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::errors::provider_error::ProviderError;
@@ -23,38 +26,42 @@ pub async fn execute_fal_kling_3p0_standard(
plan: &PlanFalKling3p0Standard,
fal_client: &RouterFalClient,
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
let webhook_response = match &plan.mode {
let (webhook_response, outbound_request) = match &plan.mode {
FalKling3p0Mode::TextToVideo => {
let request = EnqueueKling3p0StandardTextToVideoRequest {
prompt: plan.prompt.clone(),
generate_audio: plan.generate_audio,
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration.map(to_t2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio),
shot_type: None,
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueKling3p0StandardTextToVideoArgs {
request: EnqueueKling3p0StandardTextToVideoRequest {
prompt: plan.prompt.clone(),
generate_audio: plan.generate_audio,
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration.map(to_t2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio),
shot_type: None,
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_kling_3p0_standard_text_to_video_webhook(args).await
(enqueue_kling_3p0_standard_text_to_video_webhook(args).await, outbound)
}
FalKling3p0Mode::ImageToVideo { image_url, end_image_url } => {
let request = EnqueueKling3p0StandardImageToVideoRequest {
prompt: plan.prompt.clone(),
image_url: image_url.clone(),
end_image_url: end_image_url.clone(),
generate_audio: plan.generate_audio,
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration.map(to_i2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio),
shot_type: None,
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueKling3p0StandardImageToVideoArgs {
request: EnqueueKling3p0StandardImageToVideoRequest {
prompt: plan.prompt.clone(),
image_url: image_url.clone(),
end_image_url: end_image_url.clone(),
generate_audio: plan.generate_audio,
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration.map(to_i2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio),
shot_type: None,
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_kling_3p0_standard_image_to_video_webhook(args).await
(enqueue_kling_3p0_standard_image_to_video_webhook(args).await, outbound)
}
};
@@ -64,6 +71,7 @@ pub async fn execute_fal_kling_3p0_standard(
Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload {
request_id: webhook_response.request_id,
gateway_request_id: webhook_response.gateway_request_id,
maybe_outbound_request: Some(outbound_request),
}))
}
@@ -1,3 +1,6 @@
use std::fmt::Debug;
use std::sync::Arc;
use crate::client::router_fal_client::RouterFalClient;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::errors::provider_error::ProviderError;
@@ -13,17 +16,21 @@ pub async fn execute_fal_seedance_1_0_lite(
plan: &PlanFalSeedance10Lite,
fal_client: &RouterFalClient,
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
let request = Seedance1LiteRequest {
image_url: plan.image_url.clone(),
end_frame_image_url: plan.end_image_url.clone(),
prompt: plan.prompt.clone(),
duration: plan.duration,
resolution: plan.resolution,
aspect_ratio: plan.aspect_ratio,
camera_fixed: false,
seed: None,
};
let outbound_request: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = Seedance1LiteArgs {
request: Seedance1LiteRequest {
image_url: plan.image_url.clone(),
end_frame_image_url: plan.end_image_url.clone(),
prompt: plan.prompt.clone(),
duration: plan.duration,
resolution: plan.resolution,
aspect_ratio: plan.aspect_ratio,
camera_fixed: false,
seed: None,
},
request,
api_key: &fal_client.api_key,
webhook_url: fal_client.webhook_url.as_str(),
};
@@ -35,5 +42,6 @@ pub async fn execute_fal_seedance_1_0_lite(
Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload {
request_id: webhook_response.request_id,
gateway_request_id: webhook_response.gateway_request_id,
maybe_outbound_request: Some(outbound_request),
}))
}
@@ -1,3 +1,6 @@
use std::fmt::Debug;
use std::sync::Arc;
use crate::client::router_fal_client::RouterFalClient;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::errors::provider_error::ProviderError;
@@ -23,36 +26,40 @@ pub async fn execute_fal_seedance_1p5_pro(
plan: &PlanFalSeedance1p5Pro,
fal_client: &RouterFalClient,
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
let webhook_response = match &plan.mode {
let (webhook_response, outbound_request) = match &plan.mode {
FalSeedance1p5ProMode::TextToVideo => {
let request = EnqueueSeedance1p5ProTextToVideoRequest {
prompt: plan.prompt.clone(),
resolution: plan.resolution.map(to_t2v_resolution),
duration: plan.duration.map(to_t2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio),
generate_audio: plan.generate_audio,
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueSeedance1p5ProTextToVideoArgs {
request: EnqueueSeedance1p5ProTextToVideoRequest {
prompt: plan.prompt.clone(),
resolution: plan.resolution.map(to_t2v_resolution),
duration: plan.duration.map(to_t2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio),
generate_audio: plan.generate_audio,
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_seedance_1p5_pro_text_to_video_webhook(args).await
(enqueue_seedance_1p5_pro_text_to_video_webhook(args).await, outbound)
}
FalSeedance1p5ProMode::ImageToVideo { image_url, end_image_url } => {
let request = EnqueueSeedance1p5ProImageToVideoRequest {
prompt: plan.prompt.clone(),
image_url: image_url.clone(),
end_image_url: end_image_url.clone(),
resolution: plan.resolution.map(to_i2v_resolution),
duration: plan.duration.map(to_i2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio),
generate_audio: plan.generate_audio,
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueSeedance1p5ProImageToVideoArgs {
request: EnqueueSeedance1p5ProImageToVideoRequest {
prompt: plan.prompt.clone(),
image_url: image_url.clone(),
end_image_url: end_image_url.clone(),
resolution: plan.resolution.map(to_i2v_resolution),
duration: plan.duration.map(to_i2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio),
generate_audio: plan.generate_audio,
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_seedance_1p5_pro_image_to_video_webhook(args).await
(enqueue_seedance_1p5_pro_image_to_video_webhook(args).await, outbound)
}
};
@@ -62,6 +69,7 @@ pub async fn execute_fal_seedance_1p5_pro(
Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload {
request_id: webhook_response.request_id,
gateway_request_id: webhook_response.gateway_request_id,
maybe_outbound_request: Some(outbound_request),
}))
}
@@ -1,3 +1,6 @@
use std::fmt::Debug;
use std::sync::Arc;
use crate::client::router_fal_client::RouterFalClient;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::errors::provider_error::ProviderError;
@@ -22,34 +25,38 @@ pub async fn execute_fal_sora_2(
plan: &PlanFalSora2,
fal_client: &RouterFalClient,
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
let webhook_response = match &plan.mode {
let (webhook_response, outbound_request) = match &plan.mode {
FalSora2Mode::TextToVideo => {
// Text-to-video does not support Auto aspect ratio or Auto resolution.
let request = EnqueueSora2TextToVideoRequest {
prompt: plan.prompt.clone(),
resolution: plan.resolution.and_then(to_t2v_resolution),
duration: plan.duration.map(to_t2v_duration),
aspect_ratio: plan.aspect_ratio.and_then(to_t2v_aspect_ratio),
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueSora2TextToVideoArgs {
request: EnqueueSora2TextToVideoRequest {
prompt: plan.prompt.clone(),
resolution: plan.resolution.and_then(to_t2v_resolution),
duration: plan.duration.map(to_t2v_duration),
aspect_ratio: plan.aspect_ratio.and_then(to_t2v_aspect_ratio),
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_sora_2_text_to_video_webhook(args).await
(enqueue_sora_2_text_to_video_webhook(args).await, outbound)
}
FalSora2Mode::ImageToVideo { image_url } => {
let request = EnqueueSora2ImageToVideoRequest {
prompt: plan.prompt.clone(),
image_url: image_url.clone(),
duration: plan.duration.map(to_i2v_duration),
resolution: plan.resolution.map(to_i2v_resolution),
aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio),
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueSora2ImageToVideoArgs {
request: EnqueueSora2ImageToVideoRequest {
prompt: plan.prompt.clone(),
image_url: image_url.clone(),
duration: plan.duration.map(to_i2v_duration),
resolution: plan.resolution.map(to_i2v_resolution),
aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio),
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_sora_2_image_to_video_webhook(args).await
(enqueue_sora_2_image_to_video_webhook(args).await, outbound)
}
};
@@ -59,6 +66,7 @@ pub async fn execute_fal_sora_2(
Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload {
request_id: webhook_response.request_id,
gateway_request_id: webhook_response.gateway_request_id,
maybe_outbound_request: Some(outbound_request),
}))
}
@@ -1,3 +1,6 @@
use std::fmt::Debug;
use std::sync::Arc;
use crate::client::router_fal_client::RouterFalClient;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::errors::provider_error::ProviderError;
@@ -23,34 +26,38 @@ pub async fn execute_fal_sora_2_pro(
plan: &PlanFalSora2Pro,
fal_client: &RouterFalClient,
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
let webhook_response = match &plan.mode {
let (webhook_response, outbound_request) = match &plan.mode {
FalSora2ProMode::TextToVideo => {
// Text-to-video does not support Auto aspect ratio or Auto resolution.
let request = EnqueueSora2ProTextToVideoRequest {
prompt: plan.prompt.clone(),
resolution: plan.resolution.and_then(to_t2v_resolution),
duration: plan.duration.map(to_t2v_duration),
aspect_ratio: plan.aspect_ratio.and_then(to_t2v_aspect_ratio),
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueSora2ProTextToVideoArgs {
request: EnqueueSora2ProTextToVideoRequest {
prompt: plan.prompt.clone(),
resolution: plan.resolution.and_then(to_t2v_resolution),
duration: plan.duration.map(to_t2v_duration),
aspect_ratio: plan.aspect_ratio.and_then(to_t2v_aspect_ratio),
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_sora_2_pro_text_to_video_webhook(args).await
(enqueue_sora_2_pro_text_to_video_webhook(args).await, outbound)
}
FalSora2ProMode::ImageToVideo { image_url } => {
let request = EnqueueSora2ProImageToVideoRequest {
prompt: plan.prompt.clone(),
image_url: image_url.clone(),
duration: plan.duration.map(to_i2v_duration),
resolution: plan.resolution.map(to_i2v_resolution),
aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio),
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueSora2ProImageToVideoArgs {
request: EnqueueSora2ProImageToVideoRequest {
prompt: plan.prompt.clone(),
image_url: image_url.clone(),
duration: plan.duration.map(to_i2v_duration),
resolution: plan.resolution.map(to_i2v_resolution),
aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio),
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_sora_2_pro_image_to_video_webhook(args).await
(enqueue_sora_2_pro_image_to_video_webhook(args).await, outbound)
}
};
@@ -60,6 +67,7 @@ pub async fn execute_fal_sora_2_pro(
Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload {
request_id: webhook_response.request_id,
gateway_request_id: webhook_response.gateway_request_id,
maybe_outbound_request: Some(outbound_request),
}))
}
@@ -1,3 +1,6 @@
use std::fmt::Debug;
use std::sync::Arc;
use crate::client::router_fal_client::RouterFalClient;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::errors::provider_error::ProviderError;
@@ -18,42 +21,49 @@ pub async fn execute_fal_veo_2(
plan: &PlanFalVeo2,
fal_client: &RouterFalClient,
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
let webhook_response = match &plan.mode {
let (webhook_response, outbound_request) = match &plan.mode {
FalVeo2Mode::TextToVideo => {
let request = Veo2TextToVideoRequest {
prompt: plan.prompt.clone(),
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration,
aspect_ratio: plan.aspect_ratio.unwrap_or(Veo2AspectRatio::Auto),
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = Veo2TextToVideoArgs {
request: Veo2TextToVideoRequest {
prompt: plan.prompt.clone(),
negative_prompt: plan.negative_prompt.clone(),
duration: plan.duration,
aspect_ratio: plan.aspect_ratio.unwrap_or(Veo2AspectRatio::Auto),
},
request,
api_key: &fal_client.api_key,
webhook_url: fal_client.webhook_url.as_str(),
};
enqueue_veo_2_text_to_video_webhook(args)
let resp = enqueue_veo_2_text_to_video_webhook(args)
.await
.map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?
.map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?;
(resp, outbound)
}
FalVeo2Mode::ImageToVideo { image_url } => {
// Image-to-video does not support aspect_ratio — the output
// inherits the source image's aspect ratio.
let request = Veo2Request {
image_url: image_url.to_string(),
prompt: plan.prompt.clone(),
duration: plan.duration,
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = Veo2Args {
request: Veo2Request {
image_url: image_url.to_string(),
prompt: plan.prompt.clone(),
duration: plan.duration,
},
request,
api_key: &fal_client.api_key,
webhook_url: fal_client.webhook_url.as_str(),
};
enqueue_veo_2_image_to_video_webhook(args)
let resp = enqueue_veo_2_image_to_video_webhook(args)
.await
.map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?
.map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?;
(resp, outbound)
}
};
Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload {
request_id: webhook_response.request_id,
gateway_request_id: webhook_response.gateway_request_id,
maybe_outbound_request: Some(outbound_request),
}))
}
@@ -1,3 +1,6 @@
use std::fmt::Debug;
use std::sync::Arc;
use crate::client::router_fal_client::RouterFalClient;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::errors::provider_error::ProviderError;
@@ -71,45 +74,52 @@ pub async fn execute_fal_veo_3(
plan: &PlanFalVeo3,
fal_client: &RouterFalClient,
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
let webhook_response = match &plan.mode {
let (webhook_response, outbound_request) = match &plan.mode {
FalVeo3Mode::TextToVideo => {
let request = Veo3TextToVideoRequest {
prompt: plan.prompt.clone(),
negative_prompt: plan.negative_prompt.clone(),
duration: to_t2v_duration(plan.duration),
aspect_ratio: plan.t2v_aspect_ratio.map(to_t2v_aspect_ratio).unwrap_or(Veo3T2vAspectRatio::Default),
resolution: to_t2v_resolution(plan.resolution),
generate_audio: plan.generate_audio,
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = Veo3TextToVideoArgs {
request: Veo3TextToVideoRequest {
prompt: plan.prompt.clone(),
negative_prompt: plan.negative_prompt.clone(),
duration: to_t2v_duration(plan.duration),
aspect_ratio: plan.t2v_aspect_ratio.map(to_t2v_aspect_ratio).unwrap_or(Veo3T2vAspectRatio::Default),
resolution: to_t2v_resolution(plan.resolution),
generate_audio: plan.generate_audio,
},
request,
api_key: &fal_client.api_key,
webhook_url: fal_client.webhook_url.as_str(),
};
enqueue_veo_3_text_to_video_webhook(args)
let resp = enqueue_veo_3_text_to_video_webhook(args)
.await
.map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?
.map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?;
(resp, outbound)
}
FalVeo3Mode::ImageToVideo { image_url } => {
let request = Veo3Request {
image_url: image_url.to_string(),
prompt: plan.prompt.clone(),
duration: to_i2v_duration(plan.duration),
aspect_ratio: plan.i2v_aspect_ratio.map(to_i2v_aspect_ratio).unwrap_or(Veo3I2vAspectRatio::Auto),
resolution: to_i2v_resolution(plan.resolution),
generate_audio: plan.generate_audio,
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = Veo3Args {
request: Veo3Request {
image_url: image_url.to_string(),
prompt: plan.prompt.clone(),
duration: to_i2v_duration(plan.duration),
aspect_ratio: plan.i2v_aspect_ratio.map(to_i2v_aspect_ratio).unwrap_or(Veo3I2vAspectRatio::Auto),
resolution: to_i2v_resolution(plan.resolution),
generate_audio: plan.generate_audio,
},
request,
api_key: &fal_client.api_key,
webhook_url: fal_client.webhook_url.as_str(),
};
enqueue_veo_3_image_to_video_webhook(args)
let resp = enqueue_veo_3_image_to_video_webhook(args)
.await
.map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?
.map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?;
(resp, outbound)
}
};
Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload {
request_id: webhook_response.request_id,
gateway_request_id: webhook_response.gateway_request_id,
maybe_outbound_request: Some(outbound_request),
}))
}
@@ -1,3 +1,6 @@
use std::fmt::Debug;
use std::sync::Arc;
use crate::client::router_fal_client::RouterFalClient;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::errors::provider_error::ProviderError;
@@ -13,15 +16,19 @@ pub async fn execute_fal_veo_3_fast(
plan: &PlanFalVeo3Fast,
fal_client: &RouterFalClient,
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
let request = Veo3FastRequest {
prompt: plan.prompt.clone(),
image_url: plan.start_frame_url.clone(),
aspect_ratio: plan.aspect_ratio,
duration: plan.duration,
resolution: plan.resolution,
generate_audio: plan.generate_audio,
};
let outbound_request: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = Veo3FastArgs {
request: Veo3FastRequest {
prompt: plan.prompt.clone(),
image_url: plan.start_frame_url.clone(),
aspect_ratio: plan.aspect_ratio,
duration: plan.duration,
resolution: plan.resolution,
generate_audio: plan.generate_audio,
},
request,
api_key: &fal_client.api_key,
webhook_url: fal_client.webhook_url.as_str(),
};
@@ -33,5 +40,6 @@ pub async fn execute_fal_veo_3_fast(
Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload {
request_id: webhook_response.request_id,
gateway_request_id: webhook_response.gateway_request_id,
maybe_outbound_request: Some(outbound_request),
}))
}
@@ -1,3 +1,6 @@
use std::fmt::Debug;
use std::sync::Arc;
use crate::client::router_fal_client::RouterFalClient;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::errors::provider_error::ProviderError;
@@ -30,55 +33,61 @@ pub async fn execute_fal_veo_3p1(
plan: &PlanFalVeo3p1,
fal_client: &RouterFalClient,
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
let webhook_response = match &plan.mode {
let (webhook_response, outbound_request) = match &plan.mode {
FalVeo3p1Mode::TextToVideo => {
let request = EnqueueVeo3p1TextToVideoRequest {
prompt: plan.prompt.clone(),
duration: plan.duration.map(to_t2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio),
resolution: plan.resolution.map(to_t2v_resolution),
generate_audio: plan.generate_audio,
enhance_prompt: None,
negative_prompt: plan.negative_prompt.clone(),
seed: None,
auto_fix: None,
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueVeo3p1TextToVideoArgs {
request: EnqueueVeo3p1TextToVideoRequest {
prompt: plan.prompt.clone(),
duration: plan.duration.map(to_t2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio),
resolution: plan.resolution.map(to_t2v_resolution),
generate_audio: plan.generate_audio,
enhance_prompt: None,
negative_prompt: plan.negative_prompt.clone(),
seed: None,
auto_fix: None,
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_veo_3p1_text_to_video_webhook(args).await
(enqueue_veo_3p1_text_to_video_webhook(args).await, outbound)
}
FalVeo3p1Mode::ImageToVideo { start_frame_url } => {
let request = EnqueueVeo3p1ImageToVideoRequest {
prompt: plan.prompt.clone(),
image_url: start_frame_url.clone(),
duration: plan.duration.map(to_i2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio),
resolution: plan.resolution.map(to_i2v_resolution),
generate_audio: plan.generate_audio,
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueVeo3p1ImageToVideoArgs {
request: EnqueueVeo3p1ImageToVideoRequest {
prompt: plan.prompt.clone(),
image_url: start_frame_url.clone(),
duration: plan.duration.map(to_i2v_duration),
aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio),
resolution: plan.resolution.map(to_i2v_resolution),
generate_audio: plan.generate_audio,
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_veo_3p1_image_to_video_webhook(args).await
(enqueue_veo_3p1_image_to_video_webhook(args).await, outbound)
}
FalVeo3p1Mode::FirstLastFrame { first_frame_url, last_frame_url } => {
let request = EnqueueVeo3p1FirstLastFrameImageToVideoRequest {
prompt: plan.prompt.clone(),
first_frame_url: first_frame_url.clone(),
last_frame_url: last_frame_url.clone(),
duration: plan.duration.map(to_flf_duration),
aspect_ratio: plan.aspect_ratio.map(to_flf_aspect_ratio),
resolution: plan.resolution.map(to_flf_resolution),
generate_audio: plan.generate_audio,
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueVeo3p1FirstLastFrameImageToVideoArgs {
request: EnqueueVeo3p1FirstLastFrameImageToVideoRequest {
prompt: plan.prompt.clone(),
first_frame_url: first_frame_url.clone(),
last_frame_url: last_frame_url.clone(),
duration: plan.duration.map(to_flf_duration),
aspect_ratio: plan.aspect_ratio.map(to_flf_aspect_ratio),
resolution: plan.resolution.map(to_flf_resolution),
generate_audio: plan.generate_audio,
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_veo_3p1_first_last_frame_image_to_video_webhook(args).await
(enqueue_veo_3p1_first_last_frame_image_to_video_webhook(args).await, outbound)
}
};
@@ -88,6 +97,7 @@ pub async fn execute_fal_veo_3p1(
Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload {
request_id: webhook_response.request_id,
gateway_request_id: webhook_response.gateway_request_id,
maybe_outbound_request: Some(outbound_request),
}))
}
@@ -1,3 +1,6 @@
use std::fmt::Debug;
use std::sync::Arc;
use crate::client::router_fal_client::RouterFalClient;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::errors::provider_error::ProviderError;
@@ -33,55 +36,61 @@ pub async fn execute_fal_veo_3p1_fast(
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
let inner = &plan.inner;
let webhook_response = match &inner.mode {
let (webhook_response, outbound_request) = match &inner.mode {
FalVeo3p1Mode::TextToVideo => {
let request = EnqueueVeo3p1FastTextToVideoRequest {
prompt: inner.prompt.clone(),
duration: inner.duration.map(to_t2v_duration),
aspect_ratio: inner.aspect_ratio.map(to_t2v_aspect_ratio),
resolution: inner.resolution.map(to_t2v_resolution),
generate_audio: inner.generate_audio,
enhance_prompt: None,
negative_prompt: inner.negative_prompt.clone(),
seed: None,
auto_fix: None,
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueVeo3p1FastTextToVideoArgs {
request: EnqueueVeo3p1FastTextToVideoRequest {
prompt: inner.prompt.clone(),
duration: inner.duration.map(to_t2v_duration),
aspect_ratio: inner.aspect_ratio.map(to_t2v_aspect_ratio),
resolution: inner.resolution.map(to_t2v_resolution),
generate_audio: inner.generate_audio,
enhance_prompt: None,
negative_prompt: inner.negative_prompt.clone(),
seed: None,
auto_fix: None,
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_veo_3p1_fast_text_to_video_webhook(args).await
(enqueue_veo_3p1_fast_text_to_video_webhook(args).await, outbound)
}
FalVeo3p1Mode::ImageToVideo { start_frame_url } => {
let request = EnqueueVeo3p1FastImageToVideoRequest {
prompt: inner.prompt.clone(),
image_url: start_frame_url.clone(),
duration: inner.duration.map(to_i2v_duration),
aspect_ratio: inner.aspect_ratio.map(to_i2v_aspect_ratio),
resolution: inner.resolution.map(to_i2v_resolution),
generate_audio: inner.generate_audio,
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueVeo3p1FastImageToVideoArgs {
request: EnqueueVeo3p1FastImageToVideoRequest {
prompt: inner.prompt.clone(),
image_url: start_frame_url.clone(),
duration: inner.duration.map(to_i2v_duration),
aspect_ratio: inner.aspect_ratio.map(to_i2v_aspect_ratio),
resolution: inner.resolution.map(to_i2v_resolution),
generate_audio: inner.generate_audio,
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_veo_3p1_fast_image_to_video_webhook(args).await
(enqueue_veo_3p1_fast_image_to_video_webhook(args).await, outbound)
}
FalVeo3p1Mode::FirstLastFrame { first_frame_url, last_frame_url } => {
let request = EnqueueVeo3p1FastFirstLastFrameImageToVideoRequest {
prompt: inner.prompt.clone(),
first_frame_url: first_frame_url.clone(),
last_frame_url: last_frame_url.clone(),
duration: inner.duration.map(to_flf_duration),
aspect_ratio: inner.aspect_ratio.map(to_flf_aspect_ratio),
resolution: inner.resolution.map(to_flf_resolution),
generate_audio: inner.generate_audio,
};
let outbound: Arc<dyn Debug + Send + Sync> = Arc::new(request.clone());
let args = EnqueueVeo3p1FastFirstLastFrameImageToVideoArgs {
request: EnqueueVeo3p1FastFirstLastFrameImageToVideoRequest {
prompt: inner.prompt.clone(),
first_frame_url: first_frame_url.clone(),
last_frame_url: last_frame_url.clone(),
duration: inner.duration.map(to_flf_duration),
aspect_ratio: inner.aspect_ratio.map(to_flf_aspect_ratio),
resolution: inner.resolution.map(to_flf_resolution),
generate_audio: inner.generate_audio,
},
request,
webhook_url: fal_client.webhook_url.as_str(),
api_key: &fal_client.api_key,
};
enqueue_veo_3p1_fast_first_last_frame_image_to_video_webhook(args).await
(enqueue_veo_3p1_fast_first_last_frame_image_to_video_webhook(args).await, outbound)
}
};
@@ -91,6 +100,7 @@ pub async fn execute_fal_veo_3p1_fast(
Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload {
request_id: webhook_response.request_id,
gateway_request_id: webhook_response.gateway_request_id,
maybe_outbound_request: Some(outbound_request),
}))
}
@@ -1,3 +1,6 @@
use std::fmt::Debug;
use std::sync::Arc;
use muapi_client::api_types::request_id::RequestId as MuapiRequestId;
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
@@ -24,6 +27,11 @@ pub struct Seedance2proVideoResponsePayload {
pub struct FalVideoResponsePayload {
pub request_id: Option<String>,
pub gateway_request_id: Option<String>,
/// The outbound request that was sent to Fal.
/// Stored as a trait object so any Request type can be captured.
/// Use `format!("{:?}", ...)` or `format!("{:#?}", ...)` to print.
pub maybe_outbound_request: Option<Arc<dyn Debug + Send + Sync>>,
}
#[derive(Clone, Debug)]