new crate

This commit is contained in:
Brandon Thomas committed 2026-02-22 17:53:46 +07:00
1 parent 9506885529
commit 8d5d9f8991
15 files changed
+302

No files matched your search

+29
View File
@@ -0,0 +1,29 @@
[package]
name = "artcraft_router"
edition = "2024"
version = "0.0.1"
publish = false
[package.metadata.cargo-udeps.ignore]
normal = ["workspace-build-acceleration"]
[lib]
name = "artcraft_router"
path = "src/lib.rs"
[dependencies]
# Workspace hack (faster compile times)
workspace-build-acceleration.workspace = true
# Internal
artcraft_api_defs.workspace = true
storyteller_client.workspace = true
tokens.workspace = true
# External
anyhow.workspace = true
log.workspace = true
serde.workspace = true
serde_derive.workspace = true
tokio = { version = "1", features = ["full"] }
uuid = { version = "1", features = ["v4"] }
@@ -0,0 +1,42 @@
use serde_derive::{Deserialize, Serialize};
/// This is a comprehensive list of common aspect ratios you can specify when enqueuing a generation.
/// Not every model will support every aspect ratio.
/// In the case a model doesn't support the aspect ratio, gracefully pick the nearest option.
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CommonAspectRatio {
// Auto (eg. for image editing to use the source; used by Nano Banana Pro edit image, but not text-to-image)
Auto,
// Square
Square,
// Wide
WideThreeByTwo,
WideFourByThree,
WideFiveByFour,
WideSixteenByNine,
WideTwentyOneByNine,
// Tall
TallTwoByThree,
TallThreeByFour,
TallFourByFive,
TallNineBySixteen,
TallNineByTwentyOne,
// Imprecise semantic values that we probably remap to other meanings
// on a model-by-model basis.
Wide,
Tall,
// Auto values that bake in resolution
// These are from the Seedream models
Auto2k,
Auto4k,
// Defined aspect ratios that bake in resolution
// These are from the Seedream models
SquareHd,
}
@@ -0,0 +1,17 @@
use serde_derive::{Deserialize, Serialize};
/// This is a comprehensive list of common resolutions you can specify when enqueuing a generation.
/// Not every model will support every resolution.
/// In the case a model doesn't support the resolution, gracefully pick the nearest option.
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CommonVideoResolution {
/// Models: Nano Banana Pro
OneK,
/// Models: Nano Banana Pro
TwoK,
/// Models: (None)
ThreeK,
/// Models: Nano Banana Pro
FourK,
}
@@ -0,0 +1,52 @@
use serde_derive::{Deserialize, Serialize};
/// Common video models supported by the router.
/// Not all models are available through all providers.
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CommonVideoModel {
#[serde(rename = "grok_video")]
GrokVideo,
#[serde(rename = "kling_1.6_pro")]
Kling16Pro,
#[serde(rename = "kling_2.1_pro")]
Kling21Pro,
#[serde(rename = "kling_2.1_master")]
Kling21Master,
#[serde(rename = "kling_2p5_turbo_pro")]
Kling2p5TurboPro,
#[serde(rename = "kling_2p6_pro")]
Kling2p6Pro,
#[serde(rename = "seedance_1.0_lite")]
Seedance10Lite,
#[serde(rename = "seedance_2p0")]
Seedance2p0,
#[serde(rename = "sora_2")]
Sora2,
#[serde(rename = "sora_2_pro")]
Sora2Pro,
#[serde(rename = "veo_2")]
Veo2,
#[serde(rename = "veo_3")]
Veo3,
#[serde(rename = "veo_3_fast")]
Veo3Fast,
#[serde(rename = "veo_3p1")]
Veo3p1,
#[serde(rename = "veo_3p1_fast")]
Veo3p1Fast,
}
@@ -0,0 +1,3 @@
pub mod common_aspect_ratio;
pub mod common_resolution;
pub mod common_video_model;
@@ -0,0 +1,33 @@
use crate::errors::provider_error::ProviderError;
use std::error::Error;
use std::fmt::{Display, Formatter};
#[derive(Debug)]
pub enum ArtcraftRouterError {
/// The requested model is not yet supported by the router.
UnsupportedModel(String),
/// Invalid or missing input arguments.
InvalidInput(String),
/// An error from an underlying provider.
Provider(ProviderError),
}
impl Error for ArtcraftRouterError {}
impl Display for ArtcraftRouterError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::UnsupportedModel(model) => write!(f, "Unsupported model: {}", model),
Self::InvalidInput(msg) => write!(f, "Invalid input: {}", msg),
Self::Provider(e) => write!(f, "Provider error: {}", e),
}
}
}
impl From<ProviderError> for ArtcraftRouterError {
fn from(error: ProviderError) -> Self {
Self::Provider(error)
}
}
@@ -0,0 +1,2 @@
pub mod artcraft_router_error;
pub mod provider_error;
@@ -0,0 +1,24 @@
use std::error::Error;
use std::fmt::{Display, Formatter};
use storyteller_client::error::storyteller_error::StorytellerError;
#[derive(Debug)]
pub enum ProviderError {
Storyteller(StorytellerError),
}
impl Error for ProviderError {}
impl Display for ProviderError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::Storyteller(e) => write!(f, "Storyteller provider error: {}", e),
}
}
}
impl From<StorytellerError> for ProviderError {
fn from(error: StorytellerError) -> Self {
Self::Storyteller(error)
}
}
@@ -0,0 +1,37 @@
use crate::api::common_aspect_ratio::CommonAspectRatio;
use crate::api::common_resolution::CommonVideoResolution;
use crate::api::common_video_model::CommonVideoModel;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::generate::generate_video::providers::artcraft::generate_video_artcraft_seedance2p0::generate_video_artcraft_seedance2p0;
use storyteller_client::credentials::storyteller_credential_set::StorytellerCredentialSet;
use storyteller_client::utils::api_host::ApiHost;
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
pub struct GenerateVideoArgs {
pub model: CommonVideoModel,
pub resolution: Option<CommonVideoResolution>,
pub aspect_ratio: Option<CommonAspectRatio>,
pub prompt: Option<String>,
}
pub struct GenerateVideoResponse {
pub inference_job_token: InferenceJobToken,
pub all_inference_job_tokens: Vec<InferenceJobToken>,
}
pub struct GenerateVideoContext<'a> {
pub api_host: &'a ApiHost,
pub storyteller_creds: Option<&'a StorytellerCredentialSet>,
}
pub async fn generate_video(
args: &GenerateVideoArgs,
context: &GenerateVideoContext<'_>,
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
match args.model {
CommonVideoModel::Seedance2p0 => {
generate_video_artcraft_seedance2p0(args, context.api_host, context.storyteller_creds).await
}
_ => Err(ArtcraftRouterError::UnsupportedModel(format!("{:?}", args.model))),
}
}
@@ -0,0 +1,2 @@
pub mod generate_video;
pub mod providers;
@@ -0,0 +1,55 @@
use crate::api::common_aspect_ratio::CommonAspectRatio;
use crate::errors::artcraft_router_error::ArtcraftRouterError;
use crate::errors::provider_error::ProviderError;
use crate::generate::generate_video::generate_video::{GenerateVideoArgs, GenerateVideoResponse};
use artcraft_api_defs::generate::video::multi_function::seedance_2p0_multi_function_video_gen::{
Seedance2p0AspectRatio, Seedance2p0BatchCount, Seedance2p0MultiFunctionVideoGenRequest,
};
use storyteller_client::credentials::storyteller_credential_set::StorytellerCredentialSet;
use storyteller_client::endpoints::generate::video::multi_function::seedance_2p0_multi_function_video_gen::seedance_2p0_multi_function_video_gen;
use storyteller_client::utils::api_host::ApiHost;
use uuid::Uuid;
fn map_aspect_ratio(aspect_ratio: Option<CommonAspectRatio>) -> Option<Seedance2p0AspectRatio> {
match aspect_ratio {
Some(CommonAspectRatio::WideSixteenByNine) | Some(CommonAspectRatio::Wide) => {
Some(Seedance2p0AspectRatio::Landscape16x9)
}
Some(CommonAspectRatio::TallNineBySixteen) | Some(CommonAspectRatio::Tall) => {
Some(Seedance2p0AspectRatio::Portrait9x16)
}
Some(CommonAspectRatio::Square) => Some(Seedance2p0AspectRatio::Square1x1),
Some(CommonAspectRatio::WideFourByThree) => Some(Seedance2p0AspectRatio::Standard4x3),
Some(CommonAspectRatio::TallThreeByFour) => Some(Seedance2p0AspectRatio::Portrait3x4),
_ => None,
}
}
pub async fn generate_video_artcraft_seedance2p0(
args: &GenerateVideoArgs,
api_host: &ApiHost,
creds: Option<&StorytellerCredentialSet>,
) -> Result<GenerateVideoResponse, ArtcraftRouterError> {
let uuid_idempotency_token = Uuid::new_v4().to_string();
let aspect_ratio = map_aspect_ratio(args.aspect_ratio);
let request = Seedance2p0MultiFunctionVideoGenRequest {
uuid_idempotency_token,
prompt: args.prompt.clone(),
start_frame_media_token: None,
end_frame_media_token: None,
reference_image_media_tokens: None,
aspect_ratio,
duration_seconds: None,
batch_count: Some(Seedance2p0BatchCount::One),
};
let response = seedance_2p0_multi_function_video_gen(api_host, creds, request)
.await
.map_err(|err| ArtcraftRouterError::Provider(ProviderError::Storyteller(err)))?;
Ok(GenerateVideoResponse {
inference_job_token: response.inference_job_token,
all_inference_job_tokens: response.all_inference_job_tokens,
})
}
@@ -0,0 +1 @@
pub mod generate_video_artcraft_seedance2p0;
@@ -0,0 +1 @@
pub mod artcraft;
@@ -0,0 +1 @@
pub mod generate_video;
+3
View File
@@ -0,0 +1,3 @@
pub mod api;
pub mod errors;
pub mod generate;