diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_kling3p0_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_kling3p0_pro.rs index 30de768ff1..29be99c281 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_kling3p0_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_kling3p0_pro.rs @@ -1,7 +1,7 @@ use artcraft_api_defs::generate::video::multi_function::kling_3p0_pro_multi_function_video_gen::Kling3p0ProMultiFunctionVideoGenDuration; use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator; use fal_client::requests::webhook::video::text::enqueue_kling_3p0_pro_text_to_video_webhook::{ - EnqueueKling3p0ProTextToVideoArgs, + EnqueueKling3p0ProTextToVideoRequest, EnqueueKling3p0ProTextToVideoDuration, }; @@ -29,19 +29,16 @@ pub(crate) fn estimate_video_cost_artcraft_kling3p0_pro( }); // Use text-to-video cost calculator (same pricing for both modes) - let api_key = fal_client::creds::fal_api_key::FalApiKey::from_str(""); - let args = EnqueueKling3p0ProTextToVideoArgs { + let req = EnqueueKling3p0ProTextToVideoRequest { prompt: String::new(), generate_audio: plan.generate_audio, negative_prompt: None, duration, aspect_ratio: None, shot_type: None, - webhook_url: "https://example.com", - api_key: &api_key, }; - let cost_in_usd_cents = args.calculate_cost_in_cents(); + let cost_in_usd_cents = req.calculate_cost_in_cents(); VideoGenerationCostEstimate { cost_in_credits: Some(cost_in_usd_cents), diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_kling3p0_standard.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_kling3p0_standard.rs index a621de661c..38f519020c 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_kling3p0_standard.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_kling3p0_standard.rs @@ -1,7 +1,7 @@ use artcraft_api_defs::generate::video::multi_function::kling_3p0_standard_multi_function_video_gen::Kling3p0StandardMultiFunctionVideoGenDuration; use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator; use fal_client::requests::webhook::video::text::enqueue_kling_3p0_standard_text_to_video_webhook::{ - EnqueueKling3p0StandardTextToVideoArgs, + EnqueueKling3p0StandardTextToVideoRequest, EnqueueKling3p0StandardTextToVideoDuration, }; @@ -29,19 +29,16 @@ pub(crate) fn estimate_video_cost_artcraft_kling3p0_standard( }); // Use text-to-video cost calculator (same pricing for both modes) - let api_key = fal_client::creds::fal_api_key::FalApiKey::from_str(""); - let args = EnqueueKling3p0StandardTextToVideoArgs { + let req = EnqueueKling3p0StandardTextToVideoRequest { prompt: String::new(), generate_audio: plan.generate_audio, negative_prompt: None, duration, aspect_ratio: None, shot_type: None, - webhook_url: "https://example.com", - api_key: &api_key, }; - let cost_in_usd_cents = args.calculate_cost_in_cents(); + let cost_in_usd_cents = req.calculate_cost_in_cents(); VideoGenerationCostEstimate { cost_in_credits: Some(cost_in_usd_cents), diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_seedance1p5_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_seedance1p5_pro.rs index 0b47f8d5c7..ad8f83549d 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_seedance1p5_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_seedance1p5_pro.rs @@ -1,7 +1,7 @@ use artcraft_api_defs::generate::video::multi_function::seedance_1p5_pro_multi_function_video_gen::Seedance1p5ProMultiFunctionVideoGenDuration; use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator; use fal_client::requests::webhook::video::text::enqueue_seedance_1p5_pro_text_to_video_webhook::{ - EnqueueSeedance1p5ProTextToVideoArgs, + EnqueueSeedance1p5ProTextToVideoRequest, EnqueueSeedance1p5ProTextToVideoDuration, EnqueueSeedance1p5ProTextToVideoResolution, }; @@ -33,18 +33,15 @@ pub(crate) fn estimate_video_cost_artcraft_seedance1p5_pro( }); // Use text-to-video cost calculator (same pricing for both modes) - let api_key = fal_client::creds::fal_api_key::FalApiKey::from_str(""); - let args = EnqueueSeedance1p5ProTextToVideoArgs { + let req = EnqueueSeedance1p5ProTextToVideoRequest { prompt: String::new(), duration, resolution, aspect_ratio: None, generate_audio: plan.generate_audio, - webhook_url: "https://example.com", - api_key: &api_key, }; - let cost_in_usd_cents = args.calculate_cost_in_cents(); + let cost_in_usd_cents = req.calculate_cost_in_cents(); VideoGenerationCostEstimate { cost_in_credits: Some(cost_in_usd_cents), diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/fal/estimate_video_cost_fal_seedance_1p5_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/fal/estimate_video_cost_fal_seedance_1p5_pro.rs index a22777a0c7..ac033d6ed5 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/fal/estimate_video_cost_fal_seedance_1p5_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/fal/estimate_video_cost_fal_seedance_1p5_pro.rs @@ -1,7 +1,6 @@ -use fal_client::creds::fal_api_key::FalApiKey; use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator; use fal_client::requests::webhook::video::text::enqueue_seedance_1p5_pro_text_to_video_webhook::{ - EnqueueSeedance1p5ProTextToVideoArgs, EnqueueSeedance1p5ProTextToVideoDuration, + EnqueueSeedance1p5ProTextToVideoRequest, EnqueueSeedance1p5ProTextToVideoDuration, EnqueueSeedance1p5ProTextToVideoResolution, }; @@ -15,18 +14,15 @@ pub(crate) fn estimate_video_cost_fal_seedance_1p5_pro( ) -> VideoGenerationCostEstimate { // Seedance 1.5 Pro t2v and i2v have identical pricing; delegate to the t2v // calculator to guarantee parity with billing. - let api_key = FalApiKey::from_str(""); - let args = EnqueueSeedance1p5ProTextToVideoArgs { + let req = EnqueueSeedance1p5ProTextToVideoRequest { prompt: String::new(), resolution: plan.resolution.map(to_t2v_resolution), duration: plan.duration.map(to_t2v_duration), aspect_ratio: None, generate_audio: plan.generate_audio, - webhook_url: "https://example.com", - api_key: &api_key, }; - let cost_in_usd_cents = args.calculate_cost_in_cents(); + let cost_in_usd_cents = req.calculate_cost_in_cents(); VideoGenerationCostEstimate { cost_in_credits: Some(cost_in_usd_cents), diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_5_turbo_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_5_turbo_pro.rs index aa7b7b27a6..c6c80912f1 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_5_turbo_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_5_turbo_pro.rs @@ -14,7 +14,8 @@ use fal_client::requests::webhook::video::image::enqueue_kling_v2p5_turbo_pro_im }; use fal_client::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, + EnqueueKlingV2p5TurboProTextToVideoRequest, EnqueueKlingV2p5TurboProTextToVideoAspectRatio, + EnqueueKlingV2p5TurboProTextToVideoDurationSeconds, }; pub async fn execute_fal_kling_2_5_turbo_pro( @@ -24,10 +25,12 @@ pub async fn execute_fal_kling_2_5_turbo_pro( let webhook_response = match &plan.mode { FalKling2p5TurboProMode::TextToVideo => { let args = EnqueueKlingV2p5TurboProTextToVideoArgs { - 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: 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), + }, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_6_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_6_pro.rs index 4d2a9ba823..5f0e316764 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_6_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_6_pro.rs @@ -13,7 +13,8 @@ use fal_client::requests::webhook::video::image::enqueue_kling_v2p6_pro_image_to }; use fal_client::requests::webhook::video::text::enqueue_kling_v2p6_pro_text_to_video_webhook::{ enqueue_kling_v2p6_pro_text_to_video_webhook, EnqueueKlingV2p6ProTextToVideoArgs, - EnqueueKlingV2p6ProTextToVideoAspectRatio, EnqueueKlingV2p6ProTextToVideoDurationSeconds, + EnqueueKlingV2p6ProTextToVideoRequest, EnqueueKlingV2p6ProTextToVideoAspectRatio, + EnqueueKlingV2p6ProTextToVideoDurationSeconds, }; pub async fn execute_fal_kling_2_6_pro( @@ -23,11 +24,13 @@ pub async fn execute_fal_kling_2_6_pro( let webhook_response = match &plan.mode { FalKling2p6ProMode::TextToVideo => { let args = EnqueueKlingV2p6ProTextToVideoArgs { - 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: 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), + }, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_3p0_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_3p0_pro.rs index ac992e0025..292ce7179b 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_3p0_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_3p0_pro.rs @@ -14,7 +14,8 @@ use fal_client::requests::webhook::video::image::enqueue_kling_3p0_pro_image_to_ }; use fal_client::requests::webhook::video::text::enqueue_kling_3p0_pro_text_to_video_webhook::{ enqueue_kling_3p0_pro_text_to_video_webhook, EnqueueKling3p0ProTextToVideoArgs, - EnqueueKling3p0ProTextToVideoAspectRatio, EnqueueKling3p0ProTextToVideoDuration, + EnqueueKling3p0ProTextToVideoRequest, EnqueueKling3p0ProTextToVideoAspectRatio, + EnqueueKling3p0ProTextToVideoDuration, }; pub async fn execute_fal_kling_3p0_pro( @@ -24,12 +25,14 @@ pub async fn execute_fal_kling_3p0_pro( let webhook_response = match &plan.mode { FalKling3p0Mode::TextToVideo => { let args = EnqueueKling3p0ProTextToVideoArgs { - 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: 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, + }, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_3p0_standard.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_3p0_standard.rs index 263627bd42..7d83a81ead 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_3p0_standard.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_3p0_standard.rs @@ -15,7 +15,8 @@ use fal_client::requests::webhook::video::image::enqueue_kling_3p0_standard_imag }; use fal_client::requests::webhook::video::text::enqueue_kling_3p0_standard_text_to_video_webhook::{ enqueue_kling_3p0_standard_text_to_video_webhook, EnqueueKling3p0StandardTextToVideoArgs, - EnqueueKling3p0StandardTextToVideoAspectRatio, EnqueueKling3p0StandardTextToVideoDuration, + EnqueueKling3p0StandardTextToVideoRequest, EnqueueKling3p0StandardTextToVideoAspectRatio, + EnqueueKling3p0StandardTextToVideoDuration, }; pub async fn execute_fal_kling_3p0_standard( @@ -25,12 +26,14 @@ pub async fn execute_fal_kling_3p0_standard( let webhook_response = match &plan.mode { FalKling3p0Mode::TextToVideo => { let args = EnqueueKling3p0StandardTextToVideoArgs { - 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: 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, + }, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_seedance_1p5_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_seedance_1p5_pro.rs index 4fc45f8782..ce048e3932 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_seedance_1p5_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_seedance_1p5_pro.rs @@ -15,8 +15,8 @@ use fal_client::requests::webhook::video::image::enqueue_seedance_1p5_pro_image_ }; use fal_client::requests::webhook::video::text::enqueue_seedance_1p5_pro_text_to_video_webhook::{ enqueue_seedance_1p5_pro_text_to_video_webhook, EnqueueSeedance1p5ProTextToVideoArgs, - EnqueueSeedance1p5ProTextToVideoAspectRatio, EnqueueSeedance1p5ProTextToVideoDuration, - EnqueueSeedance1p5ProTextToVideoResolution, + EnqueueSeedance1p5ProTextToVideoRequest, EnqueueSeedance1p5ProTextToVideoAspectRatio, + EnqueueSeedance1p5ProTextToVideoDuration, EnqueueSeedance1p5ProTextToVideoResolution, }; pub async fn execute_fal_seedance_1p5_pro( @@ -26,11 +26,13 @@ pub async fn execute_fal_seedance_1p5_pro( let webhook_response = match &plan.mode { FalSeedance1p5ProMode::TextToVideo => { let args = EnqueueSeedance1p5ProTextToVideoArgs { - 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: 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, + }, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_sora_2.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_sora_2.rs index 666558a147..db159544c6 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_sora_2.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_sora_2.rs @@ -14,8 +14,8 @@ use fal_client::requests::webhook::video::image::enqueue_sora_2_image_to_video_w }; use fal_client::requests::webhook::video::text::enqueue_sora_2_text_to_video_webhook::{ enqueue_sora_2_text_to_video_webhook, EnqueueSora2TextToVideoArgs, - EnqueueSora2TextToVideoAspectRatio, EnqueueSora2TextToVideoDurationSeconds, - EnqueueSora2TextToVideoResolution, + EnqueueSora2TextToVideoRequest, EnqueueSora2TextToVideoAspectRatio, + EnqueueSora2TextToVideoDurationSeconds, EnqueueSora2TextToVideoResolution, }; pub async fn execute_fal_sora_2( @@ -26,10 +26,12 @@ pub async fn execute_fal_sora_2( FalSora2Mode::TextToVideo => { // Text-to-video does not support Auto aspect ratio or Auto resolution. let args = EnqueueSora2TextToVideoArgs { - 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: 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), + }, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_sora_2_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_sora_2_pro.rs index c508312fa9..870fa44a57 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_sora_2_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_sora_2_pro.rs @@ -15,8 +15,8 @@ use fal_client::requests::webhook::video::image::enqueue_sora_2_pro_image_to_vid }; use fal_client::requests::webhook::video::text::enqueue_sora_2_pro_text_to_video_webhook::{ enqueue_sora_2_pro_text_to_video_webhook, EnqueueSora2ProTextToVideoArgs, - EnqueueSora2ProTextToVideoAspectRatio, EnqueueSora2ProTextToVideoDurationSeconds, - EnqueueSora2ProTextToVideoResolution, + EnqueueSora2ProTextToVideoRequest, EnqueueSora2ProTextToVideoAspectRatio, + EnqueueSora2ProTextToVideoDurationSeconds, EnqueueSora2ProTextToVideoResolution, }; pub async fn execute_fal_sora_2_pro( @@ -27,10 +27,12 @@ pub async fn execute_fal_sora_2_pro( FalSora2ProMode::TextToVideo => { // Text-to-video does not support Auto aspect ratio or Auto resolution. let args = EnqueueSora2ProTextToVideoArgs { - 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: 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), + }, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_2.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_2.rs index 2bdbcebdca..3d3f54547d 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_2.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_2.rs @@ -11,7 +11,7 @@ use fal_client::requests::webhook::video::image::enqueue_veo_2_image_to_video_we enqueue_veo_2_image_to_video_webhook, Veo2Args, Veo2AspectRatio, Veo2Request, }; use fal_client::requests::webhook::video::text::enqueue_veo_2_text_to_video_webhook::{ - enqueue_veo_2_text_to_video_webhook, Veo2TextToVideoArgs, + enqueue_veo_2_text_to_video_webhook, Veo2TextToVideoArgs, Veo2TextToVideoRequest, }; pub async fn execute_fal_veo_2( @@ -21,11 +21,13 @@ pub async fn execute_fal_veo_2( let webhook_response = match &plan.mode { FalVeo2Mode::TextToVideo => { let args = Veo2TextToVideoArgs { - prompt: plan.prompt.as_str(), - negative_prompt: plan.negative_prompt.as_deref(), + request: Veo2TextToVideoRequest { + prompt: plan.prompt.clone(), + negative_prompt: plan.negative_prompt.clone(), + duration: plan.duration, + aspect_ratio: plan.aspect_ratio.unwrap_or(Veo2AspectRatio::Auto), + }, api_key: &fal_client.api_key, - duration: plan.duration, - aspect_ratio: plan.aspect_ratio.unwrap_or(Veo2AspectRatio::Auto), webhook_url: fal_client.webhook_url.as_str(), }; enqueue_veo_2_text_to_video_webhook(args) diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3.rs index 4e02c0d1b6..43dcc9a013 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3.rs @@ -14,7 +14,7 @@ use fal_client::requests::webhook::video::image::enqueue_veo_3_image_to_video_we }; use fal_client::requests::webhook::video::text::enqueue_veo_3_text_to_video_webhook::{ enqueue_veo_3_text_to_video_webhook, Veo3T2vAspectRatio, Veo3T2vDuration, Veo3T2vResolution, - Veo3TextToVideoArgs, + Veo3TextToVideoArgs, Veo3TextToVideoRequest, }; fn to_i2v_duration(d: FalVeo3Duration) -> Veo3I2vDuration { @@ -74,13 +74,15 @@ pub async fn execute_fal_veo_3( let webhook_response = match &plan.mode { FalVeo3Mode::TextToVideo => { let args = Veo3TextToVideoArgs { - prompt: plan.prompt.as_str(), - negative_prompt: plan.negative_prompt.as_deref(), + 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, + }, api_key: &fal_client.api_key, - 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, webhook_url: fal_client.webhook_url.as_str(), }; enqueue_veo_3_text_to_video_webhook(args) diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3p1.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3p1.rs index 05fd833891..c28aa09a21 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3p1.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3p1.rs @@ -22,8 +22,8 @@ use fal_client::requests::webhook::video::image::enqueue_veo_3p1_image_to_video_ }; use fal_client::requests::webhook::video::text::enqueue_veo_3p1_text_to_video_webhook::{ enqueue_veo_3p1_text_to_video_webhook, EnqueueVeo3p1TextToVideoArgs, - EnqueueVeo3p1TextToVideoAspectRatio, EnqueueVeo3p1TextToVideoDurationSeconds, - EnqueueVeo3p1TextToVideoResolution, + EnqueueVeo3p1TextToVideoRequest, EnqueueVeo3p1TextToVideoAspectRatio, + EnqueueVeo3p1TextToVideoDurationSeconds, EnqueueVeo3p1TextToVideoResolution, }; pub async fn execute_fal_veo_3p1( @@ -33,15 +33,17 @@ pub async fn execute_fal_veo_3p1( let webhook_response = match &plan.mode { FalVeo3p1Mode::TextToVideo => { let args = EnqueueVeo3p1TextToVideoArgs { - 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: 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, + }, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3p1_fast.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3p1_fast.rs index 6ad788858a..ad07079bcb 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3p1_fast.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3p1_fast.rs @@ -23,8 +23,8 @@ use fal_client::requests::webhook::video::image::enqueue_veo_3p1_fast_image_to_v }; use fal_client::requests::webhook::video::text::enqueue_veo_3p1_fast_text_to_video_webhook::{ enqueue_veo_3p1_fast_text_to_video_webhook, EnqueueVeo3p1FastTextToVideoArgs, - EnqueueVeo3p1FastTextToVideoAspectRatio, EnqueueVeo3p1FastTextToVideoDurationSeconds, - EnqueueVeo3p1FastTextToVideoResolution, + EnqueueVeo3p1FastTextToVideoRequest, EnqueueVeo3p1FastTextToVideoAspectRatio, + EnqueueVeo3p1FastTextToVideoDurationSeconds, EnqueueVeo3p1FastTextToVideoResolution, }; pub async fn execute_fal_veo_3p1_fast( @@ -36,15 +36,17 @@ pub async fn execute_fal_veo_3p1_fast( let webhook_response = match &inner.mode { FalVeo3p1Mode::TextToVideo => { let args = EnqueueVeo3p1FastTextToVideoArgs { - 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: 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, + }, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; diff --git a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_hailuo_v2p3_pro_text_to_video_webhook.rs b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_hailuo_v2p3_pro_text_to_video_webhook.rs index 677a4164ee..450528d6fc 100644 --- a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_hailuo_v2p3_pro_text_to_video_webhook.rs +++ b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_hailuo_v2p3_pro_text_to_video_webhook.rs @@ -7,18 +7,21 @@ use crate::requests::api::webhook_response::WebhookResponse; use reqwest::IntoUrl; pub struct EnqueueHailuoV2p3ProTextToVideoArgs<'a, R: IntoUrl> { + pub request: EnqueueHailuoV2p3ProTextToVideoRequest, + pub webhook_url: R, + pub api_key: &'a FalApiKey, +} + +#[derive(Clone, Debug)] +pub struct EnqueueHailuoV2p3ProTextToVideoRequest { // Request required pub prompt: String, // Optional args pub prompt_optimizer: Option, - - // Fulfillment - pub webhook_url: R, - pub api_key: &'a FalApiKey, } -impl FalRequestCostCalculator for EnqueueHailuoV2p3ProTextToVideoArgs<'_, U> { +impl FalRequestCostCalculator for EnqueueHailuoV2p3ProTextToVideoRequest { fn calculate_cost_in_cents(&self) -> UsdCents { /// "Your request will cost $0.49 per video generation." 49 @@ -32,10 +35,11 @@ pub async fn enqueue_hailuo_v2p3_pro_text_to_video_webhook( args: EnqueueHailuoV2p3ProTextToVideoArgs<'_, R> ) -> Result { - let prompt_optimizer = args.prompt_optimizer.unwrap_or(true); + let req = args.request; + let prompt_optimizer = req.prompt_optimizer.unwrap_or(true); let request = HailuoV2p3ProTextToVideoInput { - prompt: args.prompt, + prompt: req.prompt, // Optionals prompt_optimizer: Some(prompt_optimizer), }; @@ -51,7 +55,7 @@ pub async fn enqueue_hailuo_v2p3_pro_text_to_video_webhook( #[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 crate::requests::webhook::video::text::enqueue_hailuo_v2p3_pro_text_to_video_webhook::{enqueue_hailuo_v2p3_pro_text_to_video_webhook, EnqueueHailuoV2p3ProTextToVideoArgs, EnqueueHailuoV2p3ProTextToVideoRequest}; use errors::AnyhowResult; use std::fs::read_to_string; @@ -64,8 +68,10 @@ mod tests { 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), + request: EnqueueHailuoV2p3ProTextToVideoRequest { + 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", }; diff --git a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_3p0_pro_text_to_video_webhook.rs b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_3p0_pro_text_to_video_webhook.rs index bde09a758e..7f47e1b70d 100644 --- a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_3p0_pro_text_to_video_webhook.rs +++ b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_3p0_pro_text_to_video_webhook.rs @@ -7,6 +7,13 @@ use crate::requests::api::webhook_response::WebhookResponse; use reqwest::IntoUrl; pub struct EnqueueKling3p0ProTextToVideoArgs<'a, R: IntoUrl> { + pub request: EnqueueKling3p0ProTextToVideoRequest, + pub webhook_url: R, + pub api_key: &'a FalApiKey, +} + +#[derive(Clone, Debug)] +pub struct EnqueueKling3p0ProTextToVideoRequest { pub prompt: String, // Optional args @@ -15,10 +22,6 @@ pub struct EnqueueKling3p0ProTextToVideoArgs<'a, R: IntoUrl> { pub duration: Option, pub aspect_ratio: Option, pub shot_type: Option, - - // Fulfillment - pub webhook_url: R, - pub api_key: &'a FalApiKey, } #[derive(Copy, Clone, Debug, Eq, PartialEq, strum::EnumIter)] @@ -89,7 +92,7 @@ pub enum EnqueueKling3p0ProTextToVideoShotType { Intelligent, } -impl FalRequestCostCalculator for EnqueueKling3p0ProTextToVideoArgs<'_, U> { +impl FalRequestCostCalculator for EnqueueKling3p0ProTextToVideoRequest { fn calculate_cost_in_cents(&self) -> UsdCents { // Kling 3.0 Pro pricing: // Audio off: $0.224/second @@ -110,10 +113,12 @@ pub async fn enqueue_kling_3p0_pro_text_to_video_webhook( args: EnqueueKling3p0ProTextToVideoArgs<'_, R> ) -> Result { - let duration = args.duration + let req = args.request; + + let duration = req.duration .map(|d| d.to_str().to_string()); - let aspect_ratio = args.aspect_ratio + let aspect_ratio = req.aspect_ratio .map(|aspect| match aspect { EnqueueKling3p0ProTextToVideoAspectRatio::Square => "1:1", EnqueueKling3p0ProTextToVideoAspectRatio::SixteenByNine => "16:9", @@ -121,7 +126,7 @@ pub async fn enqueue_kling_3p0_pro_text_to_video_webhook( }) .map(|s| s.to_string()); - let shot_type = args.shot_type + let shot_type = req.shot_type .map(|st| match st { EnqueueKling3p0ProTextToVideoShotType::Customize => "customize", EnqueueKling3p0ProTextToVideoShotType::Intelligent => "intelligent", @@ -129,11 +134,11 @@ pub async fn enqueue_kling_3p0_pro_text_to_video_webhook( .map(|s| s.to_string()); let request = Kling3p0ProTextToVideoInput { - prompt: args.prompt, - generate_audio: args.generate_audio, + prompt: req.prompt, + generate_audio: req.generate_audio, duration, aspect_ratio, - negative_prompt: args.negative_prompt, + negative_prompt: req.negative_prompt, shot_type, cfg_scale: None, }; @@ -157,49 +162,45 @@ mod tests { #[test] fn test_cost() { - let api_key = FalApiKey::from_str(""); - - let mut args = EnqueueKling3p0ProTextToVideoArgs { + let mut req = EnqueueKling3p0ProTextToVideoRequest { prompt: "a spacecraft drifts through an asteroid field, dramatic lighting".to_string(), generate_audio: Some(false), negative_prompt: None, duration: Some(EnqueueKling3p0ProTextToVideoDuration::FiveSeconds), aspect_ratio: None, shot_type: None, - webhook_url: "https://example.com/webhook", - api_key: &api_key, }; // Audio off: $0.224/sec // 5s: (224 * 5 + 9) / 10 = 1129 / 10 = 112 - assert_eq!(args.calculate_cost_in_cents(), 112); + assert_eq!(req.calculate_cost_in_cents(), 112); // 3s: (224 * 3 + 9) / 10 = 681 / 10 = 68 - args.duration = Some(EnqueueKling3p0ProTextToVideoDuration::ThreeSeconds); - assert_eq!(args.calculate_cost_in_cents(), 68); + req.duration = Some(EnqueueKling3p0ProTextToVideoDuration::ThreeSeconds); + assert_eq!(req.calculate_cost_in_cents(), 68); // 10s: (224 * 10 + 9) / 10 = 2249 / 10 = 224 - args.duration = Some(EnqueueKling3p0ProTextToVideoDuration::TenSeconds); - assert_eq!(args.calculate_cost_in_cents(), 224); + req.duration = Some(EnqueueKling3p0ProTextToVideoDuration::TenSeconds); + assert_eq!(req.calculate_cost_in_cents(), 224); // 15s: (224 * 15 + 9) / 10 = 3369 / 10 = 336 - args.duration = Some(EnqueueKling3p0ProTextToVideoDuration::FifteenSeconds); - assert_eq!(args.calculate_cost_in_cents(), 336); + req.duration = Some(EnqueueKling3p0ProTextToVideoDuration::FifteenSeconds); + assert_eq!(req.calculate_cost_in_cents(), 336); // Audio on: $0.336/sec - args.generate_audio = Some(true); + req.generate_audio = Some(true); // 5s: (336 * 5 + 9) / 10 = 1689 / 10 = 168 - args.duration = Some(EnqueueKling3p0ProTextToVideoDuration::FiveSeconds); - assert_eq!(args.calculate_cost_in_cents(), 168); + req.duration = Some(EnqueueKling3p0ProTextToVideoDuration::FiveSeconds); + assert_eq!(req.calculate_cost_in_cents(), 168); // 10s: (336 * 10 + 9) / 10 = 3369 / 10 = 336 - args.duration = Some(EnqueueKling3p0ProTextToVideoDuration::TenSeconds); - assert_eq!(args.calculate_cost_in_cents(), 336); + req.duration = Some(EnqueueKling3p0ProTextToVideoDuration::TenSeconds); + assert_eq!(req.calculate_cost_in_cents(), 336); // 15s: (336 * 15 + 9) / 10 = 5049 / 10 = 504 - args.duration = Some(EnqueueKling3p0ProTextToVideoDuration::FifteenSeconds); - assert_eq!(args.calculate_cost_in_cents(), 504); + req.duration = Some(EnqueueKling3p0ProTextToVideoDuration::FifteenSeconds); + assert_eq!(req.calculate_cost_in_cents(), 504); } #[tokio::test] @@ -209,12 +210,14 @@ mod tests { let api_key = FalApiKey::from_str(&secret); let args = EnqueueKling3p0ProTextToVideoArgs { - prompt: "a samurai draws a katana in a bamboo forest, cherry blossoms falling in slow motion".to_string(), - generate_audio: Some(true), - negative_prompt: None, - duration: Some(EnqueueKling3p0ProTextToVideoDuration::FiveSeconds), - aspect_ratio: Some(EnqueueKling3p0ProTextToVideoAspectRatio::SixteenByNine), - shot_type: None, + request: EnqueueKling3p0ProTextToVideoRequest { + prompt: "a samurai draws a katana in a bamboo forest, cherry blossoms falling in slow motion".to_string(), + generate_audio: Some(true), + negative_prompt: None, + duration: Some(EnqueueKling3p0ProTextToVideoDuration::FiveSeconds), + aspect_ratio: Some(EnqueueKling3p0ProTextToVideoAspectRatio::SixteenByNine), + shot_type: None, + }, api_key: &api_key, webhook_url: "https://example.com/webhook", }; @@ -234,12 +237,14 @@ mod tests { for ar in EnqueueKling3p0ProTextToVideoAspectRatio::iter() { println!("--- aspect ratio: {:?} ---", ar); let args = EnqueueKling3p0ProTextToVideoArgs { - prompt: "a lighthouse beam sweeps across a stormy sea at night".to_string(), - generate_audio: Some(true), - negative_prompt: None, - duration: Some(EnqueueKling3p0ProTextToVideoDuration::ThreeSeconds), - aspect_ratio: Some(ar), - shot_type: None, + request: EnqueueKling3p0ProTextToVideoRequest { + prompt: "a lighthouse beam sweeps across a stormy sea at night".to_string(), + generate_audio: Some(true), + negative_prompt: None, + duration: Some(EnqueueKling3p0ProTextToVideoDuration::ThreeSeconds), + aspect_ratio: Some(ar), + shot_type: None, + }, api_key: &api_key, webhook_url: "https://example.com/webhook", }; @@ -259,12 +264,14 @@ mod tests { for dur in EnqueueKling3p0ProTextToVideoDuration::iter() { println!("--- duration: {:?} ---", dur); let args = EnqueueKling3p0ProTextToVideoArgs { - prompt: "a hot air balloon rises over misty mountains at dawn".to_string(), - generate_audio: Some(false), - negative_prompt: None, - duration: Some(dur), - aspect_ratio: Some(EnqueueKling3p0ProTextToVideoAspectRatio::SixteenByNine), - shot_type: None, + request: EnqueueKling3p0ProTextToVideoRequest { + prompt: "a hot air balloon rises over misty mountains at dawn".to_string(), + generate_audio: Some(false), + negative_prompt: None, + duration: Some(dur), + aspect_ratio: Some(EnqueueKling3p0ProTextToVideoAspectRatio::SixteenByNine), + shot_type: None, + }, api_key: &api_key, webhook_url: "https://example.com/webhook", }; @@ -284,12 +291,14 @@ mod tests { for st in EnqueueKling3p0ProTextToVideoShotType::iter() { println!("--- shot type: {:?} ---", st); let args = EnqueueKling3p0ProTextToVideoArgs { - prompt: "an eagle soars over a snow-capped mountain range".to_string(), - generate_audio: Some(true), - negative_prompt: None, - duration: Some(EnqueueKling3p0ProTextToVideoDuration::FiveSeconds), - aspect_ratio: Some(EnqueueKling3p0ProTextToVideoAspectRatio::SixteenByNine), - shot_type: Some(st), + request: EnqueueKling3p0ProTextToVideoRequest { + prompt: "an eagle soars over a snow-capped mountain range".to_string(), + generate_audio: Some(true), + negative_prompt: None, + duration: Some(EnqueueKling3p0ProTextToVideoDuration::FiveSeconds), + aspect_ratio: Some(EnqueueKling3p0ProTextToVideoAspectRatio::SixteenByNine), + shot_type: Some(st), + }, api_key: &api_key, webhook_url: "https://example.com/webhook", }; diff --git a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_3p0_standard_text_to_video_webhook.rs b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_3p0_standard_text_to_video_webhook.rs index 6f5540b279..b24faba8ec 100644 --- a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_3p0_standard_text_to_video_webhook.rs +++ b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_3p0_standard_text_to_video_webhook.rs @@ -7,6 +7,13 @@ use crate::requests::api::webhook_response::WebhookResponse; use reqwest::IntoUrl; pub struct EnqueueKling3p0StandardTextToVideoArgs<'a, R: IntoUrl> { + pub request: EnqueueKling3p0StandardTextToVideoRequest, + pub webhook_url: R, + pub api_key: &'a FalApiKey, +} + +#[derive(Clone, Debug)] +pub struct EnqueueKling3p0StandardTextToVideoRequest { pub prompt: String, // Optional args @@ -15,10 +22,6 @@ pub struct EnqueueKling3p0StandardTextToVideoArgs<'a, R: IntoUrl> { pub duration: Option, pub aspect_ratio: Option, pub shot_type: Option, - - // Fulfillment - pub webhook_url: R, - pub api_key: &'a FalApiKey, } #[derive(Copy, Clone, Debug, Eq, PartialEq, strum::EnumIter)] @@ -89,7 +92,7 @@ pub enum EnqueueKling3p0StandardTextToVideoShotType { Intelligent, } -impl FalRequestCostCalculator for EnqueueKling3p0StandardTextToVideoArgs<'_, U> { +impl FalRequestCostCalculator for EnqueueKling3p0StandardTextToVideoRequest { fn calculate_cost_in_cents(&self) -> UsdCents { // Kling 3.0 Standard pricing: // Audio off: $0.168/second @@ -111,10 +114,12 @@ pub async fn enqueue_kling_3p0_standard_text_to_video_webhook( args: EnqueueKling3p0StandardTextToVideoArgs<'_, R> ) -> Result { - let duration = args.duration + let req = args.request; + + let duration = req.duration .map(|d| d.to_str().to_string()); - let aspect_ratio = args.aspect_ratio + let aspect_ratio = req.aspect_ratio .map(|aspect| match aspect { EnqueueKling3p0StandardTextToVideoAspectRatio::Square => "1:1", EnqueueKling3p0StandardTextToVideoAspectRatio::SixteenByNine => "16:9", @@ -122,7 +127,7 @@ pub async fn enqueue_kling_3p0_standard_text_to_video_webhook( }) .map(|s| s.to_string()); - let shot_type = args.shot_type + let shot_type = req.shot_type .map(|st| match st { EnqueueKling3p0StandardTextToVideoShotType::Customize => "customize", EnqueueKling3p0StandardTextToVideoShotType::Intelligent => "intelligent", @@ -130,11 +135,11 @@ pub async fn enqueue_kling_3p0_standard_text_to_video_webhook( .map(|s| s.to_string()); let request = Kling3p0StandardTextToVideoInput { - prompt: args.prompt, - generate_audio: args.generate_audio, + prompt: req.prompt, + generate_audio: req.generate_audio, duration, aspect_ratio, - negative_prompt: args.negative_prompt, + negative_prompt: req.negative_prompt, shot_type, cfg_scale: None, }; @@ -158,49 +163,45 @@ mod tests { #[test] fn test_cost() { - let api_key = FalApiKey::from_str(""); - - let mut args = EnqueueKling3p0StandardTextToVideoArgs { + let mut req = EnqueueKling3p0StandardTextToVideoRequest { prompt: "a cat sitting on a windowsill watching rain".to_string(), generate_audio: Some(false), negative_prompt: None, duration: Some(EnqueueKling3p0StandardTextToVideoDuration::FiveSeconds), aspect_ratio: None, shot_type: None, - webhook_url: "https://example.com/webhook", - api_key: &api_key, }; // Audio off: $0.168/sec // 5s: (168 * 5 + 9) / 10 = 849 / 10 = 84 - assert_eq!(args.calculate_cost_in_cents(), 84); + assert_eq!(req.calculate_cost_in_cents(), 84); // 3s: (168 * 3 + 9) / 10 = 513 / 10 = 51 - args.duration = Some(EnqueueKling3p0StandardTextToVideoDuration::ThreeSeconds); - assert_eq!(args.calculate_cost_in_cents(), 51); + req.duration = Some(EnqueueKling3p0StandardTextToVideoDuration::ThreeSeconds); + assert_eq!(req.calculate_cost_in_cents(), 51); // 10s: (168 * 10 + 9) / 10 = 1689 / 10 = 168 - args.duration = Some(EnqueueKling3p0StandardTextToVideoDuration::TenSeconds); - assert_eq!(args.calculate_cost_in_cents(), 168); + req.duration = Some(EnqueueKling3p0StandardTextToVideoDuration::TenSeconds); + assert_eq!(req.calculate_cost_in_cents(), 168); // 15s: (168 * 15 + 9) / 10 = 2529 / 10 = 252 - args.duration = Some(EnqueueKling3p0StandardTextToVideoDuration::FifteenSeconds); - assert_eq!(args.calculate_cost_in_cents(), 252); + req.duration = Some(EnqueueKling3p0StandardTextToVideoDuration::FifteenSeconds); + assert_eq!(req.calculate_cost_in_cents(), 252); // Audio on: $0.252/sec - args.generate_audio = Some(true); + req.generate_audio = Some(true); // 5s: (252 * 5 + 9) / 10 = 1269 / 10 = 126 - args.duration = Some(EnqueueKling3p0StandardTextToVideoDuration::FiveSeconds); - assert_eq!(args.calculate_cost_in_cents(), 126); + req.duration = Some(EnqueueKling3p0StandardTextToVideoDuration::FiveSeconds); + assert_eq!(req.calculate_cost_in_cents(), 126); // 10s: (252 * 10 + 9) / 10 = 2529 / 10 = 252 - args.duration = Some(EnqueueKling3p0StandardTextToVideoDuration::TenSeconds); - assert_eq!(args.calculate_cost_in_cents(), 252); + req.duration = Some(EnqueueKling3p0StandardTextToVideoDuration::TenSeconds); + assert_eq!(req.calculate_cost_in_cents(), 252); // 15s: (252 * 15 + 9) / 10 = 3789 / 10 = 378 - args.duration = Some(EnqueueKling3p0StandardTextToVideoDuration::FifteenSeconds); - assert_eq!(args.calculate_cost_in_cents(), 378); + req.duration = Some(EnqueueKling3p0StandardTextToVideoDuration::FifteenSeconds); + assert_eq!(req.calculate_cost_in_cents(), 378); } #[tokio::test] @@ -210,12 +211,14 @@ mod tests { let api_key = FalApiKey::from_str(&secret); let args = EnqueueKling3p0StandardTextToVideoArgs { - prompt: "a golden retriever puppy chases butterflies through a sunlit meadow, cinematic slow motion".to_string(), - generate_audio: Some(true), - negative_prompt: None, - duration: Some(EnqueueKling3p0StandardTextToVideoDuration::FiveSeconds), - aspect_ratio: Some(EnqueueKling3p0StandardTextToVideoAspectRatio::SixteenByNine), - shot_type: None, + request: EnqueueKling3p0StandardTextToVideoRequest { + prompt: "a golden retriever puppy chases butterflies through a sunlit meadow, cinematic slow motion".to_string(), + generate_audio: Some(true), + negative_prompt: None, + duration: Some(EnqueueKling3p0StandardTextToVideoDuration::FiveSeconds), + aspect_ratio: Some(EnqueueKling3p0StandardTextToVideoAspectRatio::SixteenByNine), + shot_type: None, + }, api_key: &api_key, webhook_url: "https://example.com/webhook", }; @@ -235,12 +238,14 @@ mod tests { for ar in EnqueueKling3p0StandardTextToVideoAspectRatio::iter() { println!("--- aspect ratio: {:?} ---", ar); let args = EnqueueKling3p0StandardTextToVideoArgs { - prompt: "a wave crashes against a rocky shoreline at sunset".to_string(), - generate_audio: Some(true), - negative_prompt: None, - duration: Some(EnqueueKling3p0StandardTextToVideoDuration::ThreeSeconds), - aspect_ratio: Some(ar), - shot_type: None, + request: EnqueueKling3p0StandardTextToVideoRequest { + prompt: "a wave crashes against a rocky shoreline at sunset".to_string(), + generate_audio: Some(true), + negative_prompt: None, + duration: Some(EnqueueKling3p0StandardTextToVideoDuration::ThreeSeconds), + aspect_ratio: Some(ar), + shot_type: None, + }, api_key: &api_key, webhook_url: "https://example.com/webhook", }; @@ -260,12 +265,14 @@ mod tests { for dur in EnqueueKling3p0StandardTextToVideoDuration::iter() { println!("--- duration: {:?} ---", dur); let args = EnqueueKling3p0StandardTextToVideoArgs { - prompt: "a candle flame flickers in a dark room".to_string(), - generate_audio: Some(false), - negative_prompt: None, - duration: Some(dur), - aspect_ratio: Some(EnqueueKling3p0StandardTextToVideoAspectRatio::SixteenByNine), - shot_type: None, + request: EnqueueKling3p0StandardTextToVideoRequest { + prompt: "a candle flame flickers in a dark room".to_string(), + generate_audio: Some(false), + negative_prompt: None, + duration: Some(dur), + aspect_ratio: Some(EnqueueKling3p0StandardTextToVideoAspectRatio::SixteenByNine), + shot_type: None, + }, api_key: &api_key, webhook_url: "https://example.com/webhook", }; @@ -285,12 +292,14 @@ mod tests { for st in EnqueueKling3p0StandardTextToVideoShotType::iter() { println!("--- shot type: {:?} ---", st); let args = EnqueueKling3p0StandardTextToVideoArgs { - prompt: "a bird takes flight from a tree branch".to_string(), - generate_audio: Some(true), - negative_prompt: None, - duration: Some(EnqueueKling3p0StandardTextToVideoDuration::FiveSeconds), - aspect_ratio: Some(EnqueueKling3p0StandardTextToVideoAspectRatio::SixteenByNine), - shot_type: Some(st), + request: EnqueueKling3p0StandardTextToVideoRequest { + prompt: "a bird takes flight from a tree branch".to_string(), + generate_audio: Some(true), + negative_prompt: None, + duration: Some(EnqueueKling3p0StandardTextToVideoDuration::FiveSeconds), + aspect_ratio: Some(EnqueueKling3p0StandardTextToVideoAspectRatio::SixteenByNine), + shot_type: Some(st), + }, api_key: &api_key, webhook_url: "https://example.com/webhook", }; diff --git a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_v2p5_turbo_pro_text_to_video_webhook.rs b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_v2p5_turbo_pro_text_to_video_webhook.rs index 87ab87240a..0ca4733f5f 100644 --- a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_v2p5_turbo_pro_text_to_video_webhook.rs +++ b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_v2p5_turbo_pro_text_to_video_webhook.rs @@ -7,6 +7,13 @@ use crate::requests::api::webhook_response::WebhookResponse; use reqwest::IntoUrl; pub struct EnqueueKlingV2p5TurboProTextToVideoArgs<'a, R: IntoUrl> { + pub request: EnqueueKlingV2p5TurboProTextToVideoRequest, + pub webhook_url: R, + pub api_key: &'a FalApiKey, +} + +#[derive(Clone, Debug)] +pub struct EnqueueKlingV2p5TurboProTextToVideoRequest { // Request required pub prompt: String, @@ -14,10 +21,6 @@ pub struct EnqueueKlingV2p5TurboProTextToVideoArgs<'a, R: IntoUrl> { pub negative_prompt: Option, pub duration: Option, pub aspect_ratio: Option, - - // Fulfillment - pub webhook_url: R, - pub api_key: &'a FalApiKey, } #[derive(Copy, Clone, Debug)] @@ -34,7 +37,7 @@ pub enum EnqueueKlingV2p5TurboProTextToVideoAspectRatio { } -impl FalRequestCostCalculator for EnqueueKlingV2p5TurboProTextToVideoArgs<'_, U> { +impl FalRequestCostCalculator for EnqueueKlingV2p5TurboProTextToVideoRequest { fn calculate_cost_in_cents(&self) -> UsdCents { // "For 5s video your request will cost $0.35. // For every additional second you will be charged $0.07." @@ -53,14 +56,16 @@ pub async fn enqueue_kling_v2p5_turbo_pro_text_to_video_webhook( args: EnqueueKlingV2p5TurboProTextToVideoArgs<'_, R> ) -> Result { - let duration = args.duration + let req = args.request; + + let duration = req.duration .map(|resolution| match resolution { EnqueueKlingV2p5TurboProTextToVideoDurationSeconds::Five => "5", EnqueueKlingV2p5TurboProTextToVideoDurationSeconds::Ten => "10", }) .map(|s| s.to_string()); - - let aspect_ratio = args.aspect_ratio + + let aspect_ratio = req.aspect_ratio .map(|aspect| match aspect { EnqueueKlingV2p5TurboProTextToVideoAspectRatio::Square => "1:1", EnqueueKlingV2p5TurboProTextToVideoAspectRatio::SixteenByNine => "16:9", @@ -69,11 +74,11 @@ pub async fn enqueue_kling_v2p5_turbo_pro_text_to_video_webhook( .map(|s| s.to_string()); let request = KlingV2p5TurboProTextToVideoInput { - prompt: args.prompt, + prompt: req.prompt, // Optionals duration, aspect_ratio, - negative_prompt: args.negative_prompt, + negative_prompt: req.negative_prompt, // Constants cfg_scale: None, }; @@ -89,7 +94,7 @@ pub async fn enqueue_kling_v2p5_turbo_pro_text_to_video_webhook( #[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 crate::requests::webhook::video::text::enqueue_kling_v2p5_turbo_pro_text_to_video_webhook::{enqueue_kling_v2p5_turbo_pro_text_to_video_webhook, EnqueueKlingV2p5TurboProTextToVideoArgs, EnqueueKlingV2p5TurboProTextToVideoRequest, EnqueueKlingV2p5TurboProTextToVideoAspectRatio, EnqueueKlingV2p5TurboProTextToVideoDurationSeconds}; use errors::AnyhowResult; use std::fs::read_to_string; @@ -102,10 +107,12 @@ mod tests { 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), + request: EnqueueKlingV2p5TurboProTextToVideoRequest { + 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", }; diff --git a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_v2p6_pro_text_to_video_webhook.rs b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_v2p6_pro_text_to_video_webhook.rs index 7d41bbd371..eb7c0a72d5 100644 --- a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_v2p6_pro_text_to_video_webhook.rs +++ b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_kling_v2p6_pro_text_to_video_webhook.rs @@ -7,6 +7,13 @@ use crate::requests::api::webhook_response::WebhookResponse; use reqwest::IntoUrl; pub struct EnqueueKlingV2p6ProTextToVideoArgs<'a, R: IntoUrl> { + pub request: EnqueueKlingV2p6ProTextToVideoRequest, + pub webhook_url: R, + pub api_key: &'a FalApiKey, +} + +#[derive(Clone, Debug)] +pub struct EnqueueKlingV2p6ProTextToVideoRequest { // Request required pub prompt: String, @@ -15,10 +22,6 @@ pub struct EnqueueKlingV2p6ProTextToVideoArgs<'a, R: IntoUrl> { pub negative_prompt: Option, pub duration: Option, pub aspect_ratio: Option, - - // Fulfillment - pub webhook_url: R, - pub api_key: &'a FalApiKey, } #[derive(Copy, Clone, Debug)] @@ -34,7 +37,7 @@ pub enum EnqueueKlingV2p6ProTextToVideoAspectRatio { NineBySixteen, } -impl FalRequestCostCalculator for EnqueueKlingV2p6ProTextToVideoArgs<'_, U> { +impl FalRequestCostCalculator for EnqueueKlingV2p6ProTextToVideoRequest { fn calculate_cost_in_cents(&self) -> UsdCents { // "For every second of video you generated, you will be // charged $0.07 (audio off) or $0.14 (audio on). @@ -58,14 +61,16 @@ pub async fn enqueue_kling_v2p6_pro_text_to_video_webhook( args: EnqueueKlingV2p6ProTextToVideoArgs<'_, R> ) -> Result { - let duration = args.duration + let req = args.request; + + let duration = req.duration .map(|resolution| match resolution { EnqueueKlingV2p6ProTextToVideoDurationSeconds::Five => "5", EnqueueKlingV2p6ProTextToVideoDurationSeconds::Ten => "10", }) .map(|s| s.to_string()); - - let aspect_ratio = args.aspect_ratio + + let aspect_ratio = req.aspect_ratio .map(|aspect| match aspect { EnqueueKlingV2p6ProTextToVideoAspectRatio::Square => "1:1", EnqueueKlingV2p6ProTextToVideoAspectRatio::SixteenByNine => "16:9", @@ -74,12 +79,12 @@ pub async fn enqueue_kling_v2p6_pro_text_to_video_webhook( .map(|s| s.to_string()); let request = KlingV2p6ProTextToVideoInput { - prompt: args.prompt, + prompt: req.prompt, // Optionals - generate_audio: args.generate_audio, + generate_audio: req.generate_audio, duration, aspect_ratio, - negative_prompt: args.negative_prompt, + negative_prompt: req.negative_prompt, // Constants cfg_scale: None, }; @@ -95,7 +100,7 @@ pub async fn enqueue_kling_v2p6_pro_text_to_video_webhook( #[cfg(test)] mod tests { use crate::creds::fal_api_key::FalApiKey; - 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}; + use crate::requests::webhook::video::text::enqueue_kling_v2p6_pro_text_to_video_webhook::{enqueue_kling_v2p6_pro_text_to_video_webhook, EnqueueKlingV2p6ProTextToVideoArgs, EnqueueKlingV2p6ProTextToVideoRequest, EnqueueKlingV2p6ProTextToVideoAspectRatio, EnqueueKlingV2p6ProTextToVideoDurationSeconds}; use errors::AnyhowResult; use std::fs::read_to_string; @@ -108,11 +113,13 @@ mod tests { 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), + request: EnqueueKlingV2p6ProTextToVideoRequest { + 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", }; diff --git a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_pixverse_v5_text_to_video_webhook.rs b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_pixverse_v5_text_to_video_webhook.rs index 93fe9993e7..59dabc54a9 100644 --- a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_pixverse_v5_text_to_video_webhook.rs +++ b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_pixverse_v5_text_to_video_webhook.rs @@ -6,6 +6,13 @@ use crate::requests::api::webhook_response::WebhookResponse; use reqwest::IntoUrl; pub struct EnqueuePixverseV5TextToVideoArgs<'a, R: IntoUrl> { + pub request: EnqueuePixverseV5TextToVideoRequest, + pub webhook_url: R, + pub api_key: &'a FalApiKey, +} + +#[derive(Clone, Debug)] +pub struct EnqueuePixverseV5TextToVideoRequest { // Request required pub prompt: String, @@ -17,10 +24,6 @@ pub struct EnqueuePixverseV5TextToVideoArgs<'a, R: IntoUrl> { pub aspect_ratio: Option, pub resolution: Option, pub style: Option, - - // Fulfillment - pub webhook_url: R, - pub api_key: &'a FalApiKey, } #[derive(Copy, Clone, Debug)] @@ -59,14 +62,16 @@ pub async fn enqueue_pixverse_v5_text_to_video_webhook( args: EnqueuePixverseV5TextToVideoArgs<'_, R> ) -> Result { - let duration = args.duration + let req = args.request; + + let duration = req.duration .map(|resolution| match resolution { EnqueuePixverseV5TextToVideoDurationSeconds::Five => "5", EnqueuePixverseV5TextToVideoDurationSeconds::Eight=> "8", }) .map(|s| s.to_string()); - let aspect_ratio = args.aspect_ratio + let aspect_ratio = req.aspect_ratio .map(|aspect_ratio| match aspect_ratio { EnqueuePixverseV5TextToVideoAspectRatio::Square => "1:1", EnqueuePixverseV5TextToVideoAspectRatio::SixteenByNine => "16:9", @@ -76,7 +81,7 @@ pub async fn enqueue_pixverse_v5_text_to_video_webhook( }) .map(|s| s.to_string()); - let resolution = args.resolution + let resolution = req.resolution .map(|resolution| match resolution { EnqueuePixverseV5TextToVideoResolution::ThreeSixtyP => "360p", EnqueuePixverseV5TextToVideoResolution::FiveFortyP => "540p", @@ -85,7 +90,7 @@ pub async fn enqueue_pixverse_v5_text_to_video_webhook( }) .map(|s| s.to_string()); - let style = args.style + let style = req.style .map(|style| match style { EnqueuePixverseV5TextToVideoStyle::Anime => "anime", EnqueuePixverseV5TextToVideoStyle::Animation3d => "3d_animation", @@ -96,10 +101,10 @@ pub async fn enqueue_pixverse_v5_text_to_video_webhook( .map(|s| s.to_string()); let request = PixverseV5TextToVideoInput { - prompt: args.prompt, + prompt: req.prompt, // Optionals duration, - negative_prompt: args.negative_prompt, + negative_prompt: req.negative_prompt, aspect_ratio, resolution, style, @@ -118,7 +123,7 @@ pub async fn enqueue_pixverse_v5_text_to_video_webhook( #[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 crate::requests::webhook::video::text::enqueue_pixverse_v5_text_to_video_webhook::{enqueue_pixverse_v5_text_to_video_webhook, EnqueuePixverseV5TextToVideoArgs, EnqueuePixverseV5TextToVideoRequest, EnqueuePixverseV5TextToVideoAspectRatio, EnqueuePixverseV5TextToVideoDurationSeconds, EnqueuePixverseV5TextToVideoResolution, EnqueuePixverseV5TextToVideoStyle}; use errors::AnyhowResult; use std::fs::read_to_string; @@ -131,12 +136,14 @@ mod tests { 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), + request: EnqueuePixverseV5TextToVideoRequest { + 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", }; diff --git a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_seedance_1p5_pro_text_to_video_webhook.rs b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_seedance_1p5_pro_text_to_video_webhook.rs index 219b41c700..d52f0ce798 100644 --- a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_seedance_1p5_pro_text_to_video_webhook.rs +++ b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_seedance_1p5_pro_text_to_video_webhook.rs @@ -7,6 +7,13 @@ use crate::requests::api::webhook_response::WebhookResponse; use reqwest::IntoUrl; pub struct EnqueueSeedance1p5ProTextToVideoArgs<'a, R: IntoUrl> { + pub request: EnqueueSeedance1p5ProTextToVideoRequest, + pub webhook_url: R, + pub api_key: &'a FalApiKey, +} + +#[derive(Clone, Debug)] +pub struct EnqueueSeedance1p5ProTextToVideoRequest { // Request required pub prompt: String, @@ -15,10 +22,6 @@ pub struct EnqueueSeedance1p5ProTextToVideoArgs<'a, R: IntoUrl> { pub duration: Option, pub aspect_ratio: Option, pub generate_audio: Option, - - // Fulfillment - pub webhook_url: R, - pub api_key: &'a FalApiKey, } #[derive(Copy, Clone, Debug, Eq, PartialEq, strum::EnumIter)] @@ -52,7 +55,7 @@ pub enum EnqueueSeedance1p5ProTextToVideoAspectRatio { Auto, } -impl FalRequestCostCalculator for EnqueueSeedance1p5ProTextToVideoArgs<'_, U> { +impl FalRequestCostCalculator for EnqueueSeedance1p5ProTextToVideoRequest { fn calculate_cost_in_cents(&self) -> UsdCents { // Fal: // "Each 720p 5 second video with audio costs roughly $0.26. @@ -110,7 +113,9 @@ pub async fn enqueue_seedance_1p5_pro_text_to_video_webhook( args: EnqueueSeedance1p5ProTextToVideoArgs<'_, R> ) -> Result { - let duration = args.duration + let req = args.request; + + let duration = req.duration .map(|d| match d { EnqueueSeedance1p5ProTextToVideoDuration::FourSeconds => "4", EnqueueSeedance1p5ProTextToVideoDuration::FiveSeconds => "5", @@ -124,7 +129,7 @@ pub async fn enqueue_seedance_1p5_pro_text_to_video_webhook( }) .map(|d| d.to_string()); - let resolution = args.resolution + let resolution = req.resolution .map(|r| match r { EnqueueSeedance1p5ProTextToVideoResolution::FourEightyP => "480p", EnqueueSeedance1p5ProTextToVideoResolution::SevenTwentyP => "720p", @@ -132,7 +137,7 @@ pub async fn enqueue_seedance_1p5_pro_text_to_video_webhook( }) .map(|r| r.to_string()); - let aspect_ratio = args.aspect_ratio + let aspect_ratio = req.aspect_ratio .map(|ar| match ar { EnqueueSeedance1p5ProTextToVideoAspectRatio::TwentyOneByNine => "21:9", EnqueueSeedance1p5ProTextToVideoAspectRatio::SixteenByNine => "16:9", @@ -145,14 +150,14 @@ pub async fn enqueue_seedance_1p5_pro_text_to_video_webhook( .map(|ar| ar.to_string()); let request = Seedance1p5ProTextToVideoInput { - prompt: args.prompt, + prompt: req.prompt, duration, resolution, aspect_ratio, camera_fixed: None, seed: None, enable_safety_checker: Some(false), - generate_audio: Some(args.generate_audio.unwrap_or(true)), + generate_audio: Some(req.generate_audio.unwrap_or(true)), }; let result = seedance_1p5_pro_text_to_video(request) @@ -174,71 +179,63 @@ mod tests { #[test] fn test_cost() { - let api_key = FalApiKey::from_str(""); - - let mut args = EnqueueSeedance1p5ProTextToVideoArgs { + let mut req = EnqueueSeedance1p5ProTextToVideoRequest { prompt: String::new(), - api_key: &api_key, duration: Some(EnqueueSeedance1p5ProTextToVideoDuration::FiveSeconds), resolution: Some(EnqueueSeedance1p5ProTextToVideoResolution::SevenTwentyP), aspect_ratio: None, generate_audio: None, - webhook_url: "https://example.com/webhook", }; // NB: Constant value specified by Fal - let cost = args.calculate_cost_in_cents(); + let cost = req.calculate_cost_in_cents(); assert_eq!(cost, 26); // Calculated values - args.duration = Some(EnqueueSeedance1p5ProTextToVideoDuration::TenSeconds); - args.resolution = Some(EnqueueSeedance1p5ProTextToVideoResolution::SevenTwentyP); - let cost = args.calculate_cost_in_cents(); + req.duration = Some(EnqueueSeedance1p5ProTextToVideoDuration::TenSeconds); + req.resolution = Some(EnqueueSeedance1p5ProTextToVideoResolution::SevenTwentyP); + let cost = req.calculate_cost_in_cents(); assert_eq!(cost, 65); - args.duration = Some(EnqueueSeedance1p5ProTextToVideoDuration::FiveSeconds); - args.resolution = Some(EnqueueSeedance1p5ProTextToVideoResolution::TenEightyP); - let cost = args.calculate_cost_in_cents(); + req.duration = Some(EnqueueSeedance1p5ProTextToVideoDuration::FiveSeconds); + req.resolution = Some(EnqueueSeedance1p5ProTextToVideoResolution::TenEightyP); + let cost = req.calculate_cost_in_cents(); assert_eq!(cost, 73); - args.duration = Some(EnqueueSeedance1p5ProTextToVideoDuration::TenSeconds); - args.resolution = Some(EnqueueSeedance1p5ProTextToVideoResolution::TenEightyP); - let cost = args.calculate_cost_in_cents(); + req.duration = Some(EnqueueSeedance1p5ProTextToVideoDuration::TenSeconds); + req.resolution = Some(EnqueueSeedance1p5ProTextToVideoResolution::TenEightyP); + let cost = req.calculate_cost_in_cents(); assert_eq!(cost, 146); } #[test] fn test_cost_audio_off() { - let api_key = FalApiKey::from_str(""); - - let mut args = EnqueueSeedance1p5ProTextToVideoArgs { + let mut req = EnqueueSeedance1p5ProTextToVideoRequest { prompt: String::new(), - api_key: &api_key, duration: Some(EnqueueSeedance1p5ProTextToVideoDuration::FiveSeconds), resolution: Some(EnqueueSeedance1p5ProTextToVideoResolution::SevenTwentyP), aspect_ratio: None, generate_audio: Some(false), - webhook_url: "https://example.com/webhook", }; // 720p 5s without audio = half of 26 - let cost = args.calculate_cost_in_cents(); + let cost = req.calculate_cost_in_cents(); assert_eq!(cost, 13); // Calculated values — half of audio-on costs (ceil) - args.duration = Some(EnqueueSeedance1p5ProTextToVideoDuration::TenSeconds); - args.resolution = Some(EnqueueSeedance1p5ProTextToVideoResolution::SevenTwentyP); - let cost = args.calculate_cost_in_cents(); + req.duration = Some(EnqueueSeedance1p5ProTextToVideoDuration::TenSeconds); + req.resolution = Some(EnqueueSeedance1p5ProTextToVideoResolution::SevenTwentyP); + let cost = req.calculate_cost_in_cents(); assert_eq!(cost, 33); - args.duration = Some(EnqueueSeedance1p5ProTextToVideoDuration::FiveSeconds); - args.resolution = Some(EnqueueSeedance1p5ProTextToVideoResolution::TenEightyP); - let cost = args.calculate_cost_in_cents(); + req.duration = Some(EnqueueSeedance1p5ProTextToVideoDuration::FiveSeconds); + req.resolution = Some(EnqueueSeedance1p5ProTextToVideoResolution::TenEightyP); + let cost = req.calculate_cost_in_cents(); assert_eq!(cost, 37); - args.duration = Some(EnqueueSeedance1p5ProTextToVideoDuration::TenSeconds); - args.resolution = Some(EnqueueSeedance1p5ProTextToVideoResolution::TenEightyP); - let cost = args.calculate_cost_in_cents(); + req.duration = Some(EnqueueSeedance1p5ProTextToVideoDuration::TenSeconds); + req.resolution = Some(EnqueueSeedance1p5ProTextToVideoResolution::TenEightyP); + let cost = req.calculate_cost_in_cents(); assert_eq!(cost, 73); } @@ -249,11 +246,13 @@ mod tests { let api_key = FalApiKey::from_str(&secret); let args = EnqueueSeedance1p5ProTextToVideoArgs { - prompt: "a dinosaur walks through a misty forest at dawn, cinematic lighting".to_string(), - duration: Some(EnqueueSeedance1p5ProTextToVideoDuration::FiveSeconds), - aspect_ratio: Some(EnqueueSeedance1p5ProTextToVideoAspectRatio::SixteenByNine), - resolution: Some(EnqueueSeedance1p5ProTextToVideoResolution::SevenTwentyP), - generate_audio: None, + request: EnqueueSeedance1p5ProTextToVideoRequest { + prompt: "a dinosaur walks through a misty forest at dawn, cinematic lighting".to_string(), + duration: Some(EnqueueSeedance1p5ProTextToVideoDuration::FiveSeconds), + aspect_ratio: Some(EnqueueSeedance1p5ProTextToVideoAspectRatio::SixteenByNine), + resolution: Some(EnqueueSeedance1p5ProTextToVideoResolution::SevenTwentyP), + generate_audio: None, + }, api_key: &api_key, webhook_url: "https://example.com/webhook", }; @@ -273,11 +272,13 @@ mod tests { for ar in EnqueueSeedance1p5ProTextToVideoAspectRatio::iter() { println!("--- aspect ratio: {:?} ---", ar); let args = EnqueueSeedance1p5ProTextToVideoArgs { - prompt: "a corgi runs along a beach at golden hour".to_string(), - duration: Some(EnqueueSeedance1p5ProTextToVideoDuration::FourSeconds), - aspect_ratio: Some(ar), - resolution: None, - generate_audio: None, + request: EnqueueSeedance1p5ProTextToVideoRequest { + prompt: "a corgi runs along a beach at golden hour".to_string(), + duration: Some(EnqueueSeedance1p5ProTextToVideoDuration::FourSeconds), + aspect_ratio: Some(ar), + resolution: None, + generate_audio: None, + }, api_key: &api_key, webhook_url: "https://example.com/webhook", }; @@ -297,11 +298,13 @@ mod tests { for dur in EnqueueSeedance1p5ProTextToVideoDuration::iter() { println!("--- duration: {:?} ---", dur); let args = EnqueueSeedance1p5ProTextToVideoArgs { - prompt: "a corgi runs along a beach at golden hour".to_string(), - duration: Some(dur), - aspect_ratio: Some(EnqueueSeedance1p5ProTextToVideoAspectRatio::SixteenByNine), - resolution: None, - generate_audio: None, + request: EnqueueSeedance1p5ProTextToVideoRequest { + prompt: "a corgi runs along a beach at golden hour".to_string(), + duration: Some(dur), + aspect_ratio: Some(EnqueueSeedance1p5ProTextToVideoAspectRatio::SixteenByNine), + resolution: None, + generate_audio: None, + }, api_key: &api_key, webhook_url: "https://example.com/webhook", }; @@ -321,11 +324,13 @@ mod tests { for res in EnqueueSeedance1p5ProTextToVideoResolution::iter() { println!("--- resolution: {:?} ---", res); let args = EnqueueSeedance1p5ProTextToVideoArgs { - prompt: "a bird flying over an ocean at golden hour".to_string(), - duration: Some(EnqueueSeedance1p5ProTextToVideoDuration::FourSeconds), - aspect_ratio: Some(EnqueueSeedance1p5ProTextToVideoAspectRatio::SixteenByNine), - resolution: Some(res), - generate_audio: None, + request: EnqueueSeedance1p5ProTextToVideoRequest { + prompt: "a bird flying over an ocean at golden hour".to_string(), + duration: Some(EnqueueSeedance1p5ProTextToVideoDuration::FourSeconds), + aspect_ratio: Some(EnqueueSeedance1p5ProTextToVideoAspectRatio::SixteenByNine), + resolution: Some(res), + generate_audio: None, + }, api_key: &api_key, webhook_url: "https://example.com/webhook", }; diff --git a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_sora_2_pro_text_to_video_webhook.rs b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_sora_2_pro_text_to_video_webhook.rs index bd9bc37c86..e7dcb075c8 100644 --- a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_sora_2_pro_text_to_video_webhook.rs +++ b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_sora_2_pro_text_to_video_webhook.rs @@ -7,17 +7,17 @@ use crate::requests::api::webhook_response::WebhookResponse; use reqwest::IntoUrl; pub struct EnqueueSora2ProTextToVideoArgs<'a, R: IntoUrl> { - // Request required - pub prompt: String, + pub request: EnqueueSora2ProTextToVideoRequest, + pub webhook_url: R, + pub api_key: &'a FalApiKey, +} - // Optional args +#[derive(Clone, Debug)] +pub struct EnqueueSora2ProTextToVideoRequest { + pub prompt: String, pub resolution: Option, pub duration: Option, pub aspect_ratio: Option, - - // Fulfillment - pub webhook_url: R, - pub api_key: &'a FalApiKey, } #[derive(Copy, Clone, Debug, strum::EnumIter)] @@ -40,7 +40,7 @@ pub enum EnqueueSora2ProTextToVideoAspectRatio { } -impl FalRequestCostCalculator for EnqueueSora2ProTextToVideoArgs<'_, U> { +impl FalRequestCostCalculator for EnqueueSora2ProTextToVideoRequest { fn calculate_cost_in_cents(&self) -> UsdCents { // Pricing: $0.30/s for 720p and $0.50/s for 1080p. let duration = self.duration.unwrap_or(EnqueueSora2ProTextToVideoDurationSeconds::Four); @@ -62,22 +62,23 @@ impl FalRequestCostCalculator for EnqueueSora2ProTextToVideoArgs<'_ pub async fn enqueue_sora_2_pro_text_to_video_webhook( args: EnqueueSora2ProTextToVideoArgs<'_, R> ) -> Result { + let req = args.request; - let duration = args.duration + let duration = req.duration .map(|d| match d { EnqueueSora2ProTextToVideoDurationSeconds::Four => 4, EnqueueSora2ProTextToVideoDurationSeconds::Eight => 8, EnqueueSora2ProTextToVideoDurationSeconds::Twelve => 12, }); - let resolution = args.resolution + let resolution = req.resolution .map(|r| match r { EnqueueSora2ProTextToVideoResolution::SevenTwentyP => "720p", EnqueueSora2ProTextToVideoResolution::TenEightyP => "1080p", }) .map(|r| r.to_string()); - let aspect_ratio = args.aspect_ratio + let aspect_ratio = req.aspect_ratio .map(|ar| match ar { EnqueueSora2ProTextToVideoAspectRatio::NineBySixteen => "9:16", EnqueueSora2ProTextToVideoAspectRatio::SixteenByNine => "16:9", @@ -85,7 +86,7 @@ pub async fn enqueue_sora_2_pro_text_to_video_webhook( .map(|ar| ar.to_string()); let request = Sora2ProTextToVideoInput { - prompt: args.prompt, + prompt: req.prompt, duration, resolution, aspect_ratio, @@ -115,10 +116,12 @@ mod tests { 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), + request: EnqueueSora2ProTextToVideoRequest { + 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", }; @@ -138,10 +141,12 @@ mod tests { for ar in EnqueueSora2ProTextToVideoAspectRatio::iter() { println!("--- aspect ratio: {:?} ---", ar); let args = EnqueueSora2ProTextToVideoArgs { - prompt: "a serene mountain lake at sunset with gentle ripples".to_string(), - duration: Some(EnqueueSora2ProTextToVideoDurationSeconds::Four), - aspect_ratio: Some(ar), - resolution: None, + request: EnqueueSora2ProTextToVideoRequest { + prompt: "a serene mountain lake at sunset with gentle ripples".to_string(), + duration: Some(EnqueueSora2ProTextToVideoDurationSeconds::Four), + aspect_ratio: Some(ar), + resolution: None, + }, api_key: &api_key, webhook_url: "https://example.com/webhook", }; @@ -161,10 +166,12 @@ mod tests { for dur in EnqueueSora2ProTextToVideoDurationSeconds::iter() { println!("--- duration: {:?} ---", dur); let args = EnqueueSora2ProTextToVideoArgs { - prompt: "Suspenseful Hollywood movie. Interior, night. Customers are eating at a city diner. Suddenly a t-rex bursts its head through the large windows. The customers run.".to_string(), - duration: Some(dur), - aspect_ratio: Some(EnqueueSora2ProTextToVideoAspectRatio::SixteenByNine), - resolution: None, + request: EnqueueSora2ProTextToVideoRequest { + prompt: "Suspenseful Hollywood movie. Interior, night. Customers are eating at a city diner. Suddenly a t-rex bursts its head through the large windows. The customers run.".to_string(), + duration: Some(dur), + aspect_ratio: Some(EnqueueSora2ProTextToVideoAspectRatio::SixteenByNine), + resolution: None, + }, api_key: &api_key, webhook_url: "https://example.com/webhook", }; @@ -184,10 +191,12 @@ mod tests { for res in EnqueueSora2ProTextToVideoResolution::iter() { println!("--- resolution: {:?} ---", res); let args = EnqueueSora2ProTextToVideoArgs { - prompt: "a bird flying over an ocean at golden hour".to_string(), - duration: Some(EnqueueSora2ProTextToVideoDurationSeconds::Four), - aspect_ratio: Some(EnqueueSora2ProTextToVideoAspectRatio::SixteenByNine), - resolution: Some(res), + request: EnqueueSora2ProTextToVideoRequest { + prompt: "a bird flying over an ocean at golden hour".to_string(), + duration: Some(EnqueueSora2ProTextToVideoDurationSeconds::Four), + aspect_ratio: Some(EnqueueSora2ProTextToVideoAspectRatio::SixteenByNine), + resolution: Some(res), + }, api_key: &api_key, webhook_url: "https://example.com/webhook", }; diff --git a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_sora_2_text_to_video_webhook.rs b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_sora_2_text_to_video_webhook.rs index 2d4addd818..25890ed6d3 100644 --- a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_sora_2_text_to_video_webhook.rs +++ b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_sora_2_text_to_video_webhook.rs @@ -7,17 +7,17 @@ use crate::requests::api::webhook_response::WebhookResponse; use reqwest::IntoUrl; pub struct EnqueueSora2TextToVideoArgs<'a, R: IntoUrl> { - // Request required - pub prompt: String, + pub request: EnqueueSora2TextToVideoRequest, + pub webhook_url: R, + pub api_key: &'a FalApiKey, +} - // Optional args +#[derive(Clone, Debug)] +pub struct EnqueueSora2TextToVideoRequest { + pub prompt: String, pub resolution: Option, pub duration: Option, pub aspect_ratio: Option, - - // Fulfillment - pub webhook_url: R, - pub api_key: &'a FalApiKey, } #[derive(Copy, Clone, Debug, strum::EnumIter)] @@ -39,7 +39,7 @@ pub enum EnqueueSora2TextToVideoAspectRatio { } -impl FalRequestCostCalculator for EnqueueSora2TextToVideoArgs<'_, U> { +impl FalRequestCostCalculator for EnqueueSora2TextToVideoRequest { fn calculate_cost_in_cents(&self) -> UsdCents { // "The pricing is $0.1/s for Sora 2." let duration = self.duration.unwrap_or(EnqueueSora2TextToVideoDurationSeconds::Four); @@ -56,21 +56,22 @@ impl FalRequestCostCalculator for EnqueueSora2TextToVideoArgs<'_, U pub async fn enqueue_sora_2_text_to_video_webhook( args: EnqueueSora2TextToVideoArgs<'_, R> ) -> Result { + let req = args.request; - let duration = args.duration + let duration = req.duration .map(|d| match d { EnqueueSora2TextToVideoDurationSeconds::Four => 4, EnqueueSora2TextToVideoDurationSeconds::Eight => 8, EnqueueSora2TextToVideoDurationSeconds::Twelve => 12, }); - let resolution = args.resolution + let resolution = req.resolution .map(|r| match r { EnqueueSora2TextToVideoResolution::SevenTwentyP => "720p", }) .map(|r| r.to_string()); - let aspect_ratio = args.aspect_ratio + let aspect_ratio = req.aspect_ratio .map(|ar| match ar { EnqueueSora2TextToVideoAspectRatio::NineBySixteen => "9:16", EnqueueSora2TextToVideoAspectRatio::SixteenByNine => "16:9", @@ -78,7 +79,7 @@ pub async fn enqueue_sora_2_text_to_video_webhook( .map(|ar| ar.to_string()); let request = Sora2TextToVideoInput { - prompt: args.prompt, + prompt: req.prompt, duration, resolution, aspect_ratio, @@ -108,10 +109,12 @@ mod tests { 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), + request: EnqueueSora2TextToVideoRequest { + 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", }; @@ -131,10 +134,12 @@ mod tests { for ar in EnqueueSora2TextToVideoAspectRatio::iter() { println!("--- aspect ratio: {:?} ---", ar); let args = EnqueueSora2TextToVideoArgs { - prompt: "a snowy mountain cabin at sunrise".to_string(), - duration: Some(EnqueueSora2TextToVideoDurationSeconds::Four), - aspect_ratio: Some(ar), - resolution: None, + request: EnqueueSora2TextToVideoRequest { + prompt: "a snowy mountain cabin at sunrise".to_string(), + duration: Some(EnqueueSora2TextToVideoDurationSeconds::Four), + aspect_ratio: Some(ar), + resolution: None, + }, api_key: &api_key, webhook_url: "https://example.com/webhook", }; @@ -154,10 +159,12 @@ mod tests { for dur in EnqueueSora2TextToVideoDurationSeconds::iter() { println!("--- duration: {:?} ---", dur); let args = EnqueueSora2TextToVideoArgs { - prompt: "a corgi walks in front of a giant windmill in a beautiful village at sunrise".to_string(), - duration: Some(dur), - aspect_ratio: Some(EnqueueSora2TextToVideoAspectRatio::SixteenByNine), - resolution: None, + request: EnqueueSora2TextToVideoRequest { + prompt: "a corgi walks in front of a giant windmill in a beautiful village at sunrise".to_string(), + duration: Some(dur), + aspect_ratio: Some(EnqueueSora2TextToVideoAspectRatio::SixteenByNine), + resolution: None, + }, api_key: &api_key, webhook_url: "https://example.com/webhook", }; diff --git a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_veo_2_text_to_video_webhook.rs b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_veo_2_text_to_video_webhook.rs index fe09736fd0..38c466d308 100644 --- a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_veo_2_text_to_video_webhook.rs +++ b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_veo_2_text_to_video_webhook.rs @@ -15,15 +15,20 @@ pub use crate::requests::webhook::video::image::enqueue_veo_2_image_to_video_web use reqwest::IntoUrl; pub struct Veo2TextToVideoArgs<'a, V: IntoUrl> { - pub prompt: &'a str, - pub negative_prompt: Option<&'a str>, - pub duration: Veo2Duration, - pub aspect_ratio: Veo2AspectRatio, + pub request: Veo2TextToVideoRequest, pub webhook_url: V, pub api_key: &'a FalApiKey, } -impl FalRequestCostCalculator for Veo2TextToVideoArgs<'_, V> { +#[derive(Clone, Debug)] +pub struct Veo2TextToVideoRequest { + pub prompt: String, + pub negative_prompt: Option, + pub duration: Veo2Duration, + pub aspect_ratio: Veo2AspectRatio, +} + +impl FalRequestCostCalculator for Veo2TextToVideoRequest { fn calculate_cost_in_cents(&self) -> UsdCents { // Same pricing as image-to-video: // "For 5s video your request will cost $2.50. @@ -43,7 +48,9 @@ impl FalRequestCostCalculator for Veo2TextToVideoArgs<'_, V> { pub async fn enqueue_veo_2_text_to_video_webhook( args: Veo2TextToVideoArgs<'_, V>, ) -> Result { - let duration = match args.duration { + let req = args.request; + + let duration = match req.duration { Veo2Duration::Default => None, Veo2Duration::FiveSeconds => Some("5s".to_string()), Veo2Duration::SixSeconds => Some("6s".to_string()), @@ -51,7 +58,7 @@ pub async fn enqueue_veo_2_text_to_video_webhook( Veo2Duration::EightSeconds => Some("8s".to_string()), }; - let aspect_ratio = match args.aspect_ratio { + let aspect_ratio = match req.aspect_ratio { Veo2AspectRatio::Auto => None, // Let the API default (16:9) Veo2AspectRatio::AutoPreferPortrait => Some("9:16".to_string()), Veo2AspectRatio::WideSixteenNine => Some("16:9".to_string()), @@ -59,10 +66,10 @@ pub async fn enqueue_veo_2_text_to_video_webhook( }; let request = Veo2TextToVideoInput { - prompt: args.prompt.to_string(), + prompt: req.prompt, aspect_ratio, duration, - negative_prompt: args.negative_prompt.map(|s| s.to_string()), + negative_prompt: req.negative_prompt, }; let result = veo_2_text_to_video(request) @@ -77,7 +84,8 @@ pub async fn enqueue_veo_2_text_to_video_webhook( mod tests { use crate::creds::fal_api_key::FalApiKey; use crate::requests::webhook::video::text::enqueue_veo_2_text_to_video_webhook::{ - enqueue_veo_2_text_to_video_webhook, Veo2TextToVideoArgs, Veo2AspectRatio, Veo2Duration, + enqueue_veo_2_text_to_video_webhook, Veo2TextToVideoArgs, Veo2TextToVideoRequest, + Veo2AspectRatio, Veo2Duration, }; use errors::AnyhowResult; use std::fs::read_to_string; @@ -89,11 +97,13 @@ mod tests { let api_key = FalApiKey::from_str(&secret); let args = Veo2TextToVideoArgs { - prompt: "a drone shot of a coastal sunset with waves crashing on rocks", - negative_prompt: None, + request: Veo2TextToVideoRequest { + prompt: "a drone shot of a coastal sunset with waves crashing on rocks".to_string(), + negative_prompt: None, + duration: Veo2Duration::FiveSeconds, + aspect_ratio: Veo2AspectRatio::WideSixteenNine, + }, api_key: &api_key, - duration: Veo2Duration::FiveSeconds, - aspect_ratio: Veo2AspectRatio::WideSixteenNine, webhook_url: "https://example.com/webhook", }; diff --git a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_veo_3_text_to_video_webhook.rs b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_veo_3_text_to_video_webhook.rs index 0d30e746a7..4871398716 100644 --- a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_veo_3_text_to_video_webhook.rs +++ b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_veo_3_text_to_video_webhook.rs @@ -11,14 +11,19 @@ use crate::requests::traits::fal_request_cost_calculator_trait::{ use reqwest::IntoUrl; pub struct Veo3TextToVideoArgs<'a, V: IntoUrl> { - pub prompt: &'a str, - pub negative_prompt: Option<&'a str>, + pub request: Veo3TextToVideoRequest, + pub webhook_url: V, + pub api_key: &'a FalApiKey, +} + +#[derive(Clone, Debug)] +pub struct Veo3TextToVideoRequest { + pub prompt: String, + pub negative_prompt: Option, pub duration: Veo3T2vDuration, pub aspect_ratio: Veo3T2vAspectRatio, pub resolution: Veo3T2vResolution, pub generate_audio: bool, - pub webhook_url: V, - pub api_key: &'a FalApiKey, } /// Duration for Veo 3 text-to-video. Default is 8 seconds. @@ -47,7 +52,7 @@ pub enum Veo3T2vResolution { TenEightyP, } -impl FalRequestCostCalculator for Veo3TextToVideoArgs<'_, V> { +impl FalRequestCostCalculator for Veo3TextToVideoRequest { fn calculate_cost_in_cents(&self) -> UsdCents { // $0.20/sec audio off, $0.40/sec audio on. match (self.duration, self.generate_audio) { @@ -68,32 +73,34 @@ impl FalRequestCostCalculator for Veo3TextToVideoArgs<'_, V> { pub async fn enqueue_veo_3_text_to_video_webhook( args: Veo3TextToVideoArgs<'_, V>, ) -> Result { - let duration = match args.duration { + let req = args.request; + + let duration = match req.duration { Veo3T2vDuration::Default => None, Veo3T2vDuration::FourSeconds => Some("4s".to_string()), Veo3T2vDuration::SixSeconds => Some("6s".to_string()), Veo3T2vDuration::EightSeconds => Some("8s".to_string()), }; - let aspect_ratio = match args.aspect_ratio { + let aspect_ratio = match req.aspect_ratio { Veo3T2vAspectRatio::Default => None, Veo3T2vAspectRatio::WideSixteenNine => Some("16:9".to_string()), Veo3T2vAspectRatio::TallNineSixteen => Some("9:16".to_string()), }; - let resolution = match args.resolution { + let resolution = match req.resolution { Veo3T2vResolution::Default => None, Veo3T2vResolution::SevenTwentyP => Some("720p".to_string()), Veo3T2vResolution::TenEightyP => Some("1080p".to_string()), }; let request = Veo3TextToVideoInput { - prompt: args.prompt.to_string(), + prompt: req.prompt, aspect_ratio, resolution, duration, - generate_audio: Some(args.generate_audio), - negative_prompt: args.negative_prompt.map(|s| s.to_string()), + generate_audio: Some(req.generate_audio), + negative_prompt: req.negative_prompt, }; let result = veo_3_text_to_video(request) @@ -108,8 +115,8 @@ pub async fn enqueue_veo_3_text_to_video_webhook( mod tests { use crate::creds::fal_api_key::FalApiKey; use crate::requests::webhook::video::text::enqueue_veo_3_text_to_video_webhook::{ - enqueue_veo_3_text_to_video_webhook, Veo3TextToVideoArgs, Veo3T2vAspectRatio, - Veo3T2vDuration, Veo3T2vResolution, + enqueue_veo_3_text_to_video_webhook, Veo3TextToVideoArgs, Veo3TextToVideoRequest, + Veo3T2vAspectRatio, Veo3T2vDuration, Veo3T2vResolution, }; use errors::AnyhowResult; use std::fs::read_to_string; @@ -121,13 +128,15 @@ mod tests { let api_key = FalApiKey::from_str(&secret); let args = Veo3TextToVideoArgs { - prompt: "a drone shot of a coastal sunset with waves crashing on rocks", - negative_prompt: None, + request: Veo3TextToVideoRequest { + prompt: "a drone shot of a coastal sunset with waves crashing on rocks".to_string(), + negative_prompt: None, + duration: Veo3T2vDuration::EightSeconds, + aspect_ratio: Veo3T2vAspectRatio::WideSixteenNine, + resolution: Veo3T2vResolution::TenEightyP, + generate_audio: true, + }, api_key: &api_key, - duration: Veo3T2vDuration::EightSeconds, - aspect_ratio: Veo3T2vAspectRatio::WideSixteenNine, - resolution: Veo3T2vResolution::TenEightyP, - generate_audio: true, webhook_url: "https://example.com/webhook", }; diff --git a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_veo_3p1_fast_text_to_video_webhook.rs b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_veo_3p1_fast_text_to_video_webhook.rs index 150939fb68..cc31f716da 100644 --- a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_veo_3p1_fast_text_to_video_webhook.rs +++ b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_veo_3p1_fast_text_to_video_webhook.rs @@ -7,10 +7,14 @@ use crate::requests::api::webhook_response::WebhookResponse; use reqwest::IntoUrl; pub struct EnqueueVeo3p1FastTextToVideoArgs<'a, R: IntoUrl> { - // Request required - pub prompt: String, + pub request: EnqueueVeo3p1FastTextToVideoRequest, + pub webhook_url: R, + pub api_key: &'a FalApiKey, +} - // Optional args +#[derive(Clone, Debug)] +pub struct EnqueueVeo3p1FastTextToVideoRequest { + pub prompt: String, pub duration: Option, pub aspect_ratio: Option, pub resolution: Option, @@ -19,10 +23,6 @@ pub struct EnqueueVeo3p1FastTextToVideoArgs<'a, R: IntoUrl> { pub negative_prompt: Option, pub seed: Option, pub auto_fix: Option, - - // Fulfillment - pub webhook_url: R, - pub api_key: &'a FalApiKey, } #[derive(Copy, Clone, Debug)] @@ -45,7 +45,7 @@ pub enum EnqueueVeo3p1FastTextToVideoResolution { TenEightyP, } -impl FalRequestCostCalculator for EnqueueVeo3p1FastTextToVideoArgs<'_, R> { +impl FalRequestCostCalculator for EnqueueVeo3p1FastTextToVideoRequest { fn calculate_cost_in_cents(&self) -> UsdCents { // "For every second of video you generated, you will be charged // $0.10 (audio off) or @@ -73,8 +73,9 @@ impl FalRequestCostCalculator for EnqueueVeo3p1FastTextToVideoArgs< pub async fn enqueue_veo_3p1_fast_text_to_video_webhook( args: EnqueueVeo3p1FastTextToVideoArgs<'_, R> ) -> Result { + let req = args.request; - let duration = args.duration + let duration = req.duration .map(|resolution| match resolution { EnqueueVeo3p1FastTextToVideoDurationSeconds::Four => "4s", EnqueueVeo3p1FastTextToVideoDurationSeconds::Six => "6s", @@ -82,7 +83,7 @@ pub async fn enqueue_veo_3p1_fast_text_to_video_webhook( }) .map(|s| s.to_string()); - let aspect_ratio = args.aspect_ratio + let aspect_ratio = req.aspect_ratio .map(|aspect_ratio| match aspect_ratio { EnqueueVeo3p1FastTextToVideoAspectRatio::Auto => "auto", EnqueueVeo3p1FastTextToVideoAspectRatio::SixteenByNine => "16:9", @@ -90,7 +91,7 @@ pub async fn enqueue_veo_3p1_fast_text_to_video_webhook( }) .map(|s| s.to_string()); - let resolution = args.resolution + let resolution = req.resolution .map(|resolution| match resolution { EnqueueVeo3p1FastTextToVideoResolution::SevenTwentyP => "720p", EnqueueVeo3p1FastTextToVideoResolution::TenEightyP => "1080p", @@ -98,16 +99,16 @@ pub async fn enqueue_veo_3p1_fast_text_to_video_webhook( .map(|s| s.to_string()); let request = Veo3p1FastTextToVideoInput { - prompt: args.prompt, + prompt: req.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, + negative_prompt: req.negative_prompt, + generate_audio: req.generate_audio, + enhance_prompt: req.enhance_prompt, + seed: req.seed, + auto_fix: req.auto_fix, }; let result = veo_3p1_fast_text_to_video(request) @@ -121,7 +122,7 @@ pub async fn enqueue_veo_3p1_fast_text_to_video_webhook( #[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 crate::requests::webhook::video::text::enqueue_veo_3p1_fast_text_to_video_webhook::{enqueue_veo_3p1_fast_text_to_video_webhook, EnqueueVeo3p1FastTextToVideoArgs, EnqueueVeo3p1FastTextToVideoRequest, EnqueueVeo3p1FastTextToVideoAspectRatio, EnqueueVeo3p1FastTextToVideoDurationSeconds, EnqueueVeo3p1FastTextToVideoResolution}; use errors::AnyhowResult; use std::fs::read_to_string; @@ -134,15 +135,17 @@ mod tests { 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, + request: EnqueueVeo3p1FastTextToVideoRequest { + 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", }; diff --git a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_veo_3p1_text_to_video_webhook.rs b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_veo_3p1_text_to_video_webhook.rs index 18acc82b9c..b3025e0d0f 100644 --- a/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_veo_3p1_text_to_video_webhook.rs +++ b/crates/api_clients/fal_client/src/requests/webhook/video/text/enqueue_veo_3p1_text_to_video_webhook.rs @@ -7,10 +7,14 @@ use crate::requests::api::webhook_response::WebhookResponse; use reqwest::IntoUrl; pub struct EnqueueVeo3p1TextToVideoArgs<'a, R: IntoUrl> { - // Request required - pub prompt: String, + pub request: EnqueueVeo3p1TextToVideoRequest, + pub webhook_url: R, + pub api_key: &'a FalApiKey, +} - // Optional args +#[derive(Clone, Debug)] +pub struct EnqueueVeo3p1TextToVideoRequest { + pub prompt: String, pub duration: Option, pub aspect_ratio: Option, pub resolution: Option, @@ -19,10 +23,6 @@ pub struct EnqueueVeo3p1TextToVideoArgs<'a, R: IntoUrl> { pub negative_prompt: Option, pub seed: Option, pub auto_fix: Option, - - // Fulfillment - pub webhook_url: R, - pub api_key: &'a FalApiKey, } #[derive(Copy, Clone, Debug)] @@ -46,7 +46,7 @@ pub enum EnqueueVeo3p1TextToVideoResolution { } -impl FalRequestCostCalculator for EnqueueVeo3p1TextToVideoArgs<'_, R> { +impl FalRequestCostCalculator for EnqueueVeo3p1TextToVideoRequest { fn calculate_cost_in_cents(&self) -> UsdCents { // "For every second of video you generated, you will be charged // $0.20 (audio off) or @@ -74,8 +74,9 @@ impl FalRequestCostCalculator for EnqueueVeo3p1TextToVideoArgs<'_, pub async fn enqueue_veo_3p1_text_to_video_webhook( args: EnqueueVeo3p1TextToVideoArgs<'_, R> ) -> Result { + let req = args.request; - let duration = args.duration + let duration = req.duration .map(|resolution| match resolution { EnqueueVeo3p1TextToVideoDurationSeconds::Four => "4s", EnqueueVeo3p1TextToVideoDurationSeconds::Six => "6s", @@ -83,7 +84,7 @@ pub async fn enqueue_veo_3p1_text_to_video_webhook( }) .map(|s| s.to_string()); - let aspect_ratio = args.aspect_ratio + let aspect_ratio = req.aspect_ratio .map(|aspect_ratio| match aspect_ratio { EnqueueVeo3p1TextToVideoAspectRatio::Auto => "auto", EnqueueVeo3p1TextToVideoAspectRatio::SixteenByNine => "16:9", @@ -91,7 +92,7 @@ pub async fn enqueue_veo_3p1_text_to_video_webhook( }) .map(|s| s.to_string()); - let resolution = args.resolution + let resolution = req.resolution .map(|resolution| match resolution { EnqueueVeo3p1TextToVideoResolution::SevenTwentyP => "720p", EnqueueVeo3p1TextToVideoResolution::TenEightyP => "1080p", @@ -99,16 +100,16 @@ pub async fn enqueue_veo_3p1_text_to_video_webhook( .map(|s| s.to_string()); let request = Veo3p1TextToVideoInput { - prompt: args.prompt, + prompt: req.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, + negative_prompt: req.negative_prompt, + generate_audio: req.generate_audio, + enhance_prompt: req.enhance_prompt, + seed: req.seed, + auto_fix: req.auto_fix, }; let result = veo_3p1_text_to_video(request) @@ -122,7 +123,7 @@ pub async fn enqueue_veo_3p1_text_to_video_webhook( #[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 crate::requests::webhook::video::text::enqueue_veo_3p1_text_to_video_webhook::{enqueue_veo_3p1_text_to_video_webhook, EnqueueVeo3p1TextToVideoArgs, EnqueueVeo3p1TextToVideoRequest, EnqueueVeo3p1TextToVideoAspectRatio, EnqueueVeo3p1TextToVideoDurationSeconds, EnqueueVeo3p1TextToVideoResolution}; use errors::AnyhowResult; use std::fs::read_to_string; @@ -135,15 +136,17 @@ mod tests { 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, + request: EnqueueVeo3p1TextToVideoRequest { + 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", }; diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/kling_2p5_turbo_pro_multi_function_video_gen_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/kling_2p5_turbo_pro_multi_function_video_gen_handler.rs index ff7e2e5e20..fde3b1f222 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/kling_2p5_turbo_pro_multi_function_video_gen_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/kling_2p5_turbo_pro_multi_function_video_gen_handler.rs @@ -26,7 +26,7 @@ use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestC use fal_client::requests::webhook::image::edit::enqueue_gpt_image_1p5_edit_image_webhook::{enqueue_gpt_image_1p5_image_edit_webhook, EnqueueGptImage1p5EditImageArgs, EnqueueGptImage1p5EditImageBackground, EnqueueGptImage1p5EditImageInputFidelity, EnqueueGptImage1p5EditImageNumImages, EnqueueGptImage1p5EditImageQuality, EnqueueGptImage1p5EditImageRequest, EnqueueGptImage1p5EditImageSize}; use fal_client::requests::webhook::image::text::enqueue_gpt_image_1p5_text_to_image_webhook::{enqueue_gpt_image_1p5_text_to_image_webhook, EnqueueGptImage1p5TextToImageArgs, EnqueueGptImage1p5TextToImageBackground, EnqueueGptImage1p5TextToImageNumImages, EnqueueGptImage1p5TextToImageQuality, EnqueueGptImage1p5TextToImageSize}; use fal_client::requests::webhook::video::image::enqueue_kling_v2p5_turbo_pro_image_to_video_webhook::{enqueue_kling_v2p5_turbo_pro_image_to_video_webhook, EnqueueKlingV2p5TurboProImageToVideoArgs, EnqueueKlingV2p5TurboProImageToVideoRequest, EnqueueKlingV2p5TurboProImageToVideoDurationSeconds}; -use fal_client::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 fal_client::requests::webhook::video::text::enqueue_kling_v2p5_turbo_pro_text_to_video_webhook::{enqueue_kling_v2p5_turbo_pro_text_to_video_webhook, EnqueueKlingV2p5TurboProTextToVideoArgs, EnqueueKlingV2p5TurboProTextToVideoRequest, EnqueueKlingV2p5TurboProTextToVideoAspectRatio, EnqueueKlingV2p5TurboProTextToVideoDurationSeconds}; use http_server_common::request::get_request_ip::get_request_ip; use log::{error, info, warn}; use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::insert_generic_inference_job_for_fal_queue; @@ -214,17 +214,21 @@ pub async fn kling_2p5_turbo_pro_multi_function_video_gen_handler( None => EnqueueKlingV2p5TurboProTextToVideoAspectRatio::Square, }; - let args = EnqueueKlingV2p5TurboProTextToVideoArgs { + let t2v_request = EnqueueKlingV2p5TurboProTextToVideoRequest { prompt: request.prompt.as_deref().unwrap_or("").to_string(), negative_prompt: request.negative_prompt.clone(), duration: Some(duration), aspect_ratio: Some(aspect_ratio), + }; + + let cost = t2v_request.calculate_cost_in_cents(); + + let args = EnqueueKlingV2p5TurboProTextToVideoArgs { + request: t2v_request, webhook_url: &server_state.fal.webhook_url, api_key: &server_state.fal.api_key, }; - let cost = args.calculate_cost_in_cents(); - info!("Charging wallet: {}", cost); attempt_wallet_deduction_else_common_web_error( diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/kling_2p6_pro_multi_function_video_gen_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/kling_2p6_pro_multi_function_video_gen_handler.rs index 93e42ffeac..0d02fcb556 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/kling_2p6_pro_multi_function_video_gen_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/kling_2p6_pro_multi_function_video_gen_handler.rs @@ -24,7 +24,7 @@ use enums::common::visibility::Visibility; use fal_client::creds::open_ai_api_key::OpenAiApiKey; use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator; use fal_client::requests::webhook::video::image::enqueue_kling_v2p6_pro_image_to_video_webhook::{enqueue_kling_v2p6_pro_image_to_video_webhook, EnqueueKlingV2p6ProImageToVideoArgs, EnqueueKlingV2p6ProImageToVideoRequest, EnqueueKlingV2p6ProImageToVideoDurationSeconds}; -use fal_client::requests::webhook::video::text::enqueue_kling_v2p6_pro_text_to_video_webhook::{enqueue_kling_v2p6_pro_text_to_video_webhook, EnqueueKlingV2p6ProTextToVideoArgs, EnqueueKlingV2p6ProTextToVideoAspectRatio, EnqueueKlingV2p6ProTextToVideoDurationSeconds}; +use fal_client::requests::webhook::video::text::enqueue_kling_v2p6_pro_text_to_video_webhook::{enqueue_kling_v2p6_pro_text_to_video_webhook, EnqueueKlingV2p6ProTextToVideoArgs, EnqueueKlingV2p6ProTextToVideoRequest, EnqueueKlingV2p6ProTextToVideoAspectRatio, EnqueueKlingV2p6ProTextToVideoDurationSeconds}; use http_server_common::request::get_request_ip::get_request_ip; use log::{error, info, warn}; use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::FalCategory; @@ -210,17 +210,21 @@ pub async fn kling_2p6_pro_multi_function_video_gen_handler( None => EnqueueKlingV2p6ProTextToVideoAspectRatio::Square, }; - let args = EnqueueKlingV2p6ProTextToVideoArgs { + let t2v_request = EnqueueKlingV2p6ProTextToVideoRequest { prompt: request.prompt.as_deref().unwrap_or("").to_string(), negative_prompt: request.negative_prompt.clone(), generate_audio: request.generate_audio, duration: Some(duration), aspect_ratio: Some(aspect_ratio), + }; + + let cost = t2v_request.calculate_cost_in_cents(); + + let args = EnqueueKlingV2p6ProTextToVideoArgs { + request: t2v_request, webhook_url: &server_state.fal.webhook_url, api_key: &server_state.fal.api_key, }; - - let cost = args.calculate_cost_in_cents(); info!("Charging wallet..."); diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/kling_3p0_pro_multi_function_video_gen_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/kling_3p0_pro_multi_function_video_gen_handler.rs index 3b9ccfb3f3..309e5734b2 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/kling_3p0_pro_multi_function_video_gen_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/kling_3p0_pro_multi_function_video_gen_handler.rs @@ -24,7 +24,7 @@ use enums::common::visibility::Visibility; use fal_client::creds::open_ai_api_key::OpenAiApiKey; use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator; use fal_client::requests::webhook::video::image::enqueue_kling_3p0_pro_image_to_video_webhook::{enqueue_kling_3p0_pro_image_to_video_webhook, EnqueueKling3p0ProImageToVideoArgs, EnqueueKling3p0ProImageToVideoRequest, EnqueueKling3p0ProImageToVideoAspectRatio, EnqueueKling3p0ProImageToVideoDuration}; -use fal_client::requests::webhook::video::text::enqueue_kling_3p0_pro_text_to_video_webhook::{enqueue_kling_3p0_pro_text_to_video_webhook, EnqueueKling3p0ProTextToVideoArgs, EnqueueKling3p0ProTextToVideoAspectRatio, EnqueueKling3p0ProTextToVideoDuration}; +use fal_client::requests::webhook::video::text::enqueue_kling_3p0_pro_text_to_video_webhook::{enqueue_kling_3p0_pro_text_to_video_webhook, EnqueueKling3p0ProTextToVideoArgs, EnqueueKling3p0ProTextToVideoRequest, EnqueueKling3p0ProTextToVideoAspectRatio, EnqueueKling3p0ProTextToVideoDuration}; use http_server_common::request::get_request_ip::get_request_ip; use log::{error, info, warn}; use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::FalCategory; @@ -203,19 +203,23 @@ pub async fn kling_3p0_pro_multi_function_video_gen_handler( let aspect_ratio = map_aspect_ratio_t2v(request.aspect_ratio); - let args = EnqueueKling3p0ProTextToVideoArgs { + let t2v_request = EnqueueKling3p0ProTextToVideoRequest { prompt: request.prompt.as_deref().unwrap_or("").to_string(), negative_prompt: request.negative_prompt.clone(), generate_audio: Some(generate_audio), duration: Some(duration), aspect_ratio: Some(aspect_ratio), shot_type: None, + }; + + let cost = t2v_request.calculate_cost_in_cents(); + + let args = EnqueueKling3p0ProTextToVideoArgs { + request: t2v_request, webhook_url: &server_state.fal.webhook_url, api_key: &server_state.fal.api_key, }; - let cost = args.calculate_cost_in_cents(); - info!("Charging wallet..."); attempt_wallet_deduction_else_common_web_error( diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/kling_3p0_standard_multi_function_video_gen_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/kling_3p0_standard_multi_function_video_gen_handler.rs index 300787307b..9832912d89 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/kling_3p0_standard_multi_function_video_gen_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/kling_3p0_standard_multi_function_video_gen_handler.rs @@ -24,7 +24,7 @@ use enums::common::visibility::Visibility; use fal_client::creds::open_ai_api_key::OpenAiApiKey; use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator; use fal_client::requests::webhook::video::image::enqueue_kling_3p0_standard_image_to_video_webhook::{enqueue_kling_3p0_standard_image_to_video_webhook, EnqueueKling3p0StandardImageToVideoArgs, EnqueueKling3p0StandardImageToVideoRequest, EnqueueKling3p0StandardImageToVideoAspectRatio, EnqueueKling3p0StandardImageToVideoDuration}; -use fal_client::requests::webhook::video::text::enqueue_kling_3p0_standard_text_to_video_webhook::{enqueue_kling_3p0_standard_text_to_video_webhook, EnqueueKling3p0StandardTextToVideoArgs, EnqueueKling3p0StandardTextToVideoAspectRatio, EnqueueKling3p0StandardTextToVideoDuration}; +use fal_client::requests::webhook::video::text::enqueue_kling_3p0_standard_text_to_video_webhook::{enqueue_kling_3p0_standard_text_to_video_webhook, EnqueueKling3p0StandardTextToVideoArgs, EnqueueKling3p0StandardTextToVideoRequest, EnqueueKling3p0StandardTextToVideoAspectRatio, EnqueueKling3p0StandardTextToVideoDuration}; use http_server_common::request::get_request_ip::get_request_ip; use log::{error, info, warn}; use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::FalCategory; @@ -203,19 +203,23 @@ pub async fn kling_3p0_standard_multi_function_video_gen_handler( let aspect_ratio = map_aspect_ratio_t2v(request.aspect_ratio); - let args = EnqueueKling3p0StandardTextToVideoArgs { + let t2v_request = EnqueueKling3p0StandardTextToVideoRequest { prompt: request.prompt.as_deref().unwrap_or("").to_string(), negative_prompt: request.negative_prompt.clone(), generate_audio: Some(generate_audio), duration: Some(duration), aspect_ratio: Some(aspect_ratio), shot_type: None, + }; + + let cost = t2v_request.calculate_cost_in_cents(); + + let args = EnqueueKling3p0StandardTextToVideoArgs { + request: t2v_request, webhook_url: &server_state.fal.webhook_url, api_key: &server_state.fal.api_key, }; - let cost = args.calculate_cost_in_cents(); - info!("Charging wallet..."); attempt_wallet_deduction_else_common_web_error( diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/sora_2_multi_function_video_gen_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/sora_2_multi_function_video_gen_handler.rs index 09ae832fda..4c48634cd0 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/sora_2_multi_function_video_gen_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/sora_2_multi_function_video_gen_handler.rs @@ -24,7 +24,7 @@ use enums::common::generation::common_generation_mode::CommonGenerationMode; use fal_client::creds::open_ai_api_key::OpenAiApiKey; use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator; use fal_client::requests::webhook::video::image::enqueue_sora_2_image_to_video_webhook::{enqueue_sora_2_image_to_video_webhook, EnqueueSora2ImageToVideoArgs, EnqueueSora2ImageToVideoAspectRatio, EnqueueSora2ImageToVideoDurationSeconds, EnqueueSora2ImageToVideoRequest, EnqueueSora2ImageToVideoResolution}; -use fal_client::requests::webhook::video::text::enqueue_sora_2_text_to_video_webhook::{enqueue_sora_2_text_to_video_webhook, EnqueueSora2TextToVideoArgs, EnqueueSora2TextToVideoAspectRatio, EnqueueSora2TextToVideoDurationSeconds, EnqueueSora2TextToVideoResolution}; +use fal_client::requests::webhook::video::text::enqueue_sora_2_text_to_video_webhook::{enqueue_sora_2_text_to_video_webhook, EnqueueSora2TextToVideoArgs, EnqueueSora2TextToVideoRequest, EnqueueSora2TextToVideoAspectRatio, EnqueueSora2TextToVideoDurationSeconds, EnqueueSora2TextToVideoResolution}; use http_server_common::request::get_request_ip::get_request_ip; use log::{error, info, warn}; use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::insert_generic_inference_job_for_fal_queue; @@ -231,16 +231,14 @@ pub async fn sora_2_multi_function_video_gen_handler( None => EnqueueSora2TextToVideoResolution::SevenTwentyP, }; - let args = EnqueueSora2TextToVideoArgs { + let t2v_request = EnqueueSora2TextToVideoRequest { prompt: request.prompt.as_deref().unwrap_or("").to_string(), duration: Some(duration), aspect_ratio: Some(aspect_ratio), resolution: Some(resolution), - webhook_url: &server_state.fal.webhook_url, - api_key: &server_state.fal.api_key, }; - let cost = args.calculate_cost_in_cents(); + let cost = t2v_request.calculate_cost_in_cents(); info!("Charging wallet: {}", cost); @@ -251,6 +249,12 @@ pub async fn sora_2_multi_function_video_gen_handler( &mut mysql_connection, ).await?; + let args = EnqueueSora2TextToVideoArgs { + request: t2v_request, + webhook_url: &server_state.fal.webhook_url, + api_key: &server_state.fal.api_key, + }; + fal_result = enqueue_sora_2_text_to_video_webhook(args) .await .map_err(|err| { diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/sora_2_pro_multi_function_video_gen_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/sora_2_pro_multi_function_video_gen_handler.rs index 8d715e3535..f62faf5560 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/sora_2_pro_multi_function_video_gen_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/sora_2_pro_multi_function_video_gen_handler.rs @@ -24,7 +24,7 @@ use enums::common::generation::common_generation_mode::CommonGenerationMode; use fal_client::creds::open_ai_api_key::OpenAiApiKey; use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator; use fal_client::requests::webhook::video::image::enqueue_sora_2_pro_image_to_video_webhook::{enqueue_sora_2_pro_image_to_video_webhook, EnqueueSora2ProImageToVideoArgs, EnqueueSora2ProImageToVideoAspectRatio, EnqueueSora2ProImageToVideoDurationSeconds, EnqueueSora2ProImageToVideoRequest, EnqueueSora2ProImageToVideoResolution}; -use fal_client::requests::webhook::video::text::enqueue_sora_2_pro_text_to_video_webhook::{enqueue_sora_2_pro_text_to_video_webhook, EnqueueSora2ProTextToVideoArgs, EnqueueSora2ProTextToVideoAspectRatio, EnqueueSora2ProTextToVideoDurationSeconds, EnqueueSora2ProTextToVideoResolution}; +use fal_client::requests::webhook::video::text::enqueue_sora_2_pro_text_to_video_webhook::{enqueue_sora_2_pro_text_to_video_webhook, EnqueueSora2ProTextToVideoArgs, EnqueueSora2ProTextToVideoRequest, EnqueueSora2ProTextToVideoAspectRatio, EnqueueSora2ProTextToVideoDurationSeconds, EnqueueSora2ProTextToVideoResolution}; use http_server_common::request::get_request_ip::get_request_ip; use log::{error, info, warn}; use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::insert_generic_inference_job_for_fal_queue; @@ -233,16 +233,14 @@ pub async fn sora_2_pro_multi_function_video_gen_handler( None => EnqueueSora2ProTextToVideoResolution::TenEightyP, }; - let args = EnqueueSora2ProTextToVideoArgs { + let t2v_request = EnqueueSora2ProTextToVideoRequest { prompt: request.prompt.as_deref().unwrap_or("").to_string(), duration: Some(duration), aspect_ratio: Some(aspect_ratio), resolution: Some(resolution), - webhook_url: &server_state.fal.webhook_url, - api_key: &server_state.fal.api_key, }; - let cost = args.calculate_cost_in_cents(); + let cost = t2v_request.calculate_cost_in_cents(); info!("Charging wallet: {}", cost); @@ -253,6 +251,12 @@ pub async fn sora_2_pro_multi_function_video_gen_handler( &mut mysql_connection, ).await?; + let args = EnqueueSora2ProTextToVideoArgs { + request: t2v_request, + webhook_url: &server_state.fal.webhook_url, + api_key: &server_state.fal.api_key, + }; + fal_result = enqueue_sora_2_pro_text_to_video_webhook(args) .await .map_err(|err| { diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/veo_3p1_multi_function_video_gen_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/veo_3p1_multi_function_video_gen_handler.rs index 83eee8fd30..6973b9686b 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/veo_3p1_multi_function_video_gen_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/video/multi_function/veo_3p1_multi_function_video_gen_handler.rs @@ -25,7 +25,7 @@ use fal_client::creds::open_ai_api_key::OpenAiApiKey; use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator; use fal_client::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, EnqueueVeo3p1FirstLastFrameImageToVideoRequest, EnqueueVeo3p1FirstLastFrameImageToVideoResolution}; use fal_client::requests::webhook::video::image::enqueue_veo_3p1_image_to_video_webhook::{enqueue_veo_3p1_image_to_video_webhook, EnqueueVeo3p1ImageToVideoArgs, EnqueueVeo3p1ImageToVideoAspectRatio, EnqueueVeo3p1ImageToVideoDurationSeconds, EnqueueVeo3p1ImageToVideoRequest, EnqueueVeo3p1ImageToVideoResolution}; -use fal_client::requests::webhook::video::text::enqueue_veo_3p1_text_to_video_webhook::{enqueue_veo_3p1_text_to_video_webhook, EnqueueVeo3p1TextToVideoArgs, EnqueueVeo3p1TextToVideoAspectRatio, EnqueueVeo3p1TextToVideoDurationSeconds, EnqueueVeo3p1TextToVideoResolution}; +use fal_client::requests::webhook::video::text::enqueue_veo_3p1_text_to_video_webhook::{enqueue_veo_3p1_text_to_video_webhook, EnqueueVeo3p1TextToVideoArgs, EnqueueVeo3p1TextToVideoRequest, EnqueueVeo3p1TextToVideoAspectRatio, EnqueueVeo3p1TextToVideoDurationSeconds, EnqueueVeo3p1TextToVideoResolution}; use http_server_common::request::get_request_ip::get_request_ip; use log::{error, info, warn}; use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::insert_generic_inference_job_for_fal_queue; @@ -296,7 +296,7 @@ pub async fn veo_3p1_multi_function_video_gen_handler( None => EnqueueVeo3p1TextToVideoResolution::TenEightyP, }; - let args = EnqueueVeo3p1TextToVideoArgs { + let t2v_request = EnqueueVeo3p1TextToVideoRequest { prompt: request.prompt.as_deref().unwrap_or("").to_string(), negative_prompt: request.negative_prompt.clone(), duration: Some(duration), @@ -306,11 +306,9 @@ pub async fn veo_3p1_multi_function_video_gen_handler( enhance_prompt: Some(true), auto_fix: Some(true), seed: None, - webhook_url: &server_state.fal.webhook_url, - api_key: &server_state.fal.api_key, }; - - let cost = args.calculate_cost_in_cents(); + + let cost = t2v_request.calculate_cost_in_cents(); info!("Charging wallet: {}", cost); @@ -321,6 +319,12 @@ pub async fn veo_3p1_multi_function_video_gen_handler( &mut mysql_connection, ).await?; + let args = EnqueueVeo3p1TextToVideoArgs { + request: t2v_request, + webhook_url: &server_state.fal.webhook_url, + api_key: &server_state.fal.api_key, + }; + fal_result = enqueue_veo_3p1_text_to_video_webhook(args) .await .map_err(|err| {