From 865f009ee21aa4d7f70033bb98176c7528bb24bc Mon Sep 17 00:00:00 2001 From: wil Date: Thu, 20 Jun 2024 22:54:37 -0400 Subject: [PATCH] implement v2v with the new audio upload in Api Manager, and big cleanup (#515) - simplify the upload component in v2v because the api manager made it easier now - comb through all the old api files - since nothing refers to them anymore, they are deleted Co-authored-by: wil --- app/api/GetApiHost.ts | 34 ------- app/api/MakeMultipartRequest.ts | 29 ------ app/api/MakeRequest.ts | 66 ------------- app/api/bookmarks/GetBookmarksByUser.ts | 26 ------ app/{api.tsx => api/index.tsx} | 2 +- app/api/media_files/EditCoverImage.ts | 14 --- app/api/media_files/UploadEngineAsset.ts | 69 -------------- app/api/media_files/UploadMedia.ts | 18 ---- app/api/media_files/UploadNewEngineAsset.ts | 47 ---------- app/components/reusable/Select.tsx | 2 +- .../UploadAudioButtonDialogue.tsx | 1 - .../UploadAudioComponent.tsx | 92 ++++++++++--------- .../UploadAudioComponent/utilities.tsx | 47 ---------- .../itemTabs/AudioTab/pageVoiceToVoice.tsx | 14 --- 14 files changed, 52 insertions(+), 409 deletions(-) delete mode 100644 app/api/GetApiHost.ts delete mode 100644 app/api/MakeMultipartRequest.ts delete mode 100644 app/api/MakeRequest.ts delete mode 100644 app/api/bookmarks/GetBookmarksByUser.ts rename app/{api.tsx => api/index.tsx} (95%) delete mode 100644 app/api/media_files/EditCoverImage.ts delete mode 100644 app/api/media_files/UploadEngineAsset.ts delete mode 100644 app/api/media_files/UploadMedia.ts delete mode 100644 app/api/media_files/UploadNewEngineAsset.ts delete mode 100644 app/components/signaled/UploadAudioComponent/utilities.tsx diff --git a/app/api/GetApiHost.ts b/app/api/GetApiHost.ts deleted file mode 100644 index e2a7547b83..0000000000 --- a/app/api/GetApiHost.ts +++ /dev/null @@ -1,34 +0,0 @@ -// interface ApiDetails { hostname: string, useSsl: boolean, } - -const domainWithoutPort = document.location.host.split(":")[0]; - -const hostConfig = (host: string, useSsl = true) => ({ - formatUrl: (endpoint = "") => `${ useSsl ? "https" : "http" }://${ host + endpoint }`, - host, - useSsl, -}); - -export default function GetApiHost() { - switch (domainWithoutPort) { - case "fakeyou.com": - case "staging.fakeyou.com": - return hostConfig("api.fakeyou.com"); - case "storyteller.ai": - case "staging.storyteller.ai": - //return hostConfig("api.storyteller.ai"); - return hostConfig("api.fakeyou.com"); - case "storyteller.stream": // Storyteller.stream is deprecated and will be decommissioned in the future. - return hostConfig("api.storyteller.stream"); - case "devproxy.fakeyou.com": - return hostConfig("api.fakeyou.com"); - case "devproxy.storyteller.ai": - //return hostConfig("api.storyteller.ai"); - return hostConfig("api.fakeyou.com"); - case "dev.fakeyou.com": - return hostConfig("api.dev.fakeyou.com:12345",false); // false disables SSL - default: - return document.location.host.includes("localhost") ? - hostConfig("localhost:12345",document.location.protocol === "https:") : - hostConfig("api.fakeyou.com"); // default - } -}; \ No newline at end of file diff --git a/app/api/MakeMultipartRequest.ts b/app/api/MakeMultipartRequest.ts deleted file mode 100644 index 2b63f5000f..0000000000 --- a/app/api/MakeMultipartRequest.ts +++ /dev/null @@ -1,29 +0,0 @@ -const MakeMultipartRequest = (endpoint = "", body: any) => { - const formData = new FormData(); - - Object.keys(body).forEach((key) => formData.append(key, body[key])); - - formData.append("source", "file"); - - return fetch(`https://api.storyteller.ai${endpoint}`, { - method: "POST", - credentials: "include", - headers: { - Accept: "application/json", - }, - body: formData, - }) - .then((res) => res.json()) - .then((res) => { - if (res && res.success) { - return res; - } else { - return { success: false }; - } - }) - .catch((e) => { - return { success: false }; - }); -}; - -export default MakeMultipartRequest; diff --git a/app/api/MakeRequest.ts b/app/api/MakeRequest.ts deleted file mode 100644 index 901731d83f..0000000000 --- a/app/api/MakeRequest.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { environmentVariables } from "~/signals"; - -type UrlRoutingFunction = (urlRouteArgs: UrlRouteArgs) => string; - -interface RouteSetup { - method: string; - multipart?: boolean; - routingFunction: UrlRoutingFunction; -} - -const METHOD_OMITS_BODY: { [key: string]: boolean } = { - DELETE: false, - GET: true, - OPTIONS: true, - PATCH: false, - POST: false, - PUT: false, -}; - -const MakeRequest = ( - routeSetup: RouteSetup, -): (( - urlRouteArgs: UrlRouteArgs, - request: Request, - queries?: UrlParams, -) => Promise) => { - return async function ( - urlRouteArgs: UrlRouteArgs, - request: Request, - queries?: any, - ): Promise { - const newQueries = queries - ? Object.keys(queries) - .map((key, i) => { - return `${i ? "&" : ""}${key}=${Array.isArray(queries[key]) ? queries[key].join(`&${key}=`) : queries[key]}`; - }) - .join("") - : null; - - const endpoint = `${routeSetup.routingFunction(urlRouteArgs)}${newQueries ? "?" + newQueries : ""}`; - const method = routeSetup.method; - const methodOmitsBody = METHOD_OMITS_BODY[method] || false; - - // return fetch(formatUrl(endpoint), { - return fetch(`${environmentVariables.value.BASE_API}${endpoint}`, { - method, - headers: { - Accept: "application/json", - ...(methodOmitsBody ? {} : { "Content-Type": "application/json" }), - }, - credentials: "include", - ...(methodOmitsBody ? {} : { body: JSON.stringify(request) }), - }) - .then((res) => res.json()) - .then((res) => { - if (!res.success && res && (res.voice_token || res.dataset_token)) { - return res; - } else if (res && "success" in res) { - return res; - } else Promise.reject(); - }) - .catch(() => ({ success: false })); - }; -}; - -export default MakeRequest; diff --git a/app/api/bookmarks/GetBookmarksByUser.ts b/app/api/bookmarks/GetBookmarksByUser.ts deleted file mode 100644 index 21061d2c90..0000000000 --- a/app/api/bookmarks/GetBookmarksByUser.ts +++ /dev/null @@ -1,26 +0,0 @@ -import MakeRequest from "../MakeRequest"; -// import { Weight } from "../weights/GetWeight"; - -export interface UserBookmarksListRequest {} - -export interface UserBookmarksListResponse { - // pagination: Pagination, - success: boolean; - // results: Weight[]; -} - -export interface UserBookmarksListQueries { - page_index?: number; - page_size: number; -} - -export const GetBookmarksByUser = MakeRequest< - string, - UserBookmarksListRequest, - UserBookmarksListResponse, - UserBookmarksListQueries ->({ - method: "GET", - routingFunction: (userToken: string) => - `/v1/user_bookmarks/list/user/${userToken}`, -}); diff --git a/app/api.tsx b/app/api/index.tsx similarity index 95% rename from app/api.tsx rename to app/api/index.tsx index fbcf8a4a73..7c7f522ec1 100644 --- a/app/api.tsx +++ b/app/api/index.tsx @@ -19,7 +19,7 @@ export const apiHost = "https://api.storyteller.ai"; //V2V // export const listV2V = `${apiHost}/v1/voice_conversion/model_list`; // export const inferV2V = `${apiHost}/v1/voice_conversion/inference`; -export const uploadAudioV2V = `${apiHost}/v1/media_uploads/upload_audio`; +// export const uploadAudioV2V = `${apiHost}/v1/media_uploads/upload_audio`; // User Media // export const listMediaByUser = (username: string) => diff --git a/app/api/media_files/EditCoverImage.ts b/app/api/media_files/EditCoverImage.ts deleted file mode 100644 index df1867a8fd..0000000000 --- a/app/api/media_files/EditCoverImage.ts +++ /dev/null @@ -1,14 +0,0 @@ -import MakeRequest from "../MakeRequest"; - -export interface EditCoverImageRequest { - cover_image_media_file_token: string -} - -export interface EditCoverImageResponse { - success: boolean -} - -export const EditCoverImage = MakeRequest({ - method: "POST", - routingFunction: (media_token: string) => `/v1/media_files/cover_image/${ media_token }`, -}); \ No newline at end of file diff --git a/app/api/media_files/UploadEngineAsset.ts b/app/api/media_files/UploadEngineAsset.ts deleted file mode 100644 index c191bbc72c..0000000000 --- a/app/api/media_files/UploadEngineAsset.ts +++ /dev/null @@ -1,69 +0,0 @@ -import MakeMultipartRequest from "../MakeMultipartRequest"; - -export enum MediaFileEngineCategory { - Scene = "scene", - Character = "character", - Animation = "animation", - Object = "object", - Skybox = "skybox", - Expression = "expression", -} - -export enum MediaFileAnimationType { - ar_kit = "ar_kit", - miku_miku_dance = "miku_miku_dance", - miku_miku_dance_ar_kit = "miku_miku_dance_ar_kit", - mixamo = "mixamo", - mixamo_ar_kit = "mixamo_ar_kit", - mocap_net = "mocap_net", - mocap_net_ar_kit = "mocap_net_ar_kit", - move_ai = "move_ai", - move_ai_ar_kit = "move_ai_ar_kit", - rigify = "rigify", - rigify_ar_kit = "rigify_ar_kit", -} - -export enum MediaFileSubtype { - /// Animation file from Mixamo - /// Primarily used for FBX and GLB. - Mixamo = "mixamo", - - /// Animation file from MocapNet - /// Primarily used for BVH. - MocapNet = "mocap_net", - - /// Generic animation case - /// Used for BVH files, but can also pertain to animation-only files of other types. - AnimationOnly = "animation_only", - - // TODO(bt,2024-03-08): Migrate records and code, then remove - /// DEPRECATED: Use `SceneImport` instead. - Scene = "scene", - - /// Generic 3D scene file. - /// Can pertain to glTF, glB, FBX, etc. - SceneImport = "scene_import", - - /// Native Storyteller scene format. - /// Typically stored in a `.scn.ron` file. - StorytellerScene = "storyteller_scene", -} - -export interface UploadEngineAssetRequest { - engine_category: MediaFileEngineCategory; - file: File; - maybe_animation_type: MediaFileAnimationType | null; - maybe_title?: string; - maybe_visibility?: string; - uuid_idempotency_token?: string; -} - -export interface UploadEngineAssetResponse { - media_file_token: string; - engine_category: string; - success: boolean; -} - -export const UploadEngineAsset = (request: UploadEngineAssetRequest) => { - return MakeMultipartRequest("/v1/media_files/upload/engine_asset", request); -}; diff --git a/app/api/media_files/UploadMedia.ts b/app/api/media_files/UploadMedia.ts deleted file mode 100644 index 360f77e2d3..0000000000 --- a/app/api/media_files/UploadMedia.ts +++ /dev/null @@ -1,18 +0,0 @@ -import MakeMultipartRequest from "../MakeMultipartRequest"; - -export interface UploadMediaRequest { - uuid_idempotency_token?: string; - file: File; - source: string; - title?: string; - // dataset_token: string, -} - -export interface UploadMediaResponse { - media_file_token: string; - success: boolean; -} - -export const UploadMedia = (request: UploadMediaRequest) => { - return MakeMultipartRequest("/v1/media_files/upload", request); -}; diff --git a/app/api/media_files/UploadNewEngineAsset.ts b/app/api/media_files/UploadNewEngineAsset.ts deleted file mode 100644 index f484c2fa53..0000000000 --- a/app/api/media_files/UploadNewEngineAsset.ts +++ /dev/null @@ -1,47 +0,0 @@ -import MakeMultipartRequest from "../MakeMultipartRequest"; - -export enum MediaFileEngineCategory { - Scene = "scene", - Character = "character", - Animation = "animation", - Expression = "expression", - Object = "object", - Skybox = "skybox", -} - -export enum MediaFileAnimationType { - ArKit = "ar_kit", - MikuMikuDance = "miku_miku_dance", - MikuMikuDanceArKit = "miku_miku_dance_ar_kit", - Mixamo = "mixamo", - MixamoArKit = "mixamo_ar_kit", - MocapNet = "mocap_net", - MocapNetArKit = "mocap_net_ar_kit", - MoveAi = "move_ai", - MoveAiArKit = "move_ai_ar_kit", - Rigify = "rigify", - RigifyArKit = "rigify_ar_kit", - Rokoko = "rokoko", -} - -export interface UploadNewEngineAssetRequest { - engine_category: MediaFileEngineCategory; - file: File; - maybe_animation_type?: MediaFileAnimationType; - maybe_title?: string; - maybe_visibility?: "public" | "private"; - maybe_duration_millis?: number; - uuid_idempotency_token?: string; -} - -export interface UploadNewEngineAssetResponse { - media_file_token: string; - success: boolean; -} - -export const UploadNewEngineAsset = (request: UploadNewEngineAssetRequest) => { - return MakeMultipartRequest( - "/v1/media_files/upload/new_engine_asset", - request, - ); -}; diff --git a/app/components/reusable/Select.tsx b/app/components/reusable/Select.tsx index 8008012e18..f36d213a53 100644 --- a/app/components/reusable/Select.tsx +++ b/app/components/reusable/Select.tsx @@ -2,7 +2,7 @@ import { Fragment } from "react"; import { Listbox, Transition } from "@headlessui/react"; import { faCheck, faChevronDown } from "@fortawesome/pro-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { MediaFileAnimationType } from "~/api/media_files/UploadNewEngineAsset"; +import { MediaFileAnimationType } from "~/enums"; export type SelectValue = string | number; export type SelectOption = { label: string; value: SelectValue }; diff --git a/app/components/signaled/UploadAudioButtonDialogue/UploadAudioButtonDialogue.tsx b/app/components/signaled/UploadAudioButtonDialogue/UploadAudioButtonDialogue.tsx index 20eaf6caa7..6b7464a1b5 100644 --- a/app/components/signaled/UploadAudioButtonDialogue/UploadAudioButtonDialogue.tsx +++ b/app/components/signaled/UploadAudioButtonDialogue/UploadAudioButtonDialogue.tsx @@ -86,7 +86,6 @@ export const UploadAudioButtonDialogue = ({ } //handle errors - console.log(response.errorMessage); addToast( ToastTypes.ERROR, response.errorMessage || "Unknown Error: Upload Audio", diff --git a/app/components/signaled/UploadAudioComponent/UploadAudioComponent.tsx b/app/components/signaled/UploadAudioComponent/UploadAudioComponent.tsx index e6ba268632..f2c5f7e540 100644 --- a/app/components/signaled/UploadAudioComponent/UploadAudioComponent.tsx +++ b/app/components/signaled/UploadAudioComponent/UploadAudioComponent.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from "react"; +import { useCallback, useState } from "react"; import { FileUploader } from "react-drag-drop-files"; import { v4 as uuidv4 } from "uuid"; import { @@ -11,32 +11,30 @@ import { } from "@fortawesome/pro-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { UploadAudio, UploadAudioIsOk, UploadAudioRequest } from "./utilities"; - import { Button, ButtonIcon, P, Tooltip, WaveformPlayer } from "~/components"; -import { AUDIO_FILE_TYPE } from "~/enums"; +import { MediaUploadApi } from "~/Classes/ApiManager"; +import { getFileName } from "~/utilities"; +import { AUDIO_FILE_TYPE, ToastTypes } from "~/enums"; +import { addToast } from "~/signals"; const FILE_TYPES = Object.keys(AUDIO_FILE_TYPE); interface Props { - file?: File; onFileStaged?: (file: File) => void; onClear?: () => void; onFileUploaded: (token: string) => void; } export const UploadAudioComponent = ({ - file: propsFile, onFileStaged, onClear, onFileUploaded, }: Props) => { - const [{ file, uploadState, uploadToken }, setState] = useState<{ + const [{ file, uploadState }, setState] = useState<{ file: File | undefined; - uploadState: "init" | "none" | "uploading" | "uploaded" | "error"; - uploadToken?: string; + uploadState: "none" | "staged" | "uploading" | "uploaded" | "error"; }>({ - file: propsFile, - uploadState: propsFile ? "none" : "init", + file: undefined, + uploadState: "none", }); const audioUrl = file ? URL.createObjectURL(file) : ""; @@ -45,8 +43,11 @@ export const UploadAudioComponent = ({ setState((curr) => ({ ...curr, file: file, - uploadState: "none", + uploadState: "staged", })); + if (onFileStaged) { + onFileStaged(file); + } }; const handleClear = () => { @@ -56,42 +57,43 @@ export const UploadAudioComponent = ({ uploadState: "none", uploadToken: undefined, })); + if (onClear) { + onClear(); + } }; - const handleUploadFile = () => { - if (file === undefined) return false; + const handleUploadFile = useCallback( + async (file: File) => { + setState((curr) => ({ ...curr, uploadState: "uploading" })); - setState((curr) => ({ ...curr, uploadState: "uploading" })); - const request: UploadAudioRequest = { - uuid_idempotency_token: uuidv4(), - file: file, - source: "file", - }; - - UploadAudio(request).then((res) => { - if (UploadAudioIsOk(res)) { + const mediaUploadApi = new MediaUploadApi(); + const request = { + blob: file, + fileName: getFileName(file), + uuid: uuidv4(), + maybe_title: getFileName(file), + }; + const response = await mediaUploadApi.UploadAudio(request); + if (response.success && response.data) { setState((curr) => ({ ...curr, uploadState: "uploaded", - uploadToken: res.upload_token, - })); - } else { - setState((curr) => ({ - ...curr, - uploadState: "error", - uploadToken: undefined, })); + onFileUploaded(response.data); + return; } - }); - }; - - useEffect(() => { - if (file && uploadState === "none" && onFileStaged) onFileStaged(file); - if (!file && uploadState === "none" && onClear) onClear(); - }, [file, uploadState]); - useEffect(() => { - if (uploadState === "uploaded" && uploadToken) onFileUploaded(uploadToken); - }, [uploadToken, uploadState]); + //handle errors + addToast( + ToastTypes.ERROR, + response.errorMessage || "Unknown Error: Upload Audio", + ); + setState((curr) => ({ + ...curr, + uploadState: "staged", + })); + }, + [onFileUploaded], + ); return (
@@ -123,8 +125,14 @@ export const UploadAudioComponent = ({
- {/*
- -

OR

- -
*/} - {/* */}