|
"use client" |
|
|
|
import { ClapProject, parseClap, serializeClap, ClapMediaOrientation } from "@aitube/clap" |
|
import { create } from "zustand" |
|
|
|
import { GlobalStatus, TaskStatus } from "@/types" |
|
import { getVideoOrientation } from "@/lib/utils/getVideoOrientation" |
|
|
|
import { RESOLUTION_LONG, RESOLUTION_SHORT } from "./server/aitube/config" |
|
|
|
export const useStore = create<{ |
|
mainCharacterImage: string |
|
mainCharacterVoice: string |
|
storyPromptDraft: string |
|
storyPrompt: string |
|
|
|
|
|
|
|
orientation: ClapMediaOrientation |
|
|
|
status: GlobalStatus |
|
parseGenerationStatus: TaskStatus |
|
storyGenerationStatus: TaskStatus |
|
assetGenerationStatus: TaskStatus |
|
voiceGenerationStatus: TaskStatus |
|
imageGenerationStatus: TaskStatus |
|
videoGenerationStatus: TaskStatus |
|
currentClap?: ClapProject |
|
currentVideo: string |
|
|
|
|
|
|
|
currentVideoOrientation: ClapMediaOrientation |
|
progress: number |
|
error: string |
|
toggleOrientation: () => void |
|
setCurrentVideoOrientation: (currentVideoOrientation: ClapMediaOrientation) => void |
|
setMainCharacterImage: (mainCharacterImage: string) => void |
|
setMainCharacterVoice: (mainCharacterVoice: string) => void |
|
setStoryPromptDraft: (storyPromptDraft: string) => void |
|
setStoryPrompt: (storyPrompt: string) => void |
|
setStatus: (status: GlobalStatus) => void |
|
setParseGenerationStatus: (parseGenerationStatus: TaskStatus) => void |
|
setStoryGenerationStatus: (storyGenerationStatus: TaskStatus) => void |
|
setAssetGenerationStatus: (assetGenerationStatus: TaskStatus) => void |
|
setVoiceGenerationStatus: (voiceGenerationStatus: TaskStatus) => void |
|
setImageGenerationStatus: (imageGenerationStatus: TaskStatus) => void |
|
setVideoGenerationStatus: (videoGenerationStatus: TaskStatus) => void |
|
setCurrentClap: (currentClap?: ClapProject) => void |
|
|
|
|
|
setGeneratedVideo: (generatedVideo: string) => Promise<void> |
|
|
|
setProgress: (progress: number) => void |
|
setError: (error: string) => void |
|
saveClap: () => Promise<void> |
|
loadClap: (blob: Blob, fileName?: string) => Promise<ClapProject> |
|
}>((set, get) => ({ |
|
mainCharacterImage: "", |
|
mainCharacterVoice: "", |
|
storyPromptDraft: "Yesterday I was at my favorite pizza place and..", |
|
storyPrompt: "", |
|
orientation: ClapMediaOrientation.PORTRAIT, |
|
status: "idle", |
|
parseGenerationStatus: "idle", |
|
storyGenerationStatus: "idle", |
|
assetGenerationStatus: "idle", |
|
voiceGenerationStatus: "idle", |
|
imageGenerationStatus: "idle", |
|
videoGenerationStatus: "idle", |
|
currentClap: undefined, |
|
currentVideo: "", |
|
currentVideoOrientation: ClapMediaOrientation.PORTRAIT, |
|
progress: 0, |
|
error: "", |
|
toggleOrientation: () => { |
|
const { orientation: previousOrientation, currentVideoOrientation, currentVideo } = get() |
|
const orientation = |
|
previousOrientation === ClapMediaOrientation.LANDSCAPE |
|
? ClapMediaOrientation.PORTRAIT |
|
: ClapMediaOrientation.LANDSCAPE |
|
|
|
set({ |
|
orientation, |
|
|
|
|
|
currentVideoOrientation: |
|
currentVideo |
|
? currentVideoOrientation |
|
: orientation |
|
}) |
|
}, |
|
setCurrentVideoOrientation: (currentVideoOrientation: ClapMediaOrientation) => { set({ currentVideoOrientation }) }, |
|
setMainCharacterImage: (mainCharacterImage: string) => { set({ mainCharacterImage }) }, |
|
setMainCharacterVoice: (mainCharacterVoice: string) => { set({ mainCharacterVoice }) }, |
|
setStoryPromptDraft: (storyPromptDraft: string) => { set({ storyPromptDraft }) }, |
|
setStoryPrompt: (storyPrompt: string) => { set({ storyPrompt }) }, |
|
setStatus: (status: GlobalStatus) => { set({ status }) }, |
|
setParseGenerationStatus: (parseGenerationStatus: TaskStatus) => { set({ parseGenerationStatus }) }, |
|
setStoryGenerationStatus: (storyGenerationStatus: TaskStatus) => { set({ storyGenerationStatus }) }, |
|
setAssetGenerationStatus: (assetGenerationStatus: TaskStatus) => { set({ assetGenerationStatus }) }, |
|
setVoiceGenerationStatus: (voiceGenerationStatus: TaskStatus) => { set({ voiceGenerationStatus }) }, |
|
setImageGenerationStatus: (imageGenerationStatus: TaskStatus) => { set({ imageGenerationStatus }) }, |
|
setVideoGenerationStatus: (videoGenerationStatus: TaskStatus) => { set({ videoGenerationStatus }) }, |
|
setCurrentClap: (currentClap?: ClapProject) => { set({ currentClap }) }, |
|
setGeneratedVideo: async (currentVideo: string): Promise<void> => { |
|
const currentVideoOrientation = await getVideoOrientation(currentVideo) |
|
set({ |
|
currentVideo, |
|
currentVideoOrientation |
|
|
|
}) |
|
}, |
|
setProgress: (progress: number) => { set({ progress }) }, |
|
setError: (error: string) => { set({ error }) }, |
|
saveClap: async (): Promise<void> => { |
|
const { currentClap , storyPrompt } = get() |
|
|
|
if (!currentClap) { throw new Error(`cannot save a clap.. if there is no clap`) } |
|
|
|
const currentClapBlob: Blob = await serializeClap(currentClap) |
|
|
|
|
|
const objectUrl = URL.createObjectURL(currentClapBlob) |
|
|
|
|
|
const anchor = document.createElement("a") |
|
anchor.href = objectUrl |
|
|
|
const firstPartOfStoryPrompt = storyPrompt |
|
|
|
const cleanStoryPrompt = firstPartOfStoryPrompt.replace(/([^a-z0-9, ]+)/gi, "_") |
|
|
|
const cleanName = `${cleanStoryPrompt.slice(0, 50)}` |
|
|
|
anchor.download = `${cleanName}.clap` |
|
|
|
document.body.appendChild(anchor) |
|
anchor.click() |
|
|
|
|
|
URL.revokeObjectURL(objectUrl) |
|
document.body.removeChild(anchor) |
|
}, |
|
loadClap: async (blob: Blob, fileName: string = "untitled_story.clap"): Promise<ClapProject> => { |
|
if (!blob) { |
|
throw new Error(`missing blob`) |
|
} |
|
|
|
const currentClap: ClapProject | undefined = await parseClap(blob) |
|
|
|
if (!currentClap) { throw new Error(`failed to import the clap`) } |
|
|
|
|
|
const storyPrompt = currentClap.meta.description.split("||").pop() || "" |
|
|
|
|
|
|
|
|
|
const { orientation } = get() |
|
|
|
currentClap.meta.height = orientation === ClapMediaOrientation.LANDSCAPE ? RESOLUTION_SHORT : RESOLUTION_LONG |
|
currentClap.meta.width = orientation === ClapMediaOrientation.PORTRAIT ? RESOLUTION_SHORT : RESOLUTION_LONG |
|
|
|
set({ |
|
currentClap, |
|
storyPrompt, |
|
storyPromptDraft: storyPrompt, |
|
orientation, |
|
currentVideoOrientation: orientation, |
|
}) |
|
|
|
return currentClap |
|
}, |
|
})) |