mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-08 15:14:16 -05:00
Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8dd5b10d3c | ||
|
|
7acb96a888 | ||
|
|
85a349f6cb | ||
|
|
cdb371cb6c | ||
|
|
5cf299d325 | ||
|
|
b72a685c5c |
+27
-11
@@ -26,8 +26,8 @@ use crate::queries::generic_inference::api_providers::common::insert_generic_inf
|
||||
pub struct InsertGenericInferenceForSeedance2ProWithAprioriJobTokenArgs<'e, 'c, E>
|
||||
where E: 'e + Executor<'c, Database = MySql>
|
||||
{
|
||||
/// Which kinovi queue to use: standard or alternate
|
||||
pub use_alternate_kinovi: bool,
|
||||
/// Which kinovi queue to use
|
||||
pub kinovi_version: KinoviVersion,
|
||||
|
||||
pub uuid_idempotency_token: &'e str,
|
||||
|
||||
@@ -57,23 +57,39 @@ pub struct InsertGenericInferenceForSeedance2ProWithAprioriJobTokenArgs<'e, 'c,
|
||||
pub phantom: PhantomData<&'c E>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum KinoviVersion {
|
||||
Volcengine,
|
||||
BytePlus,
|
||||
BytePlusUltra,
|
||||
}
|
||||
|
||||
|
||||
pub async fn insert_generic_inference_job_for_seedance2pro_queue_with_apriori_job_token<'e, 'c : 'e, E>(
|
||||
args: InsertGenericInferenceForSeedance2ProWithAprioriJobTokenArgs<'e, 'c, E>
|
||||
) -> Result<InferenceJobToken, DatabaseQueryError>
|
||||
where E: 'e + Executor<'c, Database = MySql>
|
||||
{
|
||||
let (job_type, external_third_party, product_category) = if args.use_alternate_kinovi {
|
||||
(
|
||||
InferenceJobType::Seedance2ProAltQueue,
|
||||
InferenceJobExternalThirdParty::Seedance2ProAlt,
|
||||
InferenceJobProductCategory::Seedance2ProVideoAlt,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
let (
|
||||
job_type,
|
||||
external_third_party,
|
||||
product_category
|
||||
) = match args.kinovi_version {
|
||||
KinoviVersion::Volcengine => (
|
||||
InferenceJobType::Seedance2ProQueue,
|
||||
InferenceJobExternalThirdParty::Seedance2Pro,
|
||||
InferenceJobProductCategory::Seedance2ProVideo,
|
||||
)
|
||||
),
|
||||
KinoviVersion::BytePlus => (
|
||||
InferenceJobType::Seedance2ProAltQueue,
|
||||
InferenceJobExternalThirdParty::Seedance2ProAlt,
|
||||
InferenceJobProductCategory::Seedance2ProVideoAlt,
|
||||
),
|
||||
KinoviVersion::BytePlusUltra => (
|
||||
InferenceJobType::Seedance2ProBytePlusUltraQueue,
|
||||
InferenceJobExternalThirdParty::Seedance2ProBytePlusUltra,
|
||||
InferenceJobProductCategory::Seedance2ProVideoBytePlusUltra,
|
||||
),
|
||||
};
|
||||
|
||||
let record_id = insert_generic_inference_job_for_provider(InsertGenericInferenceJobForProviderArgs {
|
||||
|
||||
+11
-1
@@ -37,6 +37,10 @@ pub enum InferenceJobExternalThirdParty {
|
||||
#[serde(rename = "seedance2pro_alt")]
|
||||
Seedance2ProAlt,
|
||||
|
||||
/// Seedance 2 Pro BytePlus Ultra jobs
|
||||
#[serde(rename = "seedance2pro_bpu")]
|
||||
Seedance2ProBytePlusUltra,
|
||||
|
||||
/// World Labs jobs
|
||||
#[serde(rename = "worldlabs")]
|
||||
Worldlabs,
|
||||
@@ -56,6 +60,7 @@ impl InferenceJobExternalThirdParty {
|
||||
Self::GrokApi => "grok_api",
|
||||
Self::Seedance2Pro => "seedance2pro",
|
||||
Self::Seedance2ProAlt => "seedance2pro_alt",
|
||||
Self::Seedance2ProBytePlusUltra => "seedance2pro_bpu",
|
||||
Self::Worldlabs => "worldlabs",
|
||||
}
|
||||
}
|
||||
@@ -68,6 +73,7 @@ impl InferenceJobExternalThirdParty {
|
||||
"grok_api" => Ok(Self::GrokApi),
|
||||
"seedance2pro" => Ok(Self::Seedance2Pro),
|
||||
"seedance2pro_alt" => Ok(Self::Seedance2ProAlt),
|
||||
"seedance2pro_bpu" => Ok(Self::Seedance2ProBytePlusUltra),
|
||||
"worldlabs" => Ok(Self::Worldlabs),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
@@ -83,6 +89,7 @@ impl InferenceJobExternalThirdParty {
|
||||
Self::GrokApi,
|
||||
Self::Seedance2Pro,
|
||||
Self::Seedance2ProAlt,
|
||||
Self::Seedance2ProBytePlusUltra,
|
||||
Self::Worldlabs,
|
||||
])
|
||||
}
|
||||
@@ -104,6 +111,7 @@ mod tests {
|
||||
assert_serialization(InferenceJobExternalThirdParty::GrokApi, "grok_api");
|
||||
assert_serialization(InferenceJobExternalThirdParty::Seedance2Pro, "seedance2pro");
|
||||
assert_serialization(InferenceJobExternalThirdParty::Seedance2ProAlt, "seedance2pro_alt");
|
||||
assert_serialization(InferenceJobExternalThirdParty::Seedance2ProBytePlusUltra, "seedance2pro_bpu");
|
||||
assert_serialization(InferenceJobExternalThirdParty::Worldlabs, "worldlabs");
|
||||
}
|
||||
|
||||
@@ -115,6 +123,7 @@ mod tests {
|
||||
assert_eq!(InferenceJobExternalThirdParty::GrokApi.to_str(), "grok_api");
|
||||
assert_eq!(InferenceJobExternalThirdParty::Seedance2Pro.to_str(), "seedance2pro");
|
||||
assert_eq!(InferenceJobExternalThirdParty::Seedance2ProAlt.to_str(), "seedance2pro_alt");
|
||||
assert_eq!(InferenceJobExternalThirdParty::Seedance2ProBytePlusUltra.to_str(), "seedance2pro_bpu");
|
||||
assert_eq!(InferenceJobExternalThirdParty::Worldlabs.to_str(), "worldlabs");
|
||||
}
|
||||
|
||||
@@ -126,13 +135,14 @@ mod tests {
|
||||
assert_eq!(InferenceJobExternalThirdParty::from_str("grok_api").unwrap(), InferenceJobExternalThirdParty::GrokApi);
|
||||
assert_eq!(InferenceJobExternalThirdParty::from_str("seedance2pro").unwrap(), InferenceJobExternalThirdParty::Seedance2Pro);
|
||||
assert_eq!(InferenceJobExternalThirdParty::from_str("seedance2pro_alt").unwrap(), InferenceJobExternalThirdParty::Seedance2ProAlt);
|
||||
assert_eq!(InferenceJobExternalThirdParty::from_str("seedance2pro_bpu").unwrap(), InferenceJobExternalThirdParty::Seedance2ProBytePlusUltra);
|
||||
assert_eq!(InferenceJobExternalThirdParty::from_str("worldlabs").unwrap(), InferenceJobExternalThirdParty::Worldlabs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_variants() {
|
||||
// Static check
|
||||
const EXPECTED_COUNT : usize = 7;
|
||||
const EXPECTED_COUNT : usize = 8;
|
||||
|
||||
assert_eq!(InferenceJobExternalThirdParty::all_variants().len(), EXPECTED_COUNT);
|
||||
assert_eq!(InferenceJobExternalThirdParty::iter().len(), EXPECTED_COUNT);
|
||||
|
||||
+12
-1
@@ -58,6 +58,11 @@ pub enum InferenceJobProductCategory {
|
||||
#[serde(rename = "seedance2pro_video_alt")]
|
||||
Seedance2ProVideoAlt,
|
||||
|
||||
// =============== SEEDANCE 2 PRO BYTEPLUS ULTRA ===============
|
||||
|
||||
#[serde(rename = "seedance2pro_video_bpu")]
|
||||
Seedance2ProVideoBytePlusUltra,
|
||||
|
||||
// =============== WORLD LABS ===============
|
||||
|
||||
/// World Labs: Gaussian Splat Generation
|
||||
@@ -165,6 +170,7 @@ impl InferenceJobProductCategory {
|
||||
Self::Seedance2ProVideo => "seedance2pro_video",
|
||||
Self::Seedance2ProCharacter => "seedance2pro_character",
|
||||
Self::Seedance2ProVideoAlt => "seedance2pro_video_alt",
|
||||
Self::Seedance2ProVideoBytePlusUltra => "seedance2pro_video_bpu",
|
||||
Self::WorldlabsSplat => "worldlabs_splat",
|
||||
Self::TtsGptSoVits => "tts_gpt_so_vits",
|
||||
Self::TtsStyleTts2 => "tts_style_tts2",
|
||||
@@ -204,6 +210,7 @@ impl InferenceJobProductCategory {
|
||||
"seedance2pro_video" => Ok(Self::Seedance2ProVideo),
|
||||
"seedance2pro_character" => Ok(Self::Seedance2ProCharacter),
|
||||
"seedance2pro_video_alt" => Ok(Self::Seedance2ProVideoAlt),
|
||||
"seedance2pro_video_bpu" => Ok(Self::Seedance2ProVideoBytePlusUltra),
|
||||
"worldlabs_splat" => Ok(Self::WorldlabsSplat),
|
||||
"tts_gpt_so_vits" => Ok(Self::TtsGptSoVits),
|
||||
"tts_style_tts2" => Ok(Self::TtsStyleTts2),
|
||||
@@ -246,6 +253,7 @@ impl InferenceJobProductCategory {
|
||||
Self::Seedance2ProVideo,
|
||||
Self::Seedance2ProCharacter,
|
||||
Self::Seedance2ProVideoAlt,
|
||||
Self::Seedance2ProVideoBytePlusUltra,
|
||||
Self::WorldlabsSplat,
|
||||
Self::TtsGptSoVits,
|
||||
Self::TtsStyleTts2,
|
||||
@@ -294,6 +302,7 @@ mod tests {
|
||||
assert_serialization(InferenceJobProductCategory::Seedance2ProVideo, "seedance2pro_video");
|
||||
assert_serialization(InferenceJobProductCategory::Seedance2ProCharacter, "seedance2pro_character");
|
||||
assert_serialization(InferenceJobProductCategory::Seedance2ProVideoAlt, "seedance2pro_video_alt");
|
||||
assert_serialization(InferenceJobProductCategory::Seedance2ProVideoBytePlusUltra, "seedance2pro_video_bpu");
|
||||
assert_serialization(InferenceJobProductCategory::WorldlabsSplat, "worldlabs_splat");
|
||||
assert_serialization(InferenceJobProductCategory::TtsGptSoVits, "tts_gpt_so_vits");
|
||||
assert_serialization(InferenceJobProductCategory::TtsStyleTts2, "tts_style_tts2");
|
||||
@@ -332,6 +341,7 @@ mod tests {
|
||||
assert_eq!(InferenceJobProductCategory::Seedance2ProVideo.to_str(), "seedance2pro_video");
|
||||
assert_eq!(InferenceJobProductCategory::Seedance2ProCharacter.to_str(), "seedance2pro_character");
|
||||
assert_eq!(InferenceJobProductCategory::Seedance2ProVideoAlt.to_str(), "seedance2pro_video_alt");
|
||||
assert_eq!(InferenceJobProductCategory::Seedance2ProVideoBytePlusUltra.to_str(), "seedance2pro_video_bpu");
|
||||
assert_eq!(InferenceJobProductCategory::WorldlabsSplat.to_str(), "worldlabs_splat");
|
||||
assert_eq!(InferenceJobProductCategory::TtsGptSoVits.to_str(), "tts_gpt_so_vits");
|
||||
assert_eq!(InferenceJobProductCategory::TtsStyleTts2.to_str(), "tts_style_tts2");
|
||||
@@ -369,6 +379,7 @@ mod tests {
|
||||
assert_eq!(InferenceJobProductCategory::from_str("seedance2pro_video").unwrap(), InferenceJobProductCategory::Seedance2ProVideo);
|
||||
assert_eq!(InferenceJobProductCategory::from_str("seedance2pro_character").unwrap(), InferenceJobProductCategory::Seedance2ProCharacter);
|
||||
assert_eq!(InferenceJobProductCategory::from_str("seedance2pro_video_alt").unwrap(), InferenceJobProductCategory::Seedance2ProVideoAlt);
|
||||
assert_eq!(InferenceJobProductCategory::from_str("seedance2pro_video_bpu").unwrap(), InferenceJobProductCategory::Seedance2ProVideoBytePlusUltra);
|
||||
assert_eq!(InferenceJobProductCategory::from_str("worldlabs_splat").unwrap(), InferenceJobProductCategory::WorldlabsSplat);
|
||||
assert_eq!(InferenceJobProductCategory::from_str("tts_gpt_so_vits").unwrap(), InferenceJobProductCategory::TtsGptSoVits);
|
||||
assert_eq!(InferenceJobProductCategory::from_str("tts_style_tts2").unwrap(), InferenceJobProductCategory::TtsStyleTts2);
|
||||
@@ -396,7 +407,7 @@ mod tests {
|
||||
#[test]
|
||||
fn all_variants() {
|
||||
// Static check
|
||||
const EXPECTED_COUNT : usize = 34;
|
||||
const EXPECTED_COUNT : usize = 35;
|
||||
|
||||
assert_eq!(InferenceJobProductCategory::all_variants().len(), EXPECTED_COUNT);
|
||||
assert_eq!(InferenceJobProductCategory::iter().len(), EXPECTED_COUNT);
|
||||
|
||||
+11
-1
@@ -39,6 +39,10 @@ pub enum InferenceJobType {
|
||||
#[serde(rename = "seedance2pro_alt_queue")]
|
||||
Seedance2ProAltQueue,
|
||||
|
||||
/// Seedance 2 Pro BytePlus Ultra jobs. We poll for results.
|
||||
#[serde(rename = "seedance2pro_bpu_queue")]
|
||||
Seedance2ProBytePlusUltraQueue,
|
||||
|
||||
/// Beeble jobs. We poll for results.
|
||||
#[serde(rename = "beeble_queue")]
|
||||
BeebleQueue,
|
||||
@@ -143,6 +147,7 @@ impl InferenceJobType {
|
||||
Self::BeebleQueue => "beeble_queue",
|
||||
Self::Seedance2ProQueue => "seedance2pro_queue",
|
||||
Self::Seedance2ProAltQueue => "seedance2pro_alt_queue",
|
||||
Self::Seedance2ProBytePlusUltraQueue => "seedance2pro_bpu_queue",
|
||||
Self::Seedance2ProCharacter => "seedance2pro_character",
|
||||
Self::WorldlabsQueue => "worldlabs_queue",
|
||||
Self::VideoRender => "video_render",
|
||||
@@ -177,6 +182,7 @@ impl InferenceJobType {
|
||||
"seedance2pro_queue" => Ok(Self::Seedance2ProQueue),
|
||||
"seedance2pro_character" => Ok(Self::Seedance2ProCharacter),
|
||||
"seedance2pro_alt_queue" => Ok(Self::Seedance2ProAltQueue),
|
||||
"seedance2pro_bpu_queue" => Ok(Self::Seedance2ProBytePlusUltraQueue),
|
||||
"worldlabs_queue" => Ok(Self::WorldlabsQueue),
|
||||
"video_render" => Ok(Self::VideoRender),
|
||||
"live_portrait" => Ok(Self::LivePortrait),
|
||||
@@ -213,6 +219,7 @@ impl InferenceJobType {
|
||||
Self::Seedance2ProQueue,
|
||||
Self::Seedance2ProCharacter,
|
||||
Self::Seedance2ProAltQueue,
|
||||
Self::Seedance2ProBytePlusUltraQueue,
|
||||
Self::WorldlabsQueue,
|
||||
Self::VideoRender,
|
||||
Self::LivePortrait,
|
||||
@@ -260,6 +267,7 @@ mod tests {
|
||||
assert_serialization(InferenceJobType::Seedance2ProQueue, "seedance2pro_queue");
|
||||
assert_serialization(InferenceJobType::Seedance2ProCharacter, "seedance2pro_character");
|
||||
assert_serialization(InferenceJobType::Seedance2ProAltQueue, "seedance2pro_alt_queue");
|
||||
assert_serialization(InferenceJobType::Seedance2ProBytePlusUltraQueue, "seedance2pro_bpu_queue");
|
||||
assert_serialization(InferenceJobType::WorldlabsQueue, "worldlabs_queue");
|
||||
assert_serialization(InferenceJobType::VideoRender, "video_render");
|
||||
assert_serialization(InferenceJobType::LivePortrait, "live_portrait");
|
||||
@@ -292,6 +300,7 @@ mod tests {
|
||||
assert_eq!(InferenceJobType::Seedance2ProQueue.to_str(), "seedance2pro_queue");
|
||||
assert_eq!(InferenceJobType::Seedance2ProCharacter.to_str(), "seedance2pro_character");
|
||||
assert_eq!(InferenceJobType::Seedance2ProAltQueue.to_str(), "seedance2pro_alt_queue");
|
||||
assert_eq!(InferenceJobType::Seedance2ProBytePlusUltraQueue.to_str(), "seedance2pro_bpu_queue");
|
||||
assert_eq!(InferenceJobType::WorldlabsQueue.to_str(), "worldlabs_queue");
|
||||
assert_eq!(InferenceJobType::VideoRender.to_str(), "video_render");
|
||||
assert_eq!(InferenceJobType::LivePortrait.to_str(), "live_portrait");
|
||||
@@ -324,6 +333,7 @@ mod tests {
|
||||
assert_eq!(InferenceJobType::from_str("seedance2pro_queue").unwrap(), InferenceJobType::Seedance2ProQueue);
|
||||
assert_eq!(InferenceJobType::from_str("seedance2pro_character").unwrap(), InferenceJobType::Seedance2ProCharacter);
|
||||
assert_eq!(InferenceJobType::from_str("seedance2pro_alt_queue").unwrap(), InferenceJobType::Seedance2ProAltQueue);
|
||||
assert_eq!(InferenceJobType::from_str("seedance2pro_bpu_queue").unwrap(), InferenceJobType::Seedance2ProBytePlusUltraQueue);
|
||||
assert_eq!(InferenceJobType::from_str("worldlabs_queue").unwrap(), InferenceJobType::WorldlabsQueue);
|
||||
assert_eq!(InferenceJobType::from_str("video_render").unwrap(), InferenceJobType::VideoRender);
|
||||
assert_eq!(InferenceJobType::from_str("live_portrait").unwrap(), InferenceJobType::LivePortrait);
|
||||
@@ -350,7 +360,7 @@ mod tests {
|
||||
#[test]
|
||||
fn all_variants() {
|
||||
// Static check
|
||||
const EXPECTED_COUNT : usize = 28;
|
||||
const EXPECTED_COUNT : usize = 29;
|
||||
|
||||
assert_eq!(InferenceJobType::all_variants().len(), EXPECTED_COUNT);
|
||||
assert_eq!(InferenceJobType::iter().len(), EXPECTED_COUNT);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::kinovi_version::KinoviVersion;
|
||||
use chrono::Duration;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use concurrency::relaxed_atomic_bool::RelaxedAtomicBool;
|
||||
@@ -20,9 +21,8 @@ pub struct JobDependencies {
|
||||
/// Session credentials for polling seedance2-pro.com.
|
||||
pub seedance2pro_session: Seedance2ProSession,
|
||||
|
||||
/// When true, this instance polls for alternate-account jobs
|
||||
/// (Seedance2ProAltQueue / Seedance2ProAlt) instead of the primary ones.
|
||||
pub is_alternate_mode: bool,
|
||||
/// The kinovi account/version we poll
|
||||
pub kinovi_version: KinoviVersion,
|
||||
|
||||
pub server_environment: ServerEnvironment,
|
||||
|
||||
|
||||
+23
-8
@@ -5,14 +5,15 @@ use chrono::Utc;
|
||||
use enums::by_table::generic_inference_jobs::inference_job_external_third_party::InferenceJobExternalThirdParty;
|
||||
use enums::by_table::generic_inference_jobs::inference_job_type::InferenceJobType;
|
||||
use log::{error, info, warn};
|
||||
use mysql_queries::queries::generic_inference::api_providers::seedance2pro::list_pending_seedance2pro_video_jobs::{list_pending_seedance2pro_video_jobs, PendingSeedance2ProJob};
|
||||
use pager::notification::notification_details_builder::NotificationDetailsBuilder;
|
||||
use pager::notification::notification_urgency::NotificationUrgency;
|
||||
use mysql_queries::queries::generic_inference::api_providers::seedance2pro::list_pending_seedance2pro_video_jobs::{list_pending_seedance2pro_video_jobs, PendingSeedance2ProJob};
|
||||
use seedance2pro_client::requests::poll_orders::poll_orders::{poll_orders, OrderStatus, PollOrdersArgs, PollOrdersResponse, TaskStatus};
|
||||
|
||||
use crate::job_dependencies::JobDependencies;
|
||||
use crate::jobs::video_polling_job::alert_on_error::alert_pager_and_return_err;
|
||||
use crate::jobs::video_polling_job::process_orders_batch::process_orders_batch;
|
||||
use crate::job_dependencies::JobDependencies;
|
||||
use crate::kinovi_version::KinoviVersion;
|
||||
|
||||
const POLL_ALERT_THRESHOLD: Duration = Duration::from_mins(6);
|
||||
|
||||
@@ -61,14 +62,28 @@ pub async fn video_polling_main_loop(job_dependencies: JobDependencies) {
|
||||
}
|
||||
|
||||
async fn run_poll_iteration(deps: &JobDependencies) -> anyhow::Result<()> {
|
||||
info!("Querying database jobs for type: {:?}", deps.kinovi_version);
|
||||
|
||||
let (
|
||||
job_type,
|
||||
third_party,
|
||||
) = match deps.kinovi_version {
|
||||
KinoviVersion::Volcengine => (
|
||||
InferenceJobType::Seedance2ProQueue,
|
||||
InferenceJobExternalThirdParty::Seedance2Pro,
|
||||
),
|
||||
KinoviVersion::BytePlus => (
|
||||
InferenceJobType::Seedance2ProAltQueue,
|
||||
InferenceJobExternalThirdParty::Seedance2ProAlt,
|
||||
),
|
||||
KinoviVersion::BytePlusUltra => (
|
||||
InferenceJobType::Seedance2ProBytePlusUltraQueue,
|
||||
InferenceJobExternalThirdParty::Seedance2ProBytePlusUltra,
|
||||
),
|
||||
};
|
||||
|
||||
// 1. Query all (limit 25,000) non-terminal Seedance2Pro jobs from DB.
|
||||
// This is all non-(complete_success, complete_failure) jobs.
|
||||
let (third_party, job_type) = if deps.is_alternate_mode {
|
||||
(InferenceJobExternalThirdParty::Seedance2ProAlt, InferenceJobType::Seedance2ProAltQueue)
|
||||
} else {
|
||||
(InferenceJobExternalThirdParty::Seedance2Pro, InferenceJobType::Seedance2ProQueue)
|
||||
};
|
||||
|
||||
let pending_jobs = match list_pending_seedance2pro_video_jobs(&deps.mysql_pool, third_party, job_type).await {
|
||||
Ok(jobs) => jobs,
|
||||
Err(err) => {
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum KinoviVersion {
|
||||
Volcengine,
|
||||
BytePlus,
|
||||
BytePlusUltra,
|
||||
}
|
||||
|
||||
impl KinoviVersion {
|
||||
pub fn has_characters(&self) -> bool {
|
||||
match self {
|
||||
KinoviVersion::Volcengine => true,
|
||||
KinoviVersion::BytePlus => false,
|
||||
KinoviVersion::BytePlusUltra => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,10 +33,12 @@ use crate::jobs::credits_checking_job::credits_checking_main_loop::credits_check
|
||||
use crate::jobs::video_polling_job::video_polling_main_loop::video_polling_main_loop;
|
||||
use crate::job_dependencies::JobDependencies;
|
||||
use crate::startup::build_pager::build_pager;
|
||||
use crate::startup::kinovi_setup::{get_kinovi_session, get_kinovi_version};
|
||||
|
||||
pub mod http_server;
|
||||
pub mod job_dependencies;
|
||||
pub mod jobs;
|
||||
pub mod kinovi_version;
|
||||
pub mod startup;
|
||||
|
||||
// Bucket config
|
||||
@@ -46,10 +48,6 @@ const ENV_REGION_NAME: &str = "REGION_NAME";
|
||||
const ENV_PUBLIC_BUCKET_NAME: &str = "PUBLIC_BUCKET_NAME";
|
||||
const ENV_S3_ENDPOINT: &str = "S3_COMPATIBLE_ENDPOINT_URL";
|
||||
|
||||
const ENV_SEEDANCE2PRO_ALTERNATE: &str = "SEEDANCE2PRO_ALTERNATE";
|
||||
const ENV_SEEDANCE2PRO_COOKIES: &str = "SEEDANCE2PRO_COOKIES";
|
||||
const ENV_SEEDANCE2PRO_ALT_COOKIES: &str = "SEEDANCE2PRO_ALT_COOKIES";
|
||||
|
||||
const ENV_MAX_JOB_AGE_THRESHOLD_HOURS: &str = "MAX_JOB_AGE_THRESHOLD_HOURS";
|
||||
|
||||
#[tokio::main]
|
||||
@@ -105,21 +103,8 @@ async fn main() -> AnyhowResult<()> {
|
||||
Some(bucket_timeout),
|
||||
)?;
|
||||
|
||||
// Alternate mode: uses a different Kinovi account, different job types, skips character polling.
|
||||
let is_alternate_mode = easyenv::get_env_string_optional(ENV_SEEDANCE2PRO_ALTERNATE)
|
||||
.map(|v| v.trim().to_lowercase())
|
||||
.map(|v| v == "true" || v == "1")
|
||||
.unwrap_or(false);
|
||||
|
||||
if is_alternate_mode {
|
||||
info!("Running in ALTERNATE mode (SEEDANCE2PRO_ALTERNATE=true).");
|
||||
}
|
||||
|
||||
// Seedance2Pro session from cookie string
|
||||
let cookie_env_var = if is_alternate_mode { ENV_SEEDANCE2PRO_ALT_COOKIES } else { ENV_SEEDANCE2PRO_COOKIES };
|
||||
info!("Reading Seedance2Pro cookies from environment variable: {}", cookie_env_var);
|
||||
let seedance2pro_cookies = easyenv::get_env_string_required(cookie_env_var)?;
|
||||
let seedance2pro_session = Seedance2ProSession::from_cookies_string(seedance2pro_cookies);
|
||||
let kinovi_version = get_kinovi_version()?;
|
||||
let kinovi_session = get_kinovi_session(kinovi_version)?;
|
||||
|
||||
// How often to poll for results (default: 15 seconds)
|
||||
let poll_interval_millis: u64 = easyenv::get_env_num(
|
||||
@@ -186,8 +171,8 @@ async fn main() -> AnyhowResult<()> {
|
||||
let job_dependencies = JobDependencies {
|
||||
mysql_pool,
|
||||
public_bucket_client,
|
||||
seedance2pro_session,
|
||||
is_alternate_mode,
|
||||
seedance2pro_session: kinovi_session,
|
||||
kinovi_version,
|
||||
server_environment,
|
||||
job_stats,
|
||||
poll_interval_millis,
|
||||
@@ -241,16 +226,16 @@ async fn main() -> AnyhowResult<()> {
|
||||
credits_checking_main_loop(credits_deps).await;
|
||||
});
|
||||
|
||||
if is_alternate_mode {
|
||||
// Alternate mode: skip character polling entirely.
|
||||
info!("Alternate mode: character polling is disabled.");
|
||||
let _ = tokio::join!(video_handle, credits_handle);
|
||||
} else {
|
||||
if kinovi_version.has_characters() {
|
||||
let character_deps = job_dependencies;
|
||||
let character_handle = tokio::spawn(async move {
|
||||
character_polling_main_loop(character_deps).await;
|
||||
});
|
||||
let _ = tokio::join!(video_handle, character_handle, credits_handle);
|
||||
} else {
|
||||
// skip character polling entirely.
|
||||
info!("Alternate mode: character polling is disabled.");
|
||||
let _ = tokio::join!(video_handle, credits_handle);
|
||||
}
|
||||
|
||||
info!("Shutting down pager worker...");
|
||||
@@ -260,3 +245,4 @@ async fn main() -> AnyhowResult<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
use crate::kinovi_version::KinoviVersion;
|
||||
use anyhow::anyhow;
|
||||
use log::info;
|
||||
use seedance2pro_client::creds::seedance2pro_session::Seedance2ProSession;
|
||||
|
||||
// Configuration switch
|
||||
const ENV_SEEDANCE2PRO_VERSION: &str = "SEEDANCE2PRO_VERSION";
|
||||
|
||||
// Cookies for Volcengine
|
||||
#[deprecated]
|
||||
const ENV_SEEDANCE2PRO_LEGACY_COOKIES: &str = "SEEDANCE2PRO_COOKIES";
|
||||
const ENV_SEEDANCE2PRO_VOLCENGINE_COOKIES: &str = "SEEDANCE2PRO_VOLCENGINE_COOKIES";
|
||||
|
||||
// Cookies for BytePlus
|
||||
#[deprecated]
|
||||
const ENV_SEEDANCE2PRO_LEGACY_ALT_COOKIES: &str = "SEEDANCE2PRO_ALT_COOKIES";
|
||||
const ENV_SEEDANCE2PRO_BYTEPLUS_COOKIES: &str = "SEEDANCE2PRO_BYTEPLUS_COOKIES";
|
||||
|
||||
// Cookies for BytePlus Ultra
|
||||
const ENV_SEEDANCE2PRO_BYTEPLUS_ULTRA_COOKIES: &str = "SEEDANCE2PRO_BYTEPLUS_ULTRA_COOKIES";
|
||||
|
||||
|
||||
pub fn get_kinovi_version() -> anyhow::Result<KinoviVersion> {
|
||||
info!("Reading kinovi version from first CLI arg (optional - typical production config is via env vars):");
|
||||
|
||||
if let Some(arg) = std::env::args().nth(1) {
|
||||
return parse_kinovi_version(&arg);
|
||||
}
|
||||
|
||||
info!("Reading kinovi version from env var: {}", ENV_SEEDANCE2PRO_VERSION);
|
||||
|
||||
if let Some(version) = easyenv::get_env_string_optional(ENV_SEEDANCE2PRO_VERSION) {
|
||||
return parse_kinovi_version(&version);
|
||||
}
|
||||
|
||||
Err(anyhow!(
|
||||
"kinovi version not specified: set env var {} or pass volcengine|byteplus|byteplusultra as the first CLI arg",
|
||||
ENV_SEEDANCE2PRO_VERSION,
|
||||
))
|
||||
}
|
||||
|
||||
fn parse_kinovi_version(value: &str) -> anyhow::Result<KinoviVersion> {
|
||||
match value.trim().to_lowercase().as_str() {
|
||||
"volcengine" => Ok(KinoviVersion::Volcengine),
|
||||
"byteplus" => Ok(KinoviVersion::BytePlus),
|
||||
"byteplusultra" => Ok(KinoviVersion::BytePlusUltra),
|
||||
other => Err(anyhow!(
|
||||
"invalid kinovi version {:?} (expected volcengine|byteplus|byteplusultra)",
|
||||
other,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_kinovi_session(version: KinoviVersion) -> anyhow::Result<Seedance2ProSession> {
|
||||
let cookies = read_kinovi_cookies(version)?;
|
||||
Ok(Seedance2ProSession::from_cookies_string(cookies))
|
||||
}
|
||||
|
||||
fn read_kinovi_cookies(version: KinoviVersion) -> anyhow::Result<String> {
|
||||
match version {
|
||||
KinoviVersion::Volcengine => {
|
||||
info!("Using Volcengine cookies from env var: {}", ENV_SEEDANCE2PRO_VOLCENGINE_COOKIES);
|
||||
easyenv::get_env_string_optional(ENV_SEEDANCE2PRO_VOLCENGINE_COOKIES)
|
||||
.or_else(|| easyenv::get_env_string_optional(ENV_SEEDANCE2PRO_LEGACY_COOKIES))
|
||||
.ok_or_else(|| anyhow!("missing Seedance2Pro cookies in in env var {}", ENV_SEEDANCE2PRO_VOLCENGINE_COOKIES))
|
||||
}
|
||||
KinoviVersion::BytePlus => {
|
||||
info!("Using BytePlus cookies from env var: {}", ENV_SEEDANCE2PRO_BYTEPLUS_COOKIES);
|
||||
easyenv::get_env_string_optional(ENV_SEEDANCE2PRO_BYTEPLUS_COOKIES)
|
||||
.or_else(|| easyenv::get_env_string_optional(ENV_SEEDANCE2PRO_LEGACY_ALT_COOKIES))
|
||||
.ok_or_else(|| anyhow!("missing Seedance2Pro cookies in in env var {}", ENV_SEEDANCE2PRO_BYTEPLUS_COOKIES))
|
||||
}
|
||||
KinoviVersion::BytePlusUltra => {
|
||||
info!("Using BytePlus Ultra cookies from env var: {}", ENV_SEEDANCE2PRO_BYTEPLUS_ULTRA_COOKIES);
|
||||
let cookies = easyenv::get_env_string_required(ENV_SEEDANCE2PRO_BYTEPLUS_ULTRA_COOKIES)?;
|
||||
Ok(cookies)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parses_volcengine() {
|
||||
assert!(matches!(parse_kinovi_version("volcengine"), Ok(KinoviVersion::Volcengine)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_byteplus() {
|
||||
assert!(matches!(parse_kinovi_version("byteplus"), Ok(KinoviVersion::BytePlus)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_byteplusultra() {
|
||||
assert!(matches!(parse_kinovi_version("byteplusultra"), Ok(KinoviVersion::BytePlusUltra)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_is_case_insensitive() {
|
||||
assert!(matches!(parse_kinovi_version("Volcengine"), Ok(KinoviVersion::Volcengine)));
|
||||
assert!(matches!(parse_kinovi_version("BYTEPLUS"), Ok(KinoviVersion::BytePlus)));
|
||||
assert!(matches!(parse_kinovi_version("BytePlusUltra"), Ok(KinoviVersion::BytePlusUltra)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_trims_whitespace() {
|
||||
assert!(matches!(parse_kinovi_version(" volcengine\n"), Ok(KinoviVersion::Volcengine)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unknown_value_errors() {
|
||||
let err = parse_kinovi_version("nope").expect_err("nope should not parse");
|
||||
assert!(err.to_string().contains("nope"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_value_errors() {
|
||||
assert!(parse_kinovi_version("").is_err());
|
||||
assert!(parse_kinovi_version(" ").is_err());
|
||||
}
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
pub mod build_pager;
|
||||
pub mod kinovi_setup;
|
||||
|
||||
+2
-2
@@ -123,7 +123,7 @@ pub async fn create_character_handler(
|
||||
// --- Upload image to Kinovi CDN ---
|
||||
|
||||
let seedance_image_url = upload_to_kinovi(
|
||||
&server_state.inference_providers.seedance2pro.cookies,
|
||||
&server_state.inference_providers.seedance2pro.cookies_volcengine,
|
||||
image_cdn_url,
|
||||
).await?;
|
||||
|
||||
@@ -132,7 +132,7 @@ pub async fn create_character_handler(
|
||||
// --- Call Kinovi generate_character ---
|
||||
|
||||
let session = Seedance2ProSession::from_cookies_string(
|
||||
server_state.inference_providers.seedance2pro.cookies.clone()
|
||||
server_state.inference_providers.seedance2pro.cookies_volcengine.clone()
|
||||
);
|
||||
|
||||
let gen_result = generate_character(GenerateCharacterArgs {
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@ pub async fn edit_character_handler(
|
||||
if has_name_change {
|
||||
if let Some(ref kinovi_id) = character.kinovi_character_id {
|
||||
let session = Seedance2ProSession::from_cookies_string(
|
||||
server_state.inference_providers.seedance2pro.cookies.clone()
|
||||
server_state.inference_providers.seedance2pro.cookies_volcengine.clone()
|
||||
);
|
||||
|
||||
update_character(UpdateCharacterArgs {
|
||||
|
||||
+4
-7
@@ -26,10 +26,7 @@ use enums::common::visibility::Visibility;
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
use log::{error, info, warn};
|
||||
use mysql_queries::queries::characters::batch_lookup_characters_by_token_for_prompting::batch_lookup_characters_by_token_for_prompting;
|
||||
use mysql_queries::queries::generic_inference::api_providers::seedance2pro::insert_generic_inference_job_for_seedance2pro_queue_with_apriori_job_token::{
|
||||
insert_generic_inference_job_for_seedance2pro_queue_with_apriori_job_token,
|
||||
InsertGenericInferenceForSeedance2ProWithAprioriJobTokenArgs,
|
||||
};
|
||||
use mysql_queries::queries::generic_inference::api_providers::seedance2pro::insert_generic_inference_job_for_seedance2pro_queue_with_apriori_job_token::{insert_generic_inference_job_for_seedance2pro_queue_with_apriori_job_token, InsertGenericInferenceForSeedance2ProWithAprioriJobTokenArgs, KinoviVersion};
|
||||
use mysql_queries::queries::idepotency_tokens::insert_idempotency_token::insert_idempotency_token;
|
||||
use mysql_queries::queries::prompt_context_items::insert_batch_prompt_context_items::{
|
||||
insert_batch_prompt_context_items, InsertBatchArgs, PromptContextItem,
|
||||
@@ -215,7 +212,7 @@ pub async fn seedance_2p0_multi_function_video_gen_handler(
|
||||
warn!("Whitelist session failed for user {:?}: {:?}, falling back to regular session", user_token, err);
|
||||
|
||||
let regular_session = Seedance2ProSession::from_cookies_string(
|
||||
server_state.inference_providers.seedance2pro.cookies.clone()
|
||||
server_state.inference_providers.seedance2pro.cookies_volcengine.clone()
|
||||
);
|
||||
|
||||
let result = upload_and_generate(
|
||||
@@ -253,7 +250,7 @@ pub async fn seedance_2p0_multi_function_video_gen_handler(
|
||||
info!("User {:?} using regular seedance session", user_token);
|
||||
|
||||
let regular_session = Seedance2ProSession::from_cookies_string(
|
||||
server_state.inference_providers.seedance2pro.cookies.clone()
|
||||
server_state.inference_providers.seedance2pro.cookies_volcengine.clone()
|
||||
);
|
||||
|
||||
let result = upload_and_generate(
|
||||
@@ -412,7 +409,7 @@ pub async fn seedance_2p0_multi_function_video_gen_handler(
|
||||
|
||||
let db_result = insert_generic_inference_job_for_seedance2pro_queue_with_apriori_job_token(
|
||||
InsertGenericInferenceForSeedance2ProWithAprioriJobTokenArgs {
|
||||
use_alternate_kinovi: false,
|
||||
kinovi_version: KinoviVersion::Volcengine,
|
||||
apriori_job_token: &job_token,
|
||||
uuid_idempotency_token: &idempotency_str,
|
||||
maybe_external_third_party_id: order_id,
|
||||
|
||||
+12
-13
@@ -9,16 +9,17 @@ use artcraft_router::client::router_seedance2pro_client::RouterSeedance2ProClien
|
||||
use seedance2pro_client::creds::seedance2pro_session::Seedance2ProSession;
|
||||
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::endpoints::omni_gen::generate::video::kinovi_account::KinoviAccount;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
pub fn build_router_client(
|
||||
provider: RouterProvider,
|
||||
server_state: &ServerState,
|
||||
use_alternate_kinovi: bool,
|
||||
kinovi_account: KinoviAccount,
|
||||
) -> Result<RouterClient, CommonWebError> {
|
||||
match provider {
|
||||
RouterProvider::Seedance2Pro => {
|
||||
kinovi_provider(server_state, use_alternate_kinovi)
|
||||
kinovi_provider(server_state, kinovi_account)
|
||||
}
|
||||
RouterProvider::Fal => {
|
||||
let fal_client = RouterFalClient::new_with_webhook(
|
||||
@@ -45,18 +46,16 @@ pub fn build_router_client(
|
||||
}
|
||||
}
|
||||
|
||||
fn kinovi_provider(server_state: &ServerState, use_alternate_kinovi: bool) -> Result<RouterClient, CommonWebError> {
|
||||
let session = if use_alternate_kinovi {
|
||||
// Alternate Kinovi
|
||||
Seedance2ProSession::from_cookies_string(
|
||||
server_state.inference_providers.seedance2pro.cookies_byteplus.clone()
|
||||
)
|
||||
} else {
|
||||
// Standard Kinovi
|
||||
Seedance2ProSession::from_cookies_string(
|
||||
server_state.inference_providers.seedance2pro.cookies.clone()
|
||||
)
|
||||
fn kinovi_provider(server_state: &ServerState, kinovi_account: KinoviAccount) -> Result<RouterClient, CommonWebError> {
|
||||
let seedance2pro = &server_state.inference_providers.seedance2pro;
|
||||
|
||||
let cookies = match kinovi_account {
|
||||
KinoviAccount::Volcengine => seedance2pro.cookies_volcengine.clone(),
|
||||
KinoviAccount::BytePlus => seedance2pro.cookies_byteplus.clone(),
|
||||
KinoviAccount::BytePlusUltra => seedance2pro.cookies_byteplus_ultra.clone(),
|
||||
};
|
||||
|
||||
let session = Seedance2ProSession::from_cookies_string(cookies);
|
||||
|
||||
Ok(RouterClient::Seedance2Pro(RouterSeedance2ProClient::new(session)))
|
||||
}
|
||||
|
||||
+4
-7
@@ -2,10 +2,7 @@ use log::{error, warn};
|
||||
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use enums::common::visibility::Visibility;
|
||||
use mysql_queries::queries::generic_inference::api_providers::seedance2pro::insert_generic_inference_job_for_seedance2pro_queue_with_apriori_job_token::{
|
||||
insert_generic_inference_job_for_seedance2pro_queue_with_apriori_job_token,
|
||||
InsertGenericInferenceForSeedance2ProWithAprioriJobTokenArgs,
|
||||
};
|
||||
use mysql_queries::queries::generic_inference::api_providers::seedance2pro::insert_generic_inference_job_for_seedance2pro_queue_with_apriori_job_token::{insert_generic_inference_job_for_seedance2pro_queue_with_apriori_job_token, InsertGenericInferenceForSeedance2ProWithAprioriJobTokenArgs, KinoviVersion};
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use tokens::tokens::wallet_ledger_entries::WalletLedgerEntryToken;
|
||||
use uuid_utils::uuid::generate_random_uuid;
|
||||
@@ -16,7 +13,7 @@ pub struct InsertSeedance2proJobsArgs<'a, 'tx> {
|
||||
pub primary_order_id: &'a str,
|
||||
pub maybe_additional_order_ids: Option<&'a [String]>,
|
||||
pub maybe_wallet_ledger_entry_token: Option<&'a WalletLedgerEntryToken>,
|
||||
pub use_alternate_kinovi: bool,
|
||||
pub kinovi_version: KinoviVersion,
|
||||
pub shared: SharedJobArgs<'a, 'tx>,
|
||||
}
|
||||
|
||||
@@ -30,7 +27,7 @@ pub async fn insert_seedance2pro_jobs(args: InsertSeedance2proJobsArgs<'_, '_>)
|
||||
primary_order_id,
|
||||
maybe_additional_order_ids,
|
||||
maybe_wallet_ledger_entry_token,
|
||||
use_alternate_kinovi,
|
||||
kinovi_version,
|
||||
mut shared,
|
||||
} = args;
|
||||
|
||||
@@ -57,7 +54,7 @@ pub async fn insert_seedance2pro_jobs(args: InsertSeedance2proJobsArgs<'_, '_>)
|
||||
|
||||
let db_result = insert_generic_inference_job_for_seedance2pro_queue_with_apriori_job_token(
|
||||
InsertGenericInferenceForSeedance2ProWithAprioriJobTokenArgs {
|
||||
use_alternate_kinovi,
|
||||
kinovi_version,
|
||||
apriori_job_token: &job_token,
|
||||
uuid_idempotency_token: &idempotency_str,
|
||||
maybe_external_third_party_id: order_id,
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum KinoviAccount {
|
||||
Volcengine,
|
||||
BytePlus,
|
||||
BytePlusUltra,
|
||||
}
|
||||
+1
@@ -2,3 +2,4 @@ pub mod omni_gen_video_generate_handler;
|
||||
pub mod helpers;
|
||||
pub mod pipeline_v2;
|
||||
pub mod insert_db_job;
|
||||
pub mod kinovi_account;
|
||||
|
||||
+22
-8
@@ -18,6 +18,7 @@ use enums::common::generation::common_video_model::CommonVideoModel;
|
||||
use enums::common::generation_provider::GenerationProvider;
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
use mysql_queries::queries::debug_logs::insert_debug_log::{insert_debug_log, InsertDebugLogArgs};
|
||||
use mysql_queries::queries::generic_inference::api_providers::seedance2pro::insert_generic_inference_job_for_seedance2pro_queue_with_apriori_job_token::KinoviVersion;
|
||||
use mysql_queries::queries::idepotency_tokens::insert_idempotency_token::insert_idempotency_token;
|
||||
use mysql_queries::queries::prompt_context_items::insert_batch_prompt_context_items::{
|
||||
insert_batch_prompt_context_items, InsertBatchArgs, PromptContextItem,
|
||||
@@ -38,6 +39,7 @@ use crate::http_server::endpoints::omni_gen::generate::video::insert_db_job::ins
|
||||
use crate::http_server::endpoints::omni_gen::generate::video::insert_db_job::shared_job_args::SharedJobArgs;
|
||||
use crate::http_server::endpoints::omni_gen::generate::video::pipeline_v2::run_pipeline_v2::{run_pipeline_v2, RunPipelineV2Args};
|
||||
use crate::http_server::endpoints::omni_gen::generate::video::helpers::resolve_kinovi_character_ids::resolve_kinovi_character_ids;
|
||||
use crate::http_server::endpoints::omni_gen::generate::video::kinovi_account::KinoviAccount;
|
||||
use crate::http_server::session::lookup::user_session_feature_flags::UserSessionFeatureFlags;
|
||||
use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format;
|
||||
use crate::state::server_state::ServerState;
|
||||
@@ -166,12 +168,17 @@ pub async fn omni_gen_video_generate_handler(
|
||||
|
||||
// ==================== PIPELINE DISPATCH ==================== //
|
||||
|
||||
let use_alternate_kinovi = match request.model {
|
||||
Some(CommonVideoModel::Seedance2p0BytePlus) => true,
|
||||
Some(CommonVideoModel::Seedance2p0BytePlusFast) => true,
|
||||
Some(CommonVideoModel::PreviewModel) => true,
|
||||
Some(CommonVideoModel::PreviewModelFast) => true,
|
||||
_ => false,
|
||||
let kinovi_account = match request.model {
|
||||
// BytePlus Ultra
|
||||
Some(CommonVideoModel::Seedance2p0BytePlusUltra) => KinoviAccount::BytePlusUltra,
|
||||
Some(CommonVideoModel::Seedance2p0BytePlusUltraFast) => KinoviAccount::BytePlusUltra,
|
||||
// BytePlus
|
||||
Some(CommonVideoModel::Seedance2p0BytePlus) => KinoviAccount::BytePlus,
|
||||
Some(CommonVideoModel::Seedance2p0BytePlusFast) => KinoviAccount::BytePlus,
|
||||
Some(CommonVideoModel::PreviewModel) => KinoviAccount::BytePlus,
|
||||
Some(CommonVideoModel::PreviewModelFast) => KinoviAccount::BytePlus,
|
||||
// Everything else goes through Volcengine
|
||||
_ => KinoviAccount::Volcengine,
|
||||
};
|
||||
|
||||
// ==================== DEBUG LOG: HTTP REQUEST ==================== //
|
||||
@@ -194,7 +201,7 @@ pub async fn omni_gen_video_generate_handler(
|
||||
user_token,
|
||||
media_file_to_url_map: &media_file_to_url_map,
|
||||
kinovi_character_id_map: &kinovi_character_id_map,
|
||||
use_alternate_kinovi,
|
||||
kinovi_account,
|
||||
}).await?;
|
||||
|
||||
// ==================== DEBUG LOG: FAL REQUEST ==================== //
|
||||
@@ -318,11 +325,18 @@ pub async fn omni_gen_video_generate_handler(
|
||||
let (primary_job_token, all_job_tokens) = match &pipeline_result.response {
|
||||
GenerateVideoResponse::Seedance2Pro(payload) => {
|
||||
info!("Inserting seedance2pro job(s) with token: {:?}", pipeline_result.billing.apriori_job_token);
|
||||
|
||||
let kinovi_version = match kinovi_account {
|
||||
KinoviAccount::Volcengine => KinoviVersion::Volcengine,
|
||||
KinoviAccount::BytePlus => KinoviVersion::BytePlus,
|
||||
KinoviAccount::BytePlusUltra => KinoviVersion::BytePlusUltra,
|
||||
};
|
||||
|
||||
let result = insert_seedance2pro_jobs(InsertSeedance2proJobsArgs {
|
||||
primary_order_id: &payload.order_id,
|
||||
maybe_additional_order_ids: payload.maybe_order_ids.as_deref(),
|
||||
maybe_wallet_ledger_entry_token: pipeline_result.billing.maybe_wallet_ledger_entry_token.as_ref(),
|
||||
use_alternate_kinovi,
|
||||
kinovi_version,
|
||||
shared: SharedJobArgs {
|
||||
apriori_job_token: &pipeline_result.billing.apriori_job_token,
|
||||
idempotency_token: &idempotency_token,
|
||||
|
||||
+12
-9
@@ -18,6 +18,7 @@ use crate::http_server::endpoints::omni_gen::generate::video::helpers::bill_wall
|
||||
use crate::http_server::endpoints::omni_gen::generate::video::helpers::build_router_client::build_router_client;
|
||||
use crate::http_server::endpoints::omni_gen::generate::video::helpers::pipeline_result::PipelineResult;
|
||||
use crate::http_server::endpoints::omni_gen::generate::video::helpers::resolve_media_tokens_to_urls::resolve_media_tokens_to_urls;
|
||||
use crate::http_server::endpoints::omni_gen::generate::video::kinovi_account::KinoviAccount;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
pub struct RunPipelineV2Args<'a> {
|
||||
@@ -27,7 +28,7 @@ pub struct RunPipelineV2Args<'a> {
|
||||
pub user_token: &'a UserToken,
|
||||
pub media_file_to_url_map: &'a Option<HashMap<MediaFileToken, String>>,
|
||||
pub kinovi_character_id_map: &'a Option<HashMap<CharacterToken, String>>,
|
||||
pub use_alternate_kinovi: bool,
|
||||
pub kinovi_account: KinoviAccount,
|
||||
}
|
||||
|
||||
pub async fn run_pipeline_v2(args: RunPipelineV2Args<'_>) -> Result<PipelineResult, CommonWebError> {
|
||||
@@ -38,18 +39,20 @@ pub async fn run_pipeline_v2(args: RunPipelineV2Args<'_>) -> Result<PipelineResu
|
||||
user_token,
|
||||
media_file_to_url_map,
|
||||
kinovi_character_id_map,
|
||||
use_alternate_kinovi,
|
||||
kinovi_account,
|
||||
} = args;
|
||||
|
||||
let mut router_builder = router_builder.clone();
|
||||
|
||||
match router_builder.model {
|
||||
RouterVideoModel::PreviewModel |
|
||||
RouterVideoModel::Seedance2p0BytePlus => {
|
||||
RouterVideoModel::Seedance2p0BytePlus |
|
||||
RouterVideoModel::Seedance2p0BytePlusUltra => {
|
||||
router_builder.model = RouterVideoModel::Seedance2p0;
|
||||
},
|
||||
RouterVideoModel::PreviewModelFast |
|
||||
RouterVideoModel::Seedance2p0BytePlusFast => {
|
||||
RouterVideoModel::Seedance2p0BytePlusFast |
|
||||
RouterVideoModel::Seedance2p0BytePlusUltraFast => {
|
||||
router_builder.model = RouterVideoModel::Seedance2p0Fast;
|
||||
},
|
||||
_ => {}, // Fall-through
|
||||
@@ -59,8 +62,8 @@ pub async fn run_pipeline_v2(args: RunPipelineV2Args<'_>) -> Result<PipelineResu
|
||||
RouterVideoModel::HappyHorse1p0 => RouterProvider::Seedance2Pro,
|
||||
RouterVideoModel::Seedance2p0 => RouterProvider::Seedance2Pro,
|
||||
RouterVideoModel::Seedance2p0Fast => RouterProvider::Seedance2Pro,
|
||||
RouterVideoModel::Seedance2p0Ultra => RouterProvider::GmiCloud,
|
||||
RouterVideoModel::Seedance2p0UltraFast => RouterProvider::GmiCloud,
|
||||
//RouterVideoModel::Seedance2p0Ultra => RouterProvider::GmiCloud,
|
||||
//RouterVideoModel::Seedance2p0UltraFast => RouterProvider::GmiCloud,
|
||||
RouterVideoModel::GrokImagineVideo => RouterProvider::GrokApi,
|
||||
_ => RouterProvider::Fal,
|
||||
};
|
||||
@@ -114,7 +117,7 @@ pub async fn run_pipeline_v2(args: RunPipelineV2Args<'_>) -> Result<PipelineResu
|
||||
server_state,
|
||||
media_file_to_url_map.as_ref(),
|
||||
kinovi_character_id_map.as_ref(),
|
||||
use_alternate_kinovi,
|
||||
kinovi_account,
|
||||
).await;
|
||||
|
||||
// 5. On failure, refund wallet for Kinovi requests.
|
||||
@@ -147,11 +150,11 @@ async fn upload_and_generate(
|
||||
server_state: &ServerState,
|
||||
media_file_urls_by_token: Option<&HashMap<MediaFileToken, String>>,
|
||||
kinovi_character_ids: Option<&HashMap<CharacterToken, String>>,
|
||||
use_alternate_kinovi: bool,
|
||||
kinovi_account: KinoviAccount,
|
||||
) -> Result<GenerateVideoResponse, CommonWebError> {
|
||||
|
||||
let provider = draft_or_request.get_provider();
|
||||
let client = build_router_client(provider, server_state, use_alternate_kinovi)?;
|
||||
let client = build_router_client(provider, server_state, kinovi_account)?;
|
||||
|
||||
let video_request = match draft_or_request {
|
||||
VideoGenerationDraftOrRequest::Request(request) => request,
|
||||
|
||||
@@ -42,11 +42,11 @@ pub struct BeebleData {
|
||||
/// Seedance 2 Pro integration
|
||||
#[derive(Clone)]
|
||||
pub struct Seedance2ProData {
|
||||
/// Cookie string for seedance2-pro.com
|
||||
pub cookies: String,
|
||||
pub cookies_volcengine: String,
|
||||
|
||||
/// Cookie string for seedance2-pro.com (Whitelisted account)
|
||||
pub cookies_byteplus: String,
|
||||
|
||||
pub cookies_byteplus_ultra: String,
|
||||
}
|
||||
|
||||
/// OpenAI integration
|
||||
@@ -82,8 +82,9 @@ pub fn setup_inference_providers() -> AnyhowResult<InferenceProviders> {
|
||||
webhook_url: easyenv::get_env_string_required("BEEBLE_WEBHOOK_URL")?,
|
||||
},
|
||||
seedance2pro: Seedance2ProData {
|
||||
cookies: easyenv::get_env_string_required("SEEDANCE2PRO_COOKIES")?,
|
||||
cookies_volcengine: easyenv::get_env_string_required("SEEDANCE2PRO_COOKIES")?,
|
||||
cookies_byteplus: easyenv::get_env_string_required("SEEDANCE2PRO_WHITELIST_COOKIES")?,
|
||||
cookies_byteplus_ultra: easyenv::get_env_string_required("SEEDANCE2PRO_BYTEPLUS_ULTRA_COOKIES")?,
|
||||
},
|
||||
openai: OpenAiData {
|
||||
api_key: easyenv::get_env_string_required("OPENAI_API_KEY")?,
|
||||
|
||||
Reference in New Issue
Block a user