mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-24 10:39:28 -04:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f69b935678 |
+5
@@ -11,6 +11,7 @@ use artcraft_api_defs::omni_gen::cost_and_generate_requests::omni_gen_video_cost
|
||||
use artcraft_router::api::provider::Provider;
|
||||
use enums::common::generation::common_generation_mode::CommonGenerationMode;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use tokens::tokens::wallet_ledger_entries::WalletLedgerEntryToken;
|
||||
|
||||
use crate::http_server::common_responses::advanced_common_web_error::AdvancedCommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
@@ -41,6 +42,8 @@ pub async fn execute_generation(
|
||||
server_state: &ServerState,
|
||||
media_file_hydration_map: Option<&HashMap<MediaFileToken, Url>>,
|
||||
kinovi_character_ids: Option<Vec<String>>,
|
||||
maybe_wallet_ledger_entry_token: Option<&WalletLedgerEntryToken>,
|
||||
mysql_connection: &mut sqlx::pool::PoolConnection<sqlx::MySql>,
|
||||
) -> Result<GenerationResult, AdvancedCommonWebError> {
|
||||
match distilled.execution_provider {
|
||||
Provider::Seedance2Pro => {
|
||||
@@ -50,6 +53,8 @@ pub async fn execute_generation(
|
||||
server_state,
|
||||
media_file_hydration_map,
|
||||
kinovi_character_ids,
|
||||
maybe_wallet_ledger_entry_token,
|
||||
mysql_connection,
|
||||
).await
|
||||
}
|
||||
_ => {
|
||||
|
||||
+30
-1
@@ -5,7 +5,7 @@
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use log::{info, warn};
|
||||
use log::{error, info, warn};
|
||||
use url::Url;
|
||||
|
||||
use artcraft_api_defs::omni_gen::cost_and_generate_requests::omni_gen_video_cost_and_generate_request::OmniGenVideoCostAndGenerateRequest;
|
||||
@@ -20,11 +20,13 @@ use seedance2pro_client::requests::prepare_file_upload::prepare_file_upload::{
|
||||
};
|
||||
use seedance2pro_client::requests::upload_file::upload_file::{upload_file, UploadFileArgs};
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use tokens::tokens::wallet_ledger_entries::WalletLedgerEntryToken;
|
||||
use url_utils::extension::extract_extension_from_url::{
|
||||
extract_extension_from_url, ExtractExtensions,
|
||||
};
|
||||
|
||||
use crate::http_server::common_responses::advanced_common_web_error::AdvancedCommonWebError;
|
||||
use crate::http_server::endpoint_helpers::refund_wallet_after_api_failure::refund_wallet_after_api_failure;
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::util::http_download_url_to_bytes::http_download_url_to_bytes;
|
||||
|
||||
@@ -37,6 +39,33 @@ pub(super) async fn execute_generation_kinovi(
|
||||
server_state: &ServerState,
|
||||
media_file_hydration_map: Option<&HashMap<MediaFileToken, Url>>,
|
||||
kinovi_character_ids: Option<Vec<String>>,
|
||||
maybe_wallet_ledger_entry_token: Option<&WalletLedgerEntryToken>,
|
||||
mysql_connection: &mut sqlx::pool::PoolConnection<sqlx::MySql>,
|
||||
) -> Result<GenerationResult, AdvancedCommonWebError> {
|
||||
let result = execute_generation_kinovi_inner(
|
||||
request,
|
||||
server_state,
|
||||
media_file_hydration_map,
|
||||
kinovi_character_ids,
|
||||
).await;
|
||||
|
||||
if let Err(ref err) = result {
|
||||
if let Some(ledger_entry_token) = maybe_wallet_ledger_entry_token {
|
||||
warn!("Kinovi generation failed, issuing refund for ledger entry {}: {:?}", ledger_entry_token.as_str(), err);
|
||||
if let Err(refund_err) = refund_wallet_after_api_failure(ledger_entry_token, mysql_connection).await {
|
||||
error!("Failed to refund wallet after Kinovi failure: {:?}", refund_err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
async fn execute_generation_kinovi_inner(
|
||||
request: &OmniGenVideoCostAndGenerateRequest,
|
||||
server_state: &ServerState,
|
||||
media_file_hydration_map: Option<&HashMap<MediaFileToken, Url>>,
|
||||
kinovi_character_ids: Option<Vec<String>>,
|
||||
) -> Result<GenerationResult, AdvancedCommonWebError> {
|
||||
let session = Seedance2ProSession::from_cookies_string(
|
||||
server_state.seedance2pro.cookies.clone()
|
||||
|
||||
+8
-4
@@ -186,14 +186,16 @@ pub async fn omni_gen_video_generate_handler(
|
||||
|
||||
let apriori_job_token = InferenceJobToken::generate();
|
||||
|
||||
if cost > 0 {
|
||||
attempt_wallet_deduction_else_common_web_error(
|
||||
let maybe_deduction_result = if cost > 0 {
|
||||
Some(attempt_wallet_deduction_else_common_web_error(
|
||||
user_token,
|
||||
Some(apriori_job_token.as_str()),
|
||||
cost,
|
||||
&mut mysql_connection,
|
||||
).await?;
|
||||
}
|
||||
).await?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// ==================== EXECUTE GENERATION ==================== //
|
||||
|
||||
@@ -203,6 +205,8 @@ pub async fn omni_gen_video_generate_handler(
|
||||
&server_state,
|
||||
media_file_hydration_map.as_ref(),
|
||||
kinovi_character_ids,
|
||||
maybe_deduction_result.as_ref().map(|d| &d.ledger_entry_token),
|
||||
&mut mysql_connection,
|
||||
).await?;
|
||||
|
||||
// ==================== DB TRANSACTION ==================== //
|
||||
|
||||
+29
-30
@@ -244,11 +244,11 @@ mod tests {
|
||||
fn text_only_has_no_media_urls() {
|
||||
let d = distill_text(&text_only_request(Some(5), None));
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
assert!(plan.start_frame_url.is_none());
|
||||
assert!(plan.end_frame_url.is_none());
|
||||
assert!(plan.reference_image_urls.is_none());
|
||||
assert!(plan.reference_video_urls.is_none());
|
||||
assert!(plan.reference_audio_urls.is_none());
|
||||
assert!(plan.request.start_frame_url.is_none());
|
||||
assert!(plan.request.end_frame_url.is_none());
|
||||
assert!(plan.request.reference_image_urls.is_none());
|
||||
assert!(plan.request.reference_video_urls.is_none());
|
||||
assert!(plan.request.reference_audio_urls.is_none());
|
||||
} else {
|
||||
panic!("wrong plan variant");
|
||||
}
|
||||
@@ -258,7 +258,7 @@ mod tests {
|
||||
fn text_only_prompt_is_passed_through() {
|
||||
let d = distill_text(&text_only_request(Some(5), None));
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
assert_eq!(plan.prompt, Some("a cat dancing".to_string()));
|
||||
assert_eq!(plan.request.prompt, "a cat dancing");
|
||||
} else {
|
||||
panic!("wrong plan variant");
|
||||
}
|
||||
@@ -276,7 +276,7 @@ mod tests {
|
||||
let d = distill_with_map(&req, &map);
|
||||
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
let url = plan.start_frame_url.as_ref().expect("start_frame_url should be set");
|
||||
let url = plan.request.start_frame_url.as_ref().expect("start_frame_url should be set");
|
||||
assert!(url.starts_with("https://"), "expected URL, got: {}", url);
|
||||
assert!(!url.contains("m_"), "URL should not look like a media token");
|
||||
} else {
|
||||
@@ -296,7 +296,7 @@ mod tests {
|
||||
let d = distill_with_map(&req, &map);
|
||||
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
let url = plan.end_frame_url.as_ref().expect("end_frame_url should be set");
|
||||
let url = plan.request.end_frame_url.as_ref().expect("end_frame_url should be set");
|
||||
assert!(url.starts_with("https://"), "expected URL, got: {}", url);
|
||||
} else {
|
||||
panic!("wrong plan variant");
|
||||
@@ -316,8 +316,8 @@ mod tests {
|
||||
let d = distill_with_map(&req, &map);
|
||||
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
assert!(plan.start_frame_url.is_some());
|
||||
assert!(plan.end_frame_url.is_some());
|
||||
assert!(plan.request.start_frame_url.is_some());
|
||||
assert!(plan.request.end_frame_url.is_some());
|
||||
} else {
|
||||
panic!("wrong plan variant");
|
||||
}
|
||||
@@ -338,7 +338,7 @@ mod tests {
|
||||
let d = distill_with_map(&req, &map);
|
||||
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
let urls = plan.reference_image_urls.as_ref().expect("reference_image_urls should be set");
|
||||
let urls = plan.request.reference_image_urls.as_ref().expect("reference_image_urls should be set");
|
||||
assert_eq!(urls.len(), 2);
|
||||
for url in urls {
|
||||
assert!(url.starts_with("https://"), "expected URL, got: {}", url);
|
||||
@@ -362,7 +362,7 @@ mod tests {
|
||||
let d = distill_with_map(&req, &map);
|
||||
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
let urls = plan.reference_video_urls.as_ref().expect("reference_video_urls should be set");
|
||||
let urls = plan.request.reference_video_urls.as_ref().expect("reference_video_urls should be set");
|
||||
assert_eq!(urls.len(), 1);
|
||||
assert!(urls[0].starts_with("https://"));
|
||||
} else {
|
||||
@@ -383,7 +383,7 @@ mod tests {
|
||||
let d = distill_with_map(&req, &map);
|
||||
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
let urls = plan.reference_audio_urls.as_ref().expect("reference_audio_urls should be set");
|
||||
let urls = plan.request.reference_audio_urls.as_ref().expect("reference_audio_urls should be set");
|
||||
assert_eq!(urls.len(), 1);
|
||||
assert!(urls[0].starts_with("https://"));
|
||||
} else {
|
||||
@@ -410,12 +410,12 @@ mod tests {
|
||||
let d = distill_with_map(&req, &map);
|
||||
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
assert!(plan.start_frame_url.is_some());
|
||||
assert!(plan.end_frame_url.is_some());
|
||||
assert_eq!(plan.reference_image_urls.as_ref().map(|v| v.len()), Some(1));
|
||||
assert_eq!(plan.reference_video_urls.as_ref().map(|v| v.len()), Some(1));
|
||||
assert_eq!(plan.reference_audio_urls.as_ref().map(|v| v.len()), Some(1));
|
||||
assert!(plan.prompt.as_deref() == Some("full test"));
|
||||
assert!(plan.request.start_frame_url.is_some());
|
||||
assert!(plan.request.end_frame_url.is_some());
|
||||
assert_eq!(plan.request.reference_image_urls.as_ref().map(|v| v.len()), Some(1));
|
||||
assert_eq!(plan.request.reference_video_urls.as_ref().map(|v| v.len()), Some(1));
|
||||
assert_eq!(plan.request.reference_audio_urls.as_ref().map(|v| v.len()), Some(1));
|
||||
assert_eq!(plan.request.prompt, "full test");
|
||||
} else {
|
||||
panic!("wrong plan variant");
|
||||
}
|
||||
@@ -426,7 +426,7 @@ mod tests {
|
||||
// Duration below 4 should clamp to 4.
|
||||
let d = distill_text(&text_only_request(Some(1), None));
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
assert!(plan.duration_seconds >= 4, "expected >= 4, got {}", plan.duration_seconds);
|
||||
assert!(plan.request.duration_seconds >= 4, "expected >= 4, got {}", plan.request.duration_seconds);
|
||||
} else {
|
||||
panic!("wrong plan variant");
|
||||
}
|
||||
@@ -434,7 +434,7 @@ mod tests {
|
||||
// Duration above 15 should clamp to 15.
|
||||
let d = distill_text(&text_only_request(Some(99), None));
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
assert!(plan.duration_seconds <= 15, "expected <= 15, got {}", plan.duration_seconds);
|
||||
assert!(plan.request.duration_seconds <= 15, "expected <= 15, got {}", plan.request.duration_seconds);
|
||||
} else {
|
||||
panic!("wrong plan variant");
|
||||
}
|
||||
@@ -449,8 +449,7 @@ mod tests {
|
||||
let d = distill_text(&req);
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
// Prompt should be None or empty string.
|
||||
let prompt = plan.prompt.as_deref().unwrap_or("");
|
||||
assert!(prompt.is_empty() || plan.prompt.is_none());
|
||||
assert!(plan.request.prompt.is_empty());
|
||||
} else {
|
||||
panic!("wrong plan variant");
|
||||
}
|
||||
@@ -467,7 +466,7 @@ mod tests {
|
||||
);
|
||||
let d = distill_text(&req);
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
assert!(matches!(plan.aspect_ratio, KinoviAspectRatio::Landscape16x9));
|
||||
assert!(matches!(plan.request.aspect_ratio, KinoviAspectRatio::Landscape16x9));
|
||||
} else { panic!("wrong plan variant"); }
|
||||
}
|
||||
|
||||
@@ -480,7 +479,7 @@ mod tests {
|
||||
);
|
||||
let d = distill_text(&req);
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
assert!(matches!(plan.aspect_ratio, KinoviAspectRatio::Portrait9x16));
|
||||
assert!(matches!(plan.request.aspect_ratio, KinoviAspectRatio::Portrait9x16));
|
||||
} else { panic!("wrong plan variant"); }
|
||||
}
|
||||
|
||||
@@ -493,7 +492,7 @@ mod tests {
|
||||
);
|
||||
let d = distill_text(&req);
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
assert!(matches!(plan.aspect_ratio, KinoviAspectRatio::Square1x1));
|
||||
assert!(matches!(plan.request.aspect_ratio, KinoviAspectRatio::Square1x1));
|
||||
} else { panic!("wrong plan variant"); }
|
||||
}
|
||||
|
||||
@@ -506,7 +505,7 @@ mod tests {
|
||||
);
|
||||
let d = distill_text(&req);
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
assert!(matches!(plan.aspect_ratio, KinoviAspectRatio::Standard4x3));
|
||||
assert!(matches!(plan.request.aspect_ratio, KinoviAspectRatio::Standard4x3));
|
||||
} else { panic!("wrong plan variant"); }
|
||||
}
|
||||
|
||||
@@ -519,7 +518,7 @@ mod tests {
|
||||
);
|
||||
let d = distill_text(&req);
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
assert!(matches!(plan.aspect_ratio, KinoviAspectRatio::Portrait3x4));
|
||||
assert!(matches!(plan.request.aspect_ratio, KinoviAspectRatio::Portrait3x4));
|
||||
} else { panic!("wrong plan variant"); }
|
||||
}
|
||||
|
||||
@@ -532,7 +531,7 @@ mod tests {
|
||||
);
|
||||
let d = distill_text(&req);
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
assert!(matches!(plan.aspect_ratio, KinoviAspectRatio::Landscape16x9));
|
||||
assert!(matches!(plan.request.aspect_ratio, KinoviAspectRatio::Landscape16x9));
|
||||
} else { panic!("wrong plan variant"); }
|
||||
}
|
||||
|
||||
@@ -545,7 +544,7 @@ mod tests {
|
||||
);
|
||||
let d = distill_text(&req);
|
||||
if let VideoGenerationPlan::Seedance2proSeedance2p0(plan) = d.plan() {
|
||||
assert!(matches!(plan.aspect_ratio, KinoviAspectRatio::Landscape16x9));
|
||||
assert!(matches!(plan.request.aspect_ratio, KinoviAspectRatio::Landscape16x9));
|
||||
} else { panic!("wrong plan variant"); }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user