mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-17 00:13:17 +00:00
session, media_files/list endpoints
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
import axios from "axios";
|
||||
|
||||
export type MediaToken = string;
|
||||
import axios, { AxiosResponse } from "axios";
|
||||
|
||||
export class StorytellerApi {
|
||||
#api = axios.create({
|
||||
@@ -8,10 +6,10 @@ export class StorytellerApi {
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
async createScene(file: File): Promise<MediaToken> {
|
||||
async createScene(file: File): Promise<MediaFileToken> {
|
||||
type Response = {
|
||||
success: boolean;
|
||||
media_file_token: MediaToken;
|
||||
media_file_token: MediaFileToken;
|
||||
}
|
||||
|
||||
const response = await this.#api.postForm<Response>("v1/engine/create_scene", {
|
||||
@@ -20,10 +18,289 @@ export class StorytellerApi {
|
||||
}, {
|
||||
headers: { Accept: "text/plain" },
|
||||
});
|
||||
this.#validateResponse(response);
|
||||
|
||||
if (response.status === 200 && response.data.success)
|
||||
return response.data.media_file_token;
|
||||
return response.data.media_file_token;
|
||||
}
|
||||
|
||||
throw new Error(`API responded with status ${response.status}: "${response.statusText}"`);
|
||||
async session(): Promise<Session> {
|
||||
const response = await this.#api.get<Session>("v1/session");
|
||||
this.#validateResponse(response);
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async listMediaFiles(options: ListMediaFilesOptions = {}): Promise<ListMediaFilesResult> {
|
||||
const params = {} as any;
|
||||
|
||||
if (options.filterMediaType)
|
||||
params.filter_media_type = options.filterMediaType.join(",");
|
||||
if (options.sortAscending != null)
|
||||
params.soer_ascending = options.sortAscending;
|
||||
if (options.pageSize != null)
|
||||
params.page_size = options.pageSize;
|
||||
if (options.pageIndex != null)
|
||||
params.page_index = options.pageIndex;
|
||||
|
||||
const endpoint = options.username
|
||||
? `v1/media_files/list/user/${options.username}`
|
||||
: "v1/media_files/list";
|
||||
|
||||
const response = await this.#api.get<ListMediaFilesResult>(endpoint, { params });
|
||||
this.#validateResponse(response);
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
#validateResponse<R extends AxiosResponse>(response: R): asserts response is OkResponse<R> {
|
||||
if (response.status !== 200)
|
||||
throw new Error(`API responded with status ${response.status}: "${response.statusText}"`);
|
||||
|
||||
if (
|
||||
response.data
|
||||
&& "success" in response.data
|
||||
&& response.data.success === false
|
||||
) {
|
||||
throw new ApiError(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class ApiError<T extends AxiosResponse = AxiosResponse> extends Error {
|
||||
detail: T;
|
||||
|
||||
constructor (detail: T) {
|
||||
super("API Error");
|
||||
this.detail = detail;
|
||||
}
|
||||
}
|
||||
|
||||
type OkResponse<T extends AxiosResponse> = T & { status: 200 }
|
||||
|
||||
export interface ListMediaFilesOptions {
|
||||
username?: string;
|
||||
filterMediaType?: MediaFileType[];
|
||||
pageSize?: number;
|
||||
pageIndex?: number;
|
||||
sortAscending?: boolean;
|
||||
}
|
||||
|
||||
export interface ListMediaFilesResult {
|
||||
pagination: PaginationPage;
|
||||
results: MediaFileForUserListItem[];
|
||||
success: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pagination by page id.
|
||||
*
|
||||
* This type of pagination is by "page id" and "page count". This should never
|
||||
* be used to walk the entire public database as competitors and investors can
|
||||
* use it to glean information about the scale of our service. This is best used
|
||||
* for user profiles and scoped down results.
|
||||
*/
|
||||
export interface PaginationPage {
|
||||
current: number;
|
||||
total_page_count: number;
|
||||
}
|
||||
|
||||
export interface MediaFileListItem {
|
||||
/** Date-time string */
|
||||
created_at: string;
|
||||
creator_set_visibility: Visibility;
|
||||
maybe_creator?: UserDetailsLight;
|
||||
/** @deprecated */
|
||||
maybe_origin_model_token?: string;
|
||||
maybe_origin_model_type?: MediaFileOriginModelType;
|
||||
/** Text transcripts for TTS, etc. */
|
||||
maybe_text_transcript?: string;
|
||||
media_type: MediaFileType;
|
||||
origin: MediaFileOriginDetails;
|
||||
origin_category: MediaFileOriginCategory;
|
||||
origin_product_category: MediaFileOriginProductCategory;
|
||||
/** URL to the media file. */
|
||||
public_bucket_path: string;
|
||||
/** The primary key for Media Files */
|
||||
token: MediaFileToken;
|
||||
/** Date-time string */
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export type MediaFileForUserListItem = Omit<MediaFileListItem, "maybe_creator">;
|
||||
|
||||
export enum Visibility {
|
||||
Public = "public",
|
||||
Hidden = "hidden",
|
||||
Private = "private",
|
||||
}
|
||||
|
||||
/**
|
||||
* Used in the `media_files` table in a `VARCHAR` field.
|
||||
*
|
||||
* DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY.
|
||||
*/
|
||||
export enum MediaFileOriginModelType {
|
||||
RvcV2 = "rvc_v2",
|
||||
SadTalker = "sad_talker",
|
||||
SoVitsSvc = "so_vits_svc",
|
||||
Tacotron2 = "tacotron2",
|
||||
VallEX = "vall_e_x",
|
||||
Rerender = "rerender",
|
||||
MocapNet = "mocap_net",
|
||||
ComfyUi = "comfy_ui",
|
||||
StyleTts2 = "styletts2",
|
||||
StableDiffusion_1_5 = "stable_diffusion_1_5",
|
||||
}
|
||||
|
||||
/**
|
||||
* Used in the `media_files` table in a `VARCHAR(16)` field.
|
||||
*
|
||||
* DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY.
|
||||
*/
|
||||
export enum MediaFileType {
|
||||
Audio = "audio",
|
||||
Image = "image",
|
||||
Video = "video",
|
||||
Mocap = "mocap",
|
||||
Bvh = "bvh",
|
||||
Fbx = "fbx",
|
||||
Glb = "glb",
|
||||
Gltf = "gltf",
|
||||
ScnRon = "scene_ron",
|
||||
}
|
||||
|
||||
/** Fields useful for enriching media file listings */
|
||||
export interface MediaFileOriginDetails {
|
||||
maybe_model?: Model;
|
||||
origin_category: MediaFileOriginCategory;
|
||||
product_category: MediaFileOriginProductCategory;
|
||||
}
|
||||
|
||||
export interface Model {
|
||||
model_type: MediaFileOriginModelType;
|
||||
/**
|
||||
* The model title (typically only populated for model_weights models, not
|
||||
* legacy tables such as tts_models.)
|
||||
*/
|
||||
title?: string;
|
||||
/** The primary key for the "model_weights" table. */
|
||||
token?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used in the `media_files` table in a `VARCHAR` field.
|
||||
*
|
||||
* DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY.
|
||||
*/
|
||||
export enum MediaFileOriginCategory {
|
||||
Inference = "inference",
|
||||
Processed = "processed",
|
||||
Upload = "upload",
|
||||
DeviceApi = "device_api",
|
||||
StoryEngine = "story_engine",
|
||||
}
|
||||
|
||||
/**
|
||||
* Used in the `media_files` table in `VARCHAR(16)` field
|
||||
* `origin_product_category`.
|
||||
*
|
||||
* This value indicates what product originally created the media file. (Not the
|
||||
* ML model or user upload process.) This will let us scope media files to the
|
||||
* product that generated them and filter them out of unrelated products if
|
||||
* necessary (eg. a user probably doesn't want "Voice Designer" dataset samples
|
||||
* in a video generation flow.)
|
||||
*
|
||||
* DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY.
|
||||
*/
|
||||
export enum MediaFileOriginProductCategory {
|
||||
Unknown = "unknown",
|
||||
FaceAnimator = "face_animator",
|
||||
Tts = "tts",
|
||||
VoiceConversion = "voice_conversion",
|
||||
ZsVoice = "zs_voice",
|
||||
VideoFilter = "video_filter",
|
||||
Mocap = "mocap",
|
||||
ImageGen = "image_gen",
|
||||
Workflow = "workflow",
|
||||
}
|
||||
|
||||
export type MediaFileToken = string;
|
||||
|
||||
export interface Session {
|
||||
logged_in: boolean;
|
||||
success: boolean;
|
||||
user?: {
|
||||
can_access_studio: boolean;
|
||||
can_approve_w21_templates: boolean;
|
||||
can_ban_users: boolean;
|
||||
can_delete_other_users_tts_models: boolean;
|
||||
can_delete_other_users_tts_results: boolean;
|
||||
can_delete_other_users_w2l_results: boolean;
|
||||
can_delete_other_users_w2l_templates: boolean;
|
||||
can_delete_own_account: boolean;
|
||||
can_delete_own_tts_models: boolean;
|
||||
can_delete_own_tts_results: boolean;
|
||||
can_delete_own_w2l_results: boolean;
|
||||
can_delete_own_w2l_templates: boolean;
|
||||
can_delete_users: boolean;
|
||||
can_edit_other_users_profiles: boolean;
|
||||
can_edit_other_users_tts_models: boolean;
|
||||
can_edit_other_users_w2l_templates: boolean;
|
||||
can_upload_tts_models: boolean;
|
||||
can_upload_w2l_templates: boolean;
|
||||
can_use_tts: boolean;
|
||||
can_use_w2l: boolean;
|
||||
core_info: UserDetailsLight;
|
||||
display_name: string;
|
||||
email_gravatar_hash: string;
|
||||
fakeyou_plan: FakeYouPlan;
|
||||
maybe_feature_flags: unknown;
|
||||
storyteller_stream_plan: StorytellerStreamPlan;
|
||||
user_token: string;
|
||||
username: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Everything we need to refer to a user on the public web interface.
|
||||
*/
|
||||
export interface UserDetailsLight {
|
||||
default_avatar: DefaultAvatarInfo;
|
||||
/**
|
||||
* As of 2023-08-23, this is the username with capitalization (In the future,
|
||||
* a display name can be customized by the user.)
|
||||
*/
|
||||
display_name: string;
|
||||
/**
|
||||
* Email hash for Gravatar Always set for now since login is email/username +
|
||||
* password. In the future this will need to become an optional OR be filled
|
||||
* with a bogus hash.
|
||||
*/
|
||||
gravatar_hash: string;
|
||||
/** The primary key for users. */
|
||||
user_token: string;
|
||||
/**
|
||||
* The unique username someone logs in with. As of 2023-08-23, this is always
|
||||
* lowercase.
|
||||
*/
|
||||
username: string;
|
||||
}
|
||||
|
||||
export interface DefaultAvatarInfo {
|
||||
color_index: number;
|
||||
image_index: number;
|
||||
}
|
||||
|
||||
export enum FakeYouPlan {
|
||||
Free = "free",
|
||||
Basic = "basic",
|
||||
Standard = "standard",
|
||||
Pro = "pro",
|
||||
}
|
||||
|
||||
export enum StorytellerStreamPlan {
|
||||
Free = "free",
|
||||
Basic = "basic",
|
||||
Standard = "standard",
|
||||
Pro = "pro",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user