File size: 2,828 Bytes
9a42933 7448744 6c5a5b1 7448744 827f345 9a42933 8f35fb6 7448744 a9e45ba 6c5a5b1 9a42933 7448744 8bc9511 7448744 9a42933 827f345 7448744 8bc9511 7448744 6c5a5b1 7448744 6c5a5b1 b56210f 9a42933 6c5a5b1 7448744 6c5a5b1 5c5e659 a9e45ba 5c5e659 7448744 5c5e659 a9e45ba 7448744 5c5e659 9a42933 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
"use server"
import { VideoOptions } from "@/types"
import { generateVideoWithGradioAPI } from "./generateWithGradioApi"
import { generateVideoWithReplicateAPI } from "./generateWithReplicateAPI"
import { filterOutBadWords } from "./censorship"
const videoEngine = `${process.env.VIDEO_ENGINE || ""}`
// const officialApi = `${process.env.VIDEO_HOTSHOT_XL_API_OFFICIAL || ""}`
const nodeApi = `${process.env.VIDEO_HOTSHOT_XL_API_NODE || ""}`
export async function generateAnimation({
positivePrompt = "",
negativePrompt = "",
size = "512x512",
huggingFaceLora,
replicateLora,
triggerWord,
nbFrames = 8,
duration = 1000,
steps = 30,
}: VideoOptions): Promise<string> {
if (!positivePrompt?.length) {
throw new Error(`prompt is too short!`)
}
positivePrompt = filterOutBadWords(positivePrompt)
// pimp the prompt
positivePrompt = [
triggerWord,
positivePrompt,
"beautiful",
"hd"
].join(", ")
negativePrompt = [
negativePrompt,
"cropped",
"dark",
"underexposed",
"overexposed",
"watermark",
"watermarked",
].join(", ")
try {
if (videoEngine === "VIDEO_HOTSHOT_XL_API_REPLICATE") {
return generateVideoWithReplicateAPI({
positivePrompt,
negativePrompt,
size,
huggingFaceLora,
replicateLora,
nbFrames,
duration,
steps,
})
} else if (videoEngine === "VIDEO_HOTSHOT_XL_API_NODE") {
// TODO: support other API to avoid duplicate work?
// (are the other API supporting custom LoRAs?)
const res = await fetch(nodeApi, {
method: "POST",
headers: {
"Content-Type": "application/json",
// access isn't secured for now, the free lunch is open
// Authorization: `Bearer ${token}`,
},
body: JSON.stringify({
prompt: positivePrompt,
lora: huggingFaceLora,
size,
}),
cache: "no-store",
// we can also use this (see https://vercel.com/blog/vercel-cache-api-nextjs-cache)
// next: { revalidate: 1 }
})
const content = await res.text()
// Recommendation: handle errors
if (res.status !== 200) {
console.error(content)
// This will activate the closest `error.js` Error Boundary
throw new Error('Failed to fetch data')
}
return content
} else if (videoEngine === "VIDEO_HOTSHOT_XL_API_GRADIO") {
return generateVideoWithGradioAPI({
positivePrompt,
negativePrompt,
size,
huggingFaceLora,
replicateLora,
nbFrames,
duration,
steps,
})
} else {
throw new Error(`not implemented yet!`)
}
} catch (err) {
throw new Error(`failed to generate the image ${err}`)
}
} |