diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/generate_video_request_builder.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/generate_video_request_builder.rs index 42b7be0371..307a20f8ad 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/generate_video_request_builder.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/generate_video_request_builder.rs @@ -114,6 +114,14 @@ pub struct GenerateVideoRequestBuilder { } impl GenerateVideoRequestBuilder { + + pub fn use_new_builder(&self) -> bool { + match (self.provider, self.model) { + (Provider::Seedance2Pro, CommonVideoModel::Seedance2p0) => true, + _ => false, + } + } + // New builder (transitional state) pub fn build2(self) -> Result { match (self.provider, self.model) { @@ -121,7 +129,7 @@ impl GenerateVideoRequestBuilder { _ => self.unsupported_provider_and_model(), } } - + /// Read the video generation request, construct a plan, then yield a means to execute it. pub fn build(&self) -> Result { match self.provider { diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/video_generation_cost_estimate.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/video_generation_cost_estimate.rs index d521e609fa..7900b4f83f 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/video_generation_cost_estimate.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/video_generation_cost_estimate.rs @@ -1,5 +1,5 @@ /// The result of estimating the cost of a video generation plan. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct VideoGenerationCostEstimate { pub cost_in_credits: Option, pub cost_in_usd_cents: Option, diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/cost.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/cost.rs new file mode 100644 index 0000000000..ce03d55415 --- /dev/null +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/cost.rs @@ -0,0 +1,70 @@ +use seedance2pro_client::requests::generate_video::generate_video::{KinoviAspectRatio, KinoviBatchCount, KinoviGenerateVideoRequest, KinoviModelType, KinoviOutputResolution}; +use crate::generate::generate_video::video_generation_cost_estimate::VideoGenerationCostEstimate; +use crate::generate::generate_video_v2::providers::kinovi::seedance_2p0::draft::KinoviSeedance2p0DraftState; +use crate::generate::generate_video_v2::providers::kinovi::seedance_2p0::request::KinoviSeedance2p0RequestState; + +pub struct KinoviSeedance2p0CostState { + pub resolution: KinoviOutputResolution, + pub duration_seconds: u8, + pub batch_count: KinoviBatchCount, + pub has_video_reference: bool, +} + +impl KinoviSeedance2p0CostState { + pub fn from_request(request: &KinoviSeedance2p0RequestState) -> Self { + Self { + resolution: request.request.output_resolution.unwrap_or(KinoviOutputResolution::SevenTwentyP), + duration_seconds: request.request.duration_seconds, + batch_count: request.request.batch_count, + has_video_reference: request.request.reference_video_urls.is_some(), + } + } + + pub fn from_draft(draft: &KinoviSeedance2p0DraftState) -> Self { + Self { + resolution: draft.resolution.unwrap_or(KinoviOutputResolution::SevenTwentyP), + duration_seconds: draft.duration_seconds, + batch_count: draft.batch_count, + has_video_reference: draft.remaining_request + .as_ref() + .map(|rem| &rem.reference_videos) + .is_some(), + } + } + + pub fn estimate_cost(&self) -> VideoGenerationCostEstimate { + let request = KinoviGenerateVideoRequest { + // Pricing factors + model_type: KinoviModelType::Seedance2Pro, + output_resolution: Some(self.resolution), + duration_seconds: self.duration_seconds, + batch_count: self.batch_count, + reference_video_urls: if self.has_video_reference { + Some(vec!["https://example.com".to_string()]) + } else { + None + }, + // No impact on price + prompt: "".to_string(), + aspect_ratio: KinoviAspectRatio::Portrait9x16, + start_frame_url: None, + end_frame_url: None, + reference_image_urls: None, + reference_audio_urls: None, + character_ids: None, + use_face_blur_hack: None, + }; + + let cost_in_credits = request.estimate_credits(); + let cost_in_usd_cents = request.estimate_cost_in_usd_cents(); + + VideoGenerationCostEstimate { + cost_in_credits: Some(cost_in_credits as u64), + cost_in_usd_cents: Some(cost_in_usd_cents), + is_free: false, + is_unlimited: false, + is_rate_limited: false, + has_watermark: false, + } + } +} diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/draft.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/draft.rs index 74330ee238..b8ee888724 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/draft.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/draft.rs @@ -1,9 +1,5 @@ -use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::generate::generate_video::generate_video_request_builder::GenerateVideoRequestBuilder; -use crate::generate::generate_video::video_generation_cost_estimate::VideoGenerationCostEstimate; -use crate::generate::generate_video_v2::providers::kinovi::seedance_2p0::type_conversions::{map_common_resolution_to_kinovi, plan_aspect_ratio, plan_batch_count, plan_duration}; -use crate::generate::generate_video_v2::video_generation_draft::VideoGenerationDraftRequest; -use seedance2pro_client::requests::generate_video::generate_video::{KinoviAspectRatio, KinoviBatchCount, KinoviGenerateVideoRequest, KinoviModelType, KinoviOutputResolution}; +use seedance2pro_client::requests::generate_video::generate_video::{KinoviAspectRatio, KinoviBatchCount, KinoviOutputResolution}; #[derive(Debug, Clone)] pub struct KinoviSeedance2p0DraftState { @@ -34,36 +30,3 @@ pub struct KinoviSeedance2p0DraftState { // pub reference_audio: Option, // pub reference_character_tokens: Option, } - -impl KinoviSeedance2p0DraftState { - - pub fn estimate_cost(&self) -> VideoGenerationCostEstimate { - let request = KinoviGenerateVideoRequest { - model_type: KinoviModelType::Seedance2Pro, - prompt: self.prompt.clone(), - aspect_ratio: self.aspect_ratio, - output_resolution: self.resolution, - duration_seconds: self.duration_seconds, - batch_count: self.batch_count, - start_frame_url: None, // TODO - end_frame_url: None, // TODO - reference_image_urls: None, // TODO - reference_video_urls: None, // TODO - reference_audio_urls: None, // TODO - character_ids: None, // TODO - use_face_blur_hack: None, - }; - - let cost_in_credits = request.estimate_credits(); - let cost_in_usd_cents = request.estimate_cost_in_usd_cents(); - - VideoGenerationCostEstimate { - cost_in_credits: Some(cost_in_credits as u64), - cost_in_usd_cents: Some(cost_in_usd_cents), - is_free: false, - is_unlimited: false, - is_rate_limited: false, - has_watermark: false, - } - } -} diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/mod.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/mod.rs index 38bd618fd4..fd9102d428 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/mod.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/mod.rs @@ -1,4 +1,5 @@ pub mod build; pub (super) mod type_conversions; pub mod draft; -pub mod request; \ No newline at end of file +pub mod request; +pub mod cost; \ No newline at end of file diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/video_generation_draft.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/video_generation_draft.rs index cc1822e326..951e6d6992 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/video_generation_draft.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/video_generation_draft.rs @@ -1,6 +1,7 @@ use crate::client::router_client::RouterClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::generate::generate_video::video_generation_cost_estimate::VideoGenerationCostEstimate; +use crate::generate::generate_video_v2::providers::kinovi::seedance_2p0::cost::KinoviSeedance2p0CostState; use crate::generate::generate_video_v2::providers::kinovi::seedance_2p0::draft::KinoviSeedance2p0DraftState; use crate::generate::generate_video_v2::providers::kinovi::seedance_2p0::request::KinoviSeedance2p0RequestState; use crate::generate::generate_video_v2::video_generation_request::VideoGenerationRequest; @@ -15,7 +16,7 @@ impl VideoGenerationDraftRequest { /// Return a cost estimate to fulfill the request. pub fn estimate_cost(&self) -> Result { match self { - VideoGenerationDraftRequest::KinoviSeedance2p0(draft) => Ok(draft.estimate_cost()), + VideoGenerationDraftRequest::KinoviSeedance2p0(draft) => Ok(KinoviSeedance2p0CostState::from_draft(draft).estimate_cost()), } } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/video_generation_request.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/video_generation_request.rs index 4ed96a1baf..bec7bdc965 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/video_generation_request.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/video_generation_request.rs @@ -2,6 +2,7 @@ use crate::client::router_client::RouterClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::generate::generate_video::generate_video_response::GenerateVideoResponse; use crate::generate::generate_video::video_generation_cost_estimate::VideoGenerationCostEstimate; +use crate::generate::generate_video_v2::providers::kinovi::seedance_2p0::cost::KinoviSeedance2p0CostState; use crate::generate::generate_video_v2::providers::kinovi::seedance_2p0::request::KinoviSeedance2p0RequestState; #[derive(Clone, Debug)] @@ -10,10 +11,14 @@ pub enum VideoGenerationRequest { } impl VideoGenerationRequest { + + /// Return a cost estimate to fulfill the request. pub fn estimate_cost(&self) -> Result { - Ok(()) + match self { + VideoGenerationRequest::KinoviSeedance2p0(request) => Ok(KinoviSeedance2p0CostState::from_request(request).estimate_cost()), + } } - + /// Send the video generation request /// If successful, returns the job IDs. pub async fn send_request(&self, client: &RouterClient) -> Result {