mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-09 11:31:27 +00:00
condense
This commit is contained in:
1 parent
d676a2fa6f
commit
65df7e392f
2 files changed
+74
-160
No files matched your search
+71
-130
@@ -12,7 +12,6 @@ use crate::api::video_list_ref::VideoListRef;
|
||||
use crate::client::router_seedance2pro_client::RouterSeedance2ProClient;
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_video::generate_video_request_builder::GenerateVideoRequestBuilder;
|
||||
use crate::generate::generate_video_v2::providers::kinovi::seedance_2p0::request::KinoviSeedance2p0RequestState;
|
||||
use crate::generate::generate_video_v2::providers::kinovi::upload::upload_to_seedance2pro;
|
||||
|
||||
@@ -55,24 +54,21 @@ impl KinoviSeedance2p0DraftState {
|
||||
let mut reference_audio_urls = None;
|
||||
|
||||
if let Some(remaining) = self.unhandled_request_state.take() {
|
||||
start_frame_url = resolve_and_upload_image_ref(
|
||||
session, remaining.start_frame, maybe_media_file_to_url_map,
|
||||
let map = maybe_media_file_to_url_map;
|
||||
|
||||
start_frame_url = resolve_and_upload_single(session, remaining.start_frame, map).await?;
|
||||
end_frame_url = resolve_and_upload_single(session, remaining.end_frame, map).await?;
|
||||
|
||||
reference_image_urls = resolve_and_upload_list(
|
||||
session, remaining.reference_images.map(ImageListRef::into_urls_or_tokens), map,
|
||||
).await?;
|
||||
|
||||
end_frame_url = resolve_and_upload_image_ref(
|
||||
session, remaining.end_frame, maybe_media_file_to_url_map,
|
||||
reference_video_urls = resolve_and_upload_list(
|
||||
session, remaining.reference_videos.map(VideoListRef::into_urls_or_tokens), map,
|
||||
).await?;
|
||||
|
||||
reference_image_urls = resolve_and_upload_image_list_ref(
|
||||
session, remaining.reference_images, maybe_media_file_to_url_map,
|
||||
).await?;
|
||||
|
||||
reference_video_urls = resolve_and_upload_video_list_ref(
|
||||
session, remaining.reference_videos, maybe_media_file_to_url_map,
|
||||
).await?;
|
||||
|
||||
reference_audio_urls = resolve_and_upload_audio_list_ref(
|
||||
session, remaining.reference_audio, maybe_media_file_to_url_map,
|
||||
reference_audio_urls = resolve_and_upload_list(
|
||||
session, remaining.reference_audio.map(AudioListRef::into_urls_or_tokens), map,
|
||||
).await?;
|
||||
|
||||
// TODO: Handle remaining.reference_character_tokens
|
||||
@@ -98,49 +94,71 @@ impl KinoviSeedance2p0DraftState {
|
||||
}
|
||||
}
|
||||
|
||||
/// Either resolved URLs or unresolved media file tokens.
|
||||
enum UrlsOrTokens {
|
||||
Urls(Vec<String>),
|
||||
Tokens(Vec<MediaFileToken>),
|
||||
}
|
||||
|
||||
// Allow each list ref type to decompose into this common representation.
|
||||
impl ImageListRef {
|
||||
fn into_urls_or_tokens(self) -> UrlsOrTokens {
|
||||
match self {
|
||||
Self::Urls(urls) => UrlsOrTokens::Urls(urls),
|
||||
Self::MediaFileTokens(tokens) => UrlsOrTokens::Tokens(tokens),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VideoListRef {
|
||||
fn into_urls_or_tokens(self) -> UrlsOrTokens {
|
||||
match self {
|
||||
Self::Urls(urls) => UrlsOrTokens::Urls(urls),
|
||||
Self::MediaFileTokens(tokens) => UrlsOrTokens::Tokens(tokens),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AudioListRef {
|
||||
fn into_urls_or_tokens(self) -> UrlsOrTokens {
|
||||
match self {
|
||||
Self::Urls(urls) => UrlsOrTokens::Urls(urls),
|
||||
Self::MediaFileTokens(tokens) => UrlsOrTokens::Tokens(tokens),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Resolve + upload helpers ---
|
||||
|
||||
/// Resolve a single ImageRef to a URL string, then upload to Seedance2Pro CDN.
|
||||
async fn resolve_and_upload_image_ref(
|
||||
/// Resolve a single ImageRef and upload to Seedance2Pro CDN.
|
||||
async fn resolve_and_upload_single(
|
||||
session: &Seedance2ProSession,
|
||||
image_ref: Option<ImageRef>,
|
||||
maybe_map: Option<&HashMap<MediaFileToken, String>>,
|
||||
) -> Result<Option<String>, ArtcraftRouterError> {
|
||||
let image_ref = match image_ref {
|
||||
None => return Ok(None),
|
||||
Some(r) => r,
|
||||
};
|
||||
|
||||
let source_url = match image_ref {
|
||||
ImageRef::Url(url) => url,
|
||||
ImageRef::MediaFileToken(token) => resolve_token_to_url(&token, maybe_map)?,
|
||||
None => return Ok(None),
|
||||
Some(ImageRef::Url(url)) => url,
|
||||
Some(ImageRef::MediaFileToken(token)) => resolve_token(maybe_map, &token)?,
|
||||
};
|
||||
|
||||
let uploaded = upload_to_seedance2pro(session, &source_url).await?;
|
||||
Ok(Some(uploaded))
|
||||
Ok(Some(upload_to_seedance2pro(session, &source_url).await?))
|
||||
}
|
||||
|
||||
/// Resolve an ImageListRef to URL strings, then upload each to Seedance2Pro CDN.
|
||||
/// Order of the input list is preserved in the output.
|
||||
async fn resolve_and_upload_image_list_ref(
|
||||
/// Resolve a list of refs to URLs and upload each to Seedance2Pro CDN.
|
||||
/// Order is preserved.
|
||||
async fn resolve_and_upload_list(
|
||||
session: &Seedance2ProSession,
|
||||
image_list_ref: Option<ImageListRef>,
|
||||
urls_or_tokens: Option<UrlsOrTokens>,
|
||||
maybe_map: Option<&HashMap<MediaFileToken, String>>,
|
||||
) -> Result<Option<Vec<String>>, ArtcraftRouterError> {
|
||||
let list = match image_list_ref {
|
||||
let source_urls = match urls_or_tokens {
|
||||
None => return Ok(None),
|
||||
Some(r) => r,
|
||||
Some(UrlsOrTokens::Urls(urls)) if urls.is_empty() => return Ok(None),
|
||||
Some(UrlsOrTokens::Urls(urls)) => urls,
|
||||
Some(UrlsOrTokens::Tokens(tokens)) if tokens.is_empty() => return Ok(None),
|
||||
Some(UrlsOrTokens::Tokens(tokens)) => resolve_tokens(maybe_map, &tokens)?,
|
||||
};
|
||||
|
||||
let source_urls = match list {
|
||||
ImageListRef::Urls(urls) => urls,
|
||||
ImageListRef::MediaFileTokens(tokens) => resolve_tokens_to_urls(&tokens, maybe_map)?,
|
||||
};
|
||||
|
||||
if source_urls.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let mut uploaded = Vec::with_capacity(source_urls.len());
|
||||
for url in &source_urls {
|
||||
uploaded.push(upload_to_seedance2pro(session, url).await?);
|
||||
@@ -148,100 +166,23 @@ async fn resolve_and_upload_image_list_ref(
|
||||
Ok(Some(uploaded))
|
||||
}
|
||||
|
||||
/// Resolve a VideoListRef to URL strings, then upload each to Seedance2Pro CDN.
|
||||
/// Order of the input list is preserved in the output.
|
||||
async fn resolve_and_upload_video_list_ref(
|
||||
session: &Seedance2ProSession,
|
||||
video_list_ref: Option<VideoListRef>,
|
||||
// --- Token resolution ---
|
||||
|
||||
fn resolve_token(
|
||||
maybe_map: Option<&HashMap<MediaFileToken, String>>,
|
||||
) -> Result<Option<Vec<String>>, ArtcraftRouterError> {
|
||||
let list = match video_list_ref {
|
||||
None => return Ok(None),
|
||||
Some(r) => r,
|
||||
};
|
||||
|
||||
let source_urls = match list {
|
||||
VideoListRef::Urls(urls) => urls,
|
||||
VideoListRef::MediaFileTokens(tokens) => resolve_tokens_to_urls(&tokens, maybe_map)?,
|
||||
};
|
||||
|
||||
if source_urls.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let mut uploaded = Vec::with_capacity(source_urls.len());
|
||||
for url in &source_urls {
|
||||
uploaded.push(upload_to_seedance2pro(session, url).await?);
|
||||
}
|
||||
Ok(Some(uploaded))
|
||||
}
|
||||
|
||||
/// Resolve an AudioListRef to URL strings, then upload each to Seedance2Pro CDN.
|
||||
/// Order of the input list is preserved in the output.
|
||||
async fn resolve_and_upload_audio_list_ref(
|
||||
session: &Seedance2ProSession,
|
||||
audio_list_ref: Option<AudioListRef>,
|
||||
maybe_map: Option<&HashMap<MediaFileToken, String>>,
|
||||
) -> Result<Option<Vec<String>>, ArtcraftRouterError> {
|
||||
let list = match audio_list_ref {
|
||||
None => return Ok(None),
|
||||
Some(r) => r,
|
||||
};
|
||||
|
||||
let source_urls = match list {
|
||||
AudioListRef::Urls(urls) => urls,
|
||||
AudioListRef::MediaFileTokens(tokens) => resolve_tokens_to_urls(&tokens, maybe_map)?,
|
||||
};
|
||||
|
||||
if source_urls.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let mut uploaded = Vec::with_capacity(source_urls.len());
|
||||
for url in &source_urls {
|
||||
uploaded.push(upload_to_seedance2pro(session, url).await?);
|
||||
}
|
||||
Ok(Some(uploaded))
|
||||
}
|
||||
|
||||
// --- Token resolution helpers ---
|
||||
|
||||
/// Look up a single media file token in the map to get its CDN URL.
|
||||
fn resolve_token_to_url(
|
||||
token: &MediaFileToken,
|
||||
maybe_map: Option<&HashMap<MediaFileToken, String>>,
|
||||
) -> Result<String, ArtcraftRouterError> {
|
||||
let map = maybe_map.ok_or_else(|| {
|
||||
ArtcraftRouterError::Client(ClientError::MediaFileToUrlMapNotProvided)
|
||||
})?;
|
||||
|
||||
map.get(token)
|
||||
.cloned()
|
||||
.ok_or_else(|| {
|
||||
ArtcraftRouterError::Client(ClientError::MediaFileTokenNotFoundInMap {
|
||||
token: token.as_str().to_string(),
|
||||
})
|
||||
let map = maybe_map.ok_or(ArtcraftRouterError::Client(ClientError::MediaFileToUrlMapNotProvided))?;
|
||||
map.get(token).cloned().ok_or_else(|| {
|
||||
ArtcraftRouterError::Client(ClientError::MediaFileTokenNotFoundInMap {
|
||||
token: token.as_str().to_string(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Look up multiple media file tokens in the map. Order is preserved.
|
||||
fn resolve_tokens_to_urls(
|
||||
tokens: &[MediaFileToken],
|
||||
fn resolve_tokens(
|
||||
maybe_map: Option<&HashMap<MediaFileToken, String>>,
|
||||
tokens: &[MediaFileToken],
|
||||
) -> Result<Vec<String>, ArtcraftRouterError> {
|
||||
let map = maybe_map.ok_or_else(|| {
|
||||
ArtcraftRouterError::Client(ClientError::MediaFileToUrlMapNotProvided)
|
||||
})?;
|
||||
|
||||
tokens.iter()
|
||||
.map(|token| {
|
||||
map.get(token)
|
||||
.cloned()
|
||||
.ok_or_else(|| {
|
||||
ArtcraftRouterError::Client(ClientError::MediaFileTokenNotFoundInMap {
|
||||
token: token.as_str().to_string(),
|
||||
})
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
tokens.iter().map(|t| resolve_token(maybe_map, t)).collect()
|
||||
}
|
||||
+3
-30
@@ -1,41 +1,14 @@
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::provider_error::ProviderError;
|
||||
use crate::utils::download_file::download_file;
|
||||
use seedance2pro_client::creds::seedance2pro_session::Seedance2ProSession;
|
||||
use seedance2pro_client::requests::prepare_file_upload::prepare_file_upload::{prepare_file_upload, PrepareFileUploadArgs};
|
||||
use seedance2pro_client::requests::upload_file::upload_file::{upload_file, UploadFileArgs};
|
||||
use url_utils::extension::extract_extension_from_url::{extract_extension_from_url_str, ExtractExtensions};
|
||||
use crate::errors::provider_error::ProviderError;
|
||||
use crate::utils::download_file::download_file;
|
||||
|
||||
pub(super) async fn upload_optional_url(
|
||||
session: &Seedance2ProSession,
|
||||
url: Option<&str>,
|
||||
) -> Result<Option<String>, ArtcraftRouterError> {
|
||||
match url {
|
||||
None => Ok(None),
|
||||
Some(u) => Ok(Some(upload_to_seedance2pro(session, u).await?)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) async fn upload_optional_url_list(
|
||||
session: &Seedance2ProSession,
|
||||
urls: Option<&[String]>,
|
||||
) -> Result<Option<Vec<String>>, ArtcraftRouterError> {
|
||||
match urls {
|
||||
None => Ok(None),
|
||||
Some(url_list) if url_list.is_empty() => Ok(None),
|
||||
Some(url_list) => {
|
||||
let mut uploaded = Vec::with_capacity(url_list.len());
|
||||
for url in url_list {
|
||||
uploaded.push(upload_to_seedance2pro(session, url).await?);
|
||||
}
|
||||
Ok(Some(uploaded))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Downloads a file from a source URL and re-uploads it to seedance2pro CDN.
|
||||
pub(crate) async fn upload_to_seedance2pro(
|
||||
session: &seedance2pro_client::creds::seedance2pro_session::Seedance2ProSession,
|
||||
session: &Seedance2ProSession,
|
||||
source_url: &str,
|
||||
) -> Result<String, ArtcraftRouterError> {
|
||||
let extension = extract_extension_from_url_str(source_url, &ExtractExtensions::All)
|
||||
|
||||
Reference in new issue
Block a user