Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
| import api from "./http"; | |
| import { | |
| Asset, | |
| ChatMessage, | |
| ChatResponse, | |
| PipelineStatus, | |
| Project, | |
| ProjectListItem, | |
| RenderStatus, | |
| Scene, | |
| StudioResponse, | |
| ProjectTemplateChangeJob, | |
| ProjectRegenerateScriptJob, | |
| RegenerateScriptPreviewOut, | |
| } from "./types"; | |
| // βββ Project API ββββββββββββββββββββββββββββββββββββββββββ | |
| export const createProject = ( | |
| blog_url: string, | |
| name?: string, | |
| voice_gender?: string, | |
| voice_accent?: string, | |
| accent_color?: string, | |
| bg_color?: string, | |
| text_color?: string, | |
| animation_instructions?: string, | |
| logo_position?: string, | |
| logo_opacity?: number, | |
| custom_voice_id?: string, | |
| aspect_ratio?: string | |
| ) => | |
| api.post<Project>("/projects", { | |
| blog_url, | |
| name, | |
| voice_gender, | |
| voice_accent, | |
| accent_color, | |
| bg_color, | |
| text_color, | |
| animation_instructions, | |
| logo_position, | |
| logo_opacity, | |
| custom_voice_id, | |
| aspect_ratio, | |
| }); | |
| export const uploadLogo = (projectId: number, file: File) => { | |
| const formData = new FormData(); | |
| formData.append("file", file); | |
| return api.post<{ logo_url: string; logo_position: string }>( | |
| `/projects/${projectId}/logo`, | |
| formData, | |
| { headers: { "Content-Type": "multipart/form-data" } } | |
| ); | |
| }; | |
| export const listProjects = () => api.get<ProjectListItem[]>("/projects"); | |
| export const getProject = (id: number) => api.get<Project>(`/projects/${id}`); | |
| export const deleteProject = (id: number) => api.delete(`/projects/${id}`); | |
| export const toggleAssetExclusion = (projectId: number, assetId: number) => | |
| api.patch<{ id: number; excluded: boolean }>( | |
| `/projects/${projectId}/assets/${assetId}/exclude` | |
| ); | |
| export const scrapeProject = (id: number) => | |
| api.post<Project>(`/projects/${id}/scrape`); | |
| export const generateScript = (id: number) => | |
| api.post<Project>(`/projects/${id}/generate-script`); | |
| export const generateScenes = (id: number) => | |
| api.post<Project>(`/projects/${id}/generate-scenes`); | |
| // βββ Async pipeline ββββββββββββββββββββββββββββββββββββββ | |
| export const startGeneration = (id: number) => | |
| api.post(`/projects/${id}/generate`); | |
| export const getPipelineStatus = (id: number) => | |
| api.get<PipelineStatus>(`/projects/${id}/status`); | |
| export const changeProjectTemplateRegenerateLayouts = ( | |
| projectId: number, | |
| template: string | |
| ) => | |
| api.post<ProjectTemplateChangeJob>( | |
| `/projects/${projectId}/change-template-regenerate-layouts`, | |
| { template } | |
| ); | |
| export const getProjectTemplateChangeStatus = (projectId: number) => | |
| api.get<ProjectTemplateChangeJob | null>( | |
| `/projects/${projectId}/template-change-status` | |
| ); | |
| export const regenerateScript = ( | |
| projectId: number, | |
| body?: { user_instruction?: string }, | |
| ) => | |
| api.post<ProjectRegenerateScriptJob>( | |
| `/projects/${projectId}/regenerate-script`, | |
| body ?? {}, | |
| ); | |
| export const getRegenerateScriptStatus = (projectId: number) => | |
| api.get<ProjectRegenerateScriptJob | null>( | |
| `/projects/${projectId}/regenerate-script-status` | |
| ); | |
| // Fetch the previous (pre-regeneration) scenes for the verify-step before/after comparison. | |
| export const getRegenerateScriptPreview = (projectId: number) => | |
| api.get<RegenerateScriptPreviewOut>( | |
| `/projects/${projectId}/regenerate-script/preview` | |
| ); | |
| // Approve the regenerated script (paused at the verify step) and resume scene generation. | |
| export const verifyRegenerateScript = (projectId: number) => | |
| api.post<ProjectRegenerateScriptJob>( | |
| `/projects/${projectId}/regenerate-script/verify`, | |
| {}, | |
| ); | |
| // Discard the regenerated script and re-run it, optionally with a modified instruction. | |
| export const rejectRegenerateScript = ( | |
| projectId: number, | |
| body?: { user_instruction?: string }, | |
| ) => | |
| api.post<ProjectRegenerateScriptJob>( | |
| `/projects/${projectId}/regenerate-script/regenerate`, | |
| body ?? {}, | |
| ); | |
| export const updateScene = ( | |
| projectId: number, | |
| sceneId: number, | |
| data: Partial<Scene> | |
| ) => api.put<Scene>(`/projects/${projectId}/scenes/${sceneId}`, data); | |
| export const deleteScene = (projectId: number, sceneId: number) => | |
| api.delete(`/projects/${projectId}/scenes/${sceneId}`); | |
| export const launchStudio = (id: number) => | |
| api.post<StudioResponse>(`/projects/${id}/launch-studio`); | |
| export const renderVideo = (id: number, resolution: string = "720p") => | |
| api.post(`/projects/${id}/render?resolution=${resolution}`); | |
| export const getRenderStatus = (id: number) => | |
| api.get<RenderStatus>(`/projects/${id}/render-status`); | |
| export const downloadVideo = async (id: number, filename?: string) => { | |
| const urlRes = await api.get<{ url: string }>(`/projects/${id}/download-url`); | |
| const videoUrl = urlRes.data.url; | |
| // Fetch the video as a blob so the download works even with popup blockers. | |
| // Using fetch() directly (not axios) because the URL may be a cross-origin R2 URL. | |
| const resp = await fetch(videoUrl); | |
| if (!resp.ok) throw new Error(`Download failed (${resp.status})`); | |
| const blob = await resp.blob(); | |
| const blobUrl = window.URL.createObjectURL(blob); | |
| const a = document.createElement("a"); | |
| a.href = blobUrl; | |
| a.download = filename || "video.mp4"; | |
| document.body.appendChild(a); | |
| a.click(); | |
| a.remove(); | |
| window.URL.revokeObjectURL(blobUrl); | |
| }; | |
| export const downloadStudioZip = async (id: number, filename?: string) => { | |
| const res = await api.get(`/projects/${id}/download-studio`, { | |
| responseType: "blob", | |
| }); | |
| const url = window.URL.createObjectURL(new Blob([res.data])); | |
| const a = document.createElement("a"); | |
| a.href = url; | |
| a.download = filename || "studio_project.zip"; | |
| document.body.appendChild(a); | |
| a.click(); | |
| a.remove(); | |
| window.URL.revokeObjectURL(url); | |
| }; | |
| export const sendChatMessage = (id: number, message: string) => | |
| api.post<ChatResponse>(`/projects/${id}/chat`, { message }); | |
| export const getChatHistory = (id: number) => | |
| api.get<ChatMessage[]>(`/projects/${id}/chat/history`); | |