Spaces:
Sleeping
Sleeping
| import { NextResponse, NextRequest } from "next/server" | |
| import { createSecretKey } from "node:crypto" | |
| import { generateSeed } from "@aitube/clap" | |
| import queryString from "query-string" | |
| import { newRender, getRender } from "../../providers/videochain/renderWithVideoChain" | |
| import { sleep } from "@/lib/utils/sleep" | |
| import { getNegativePrompt, getPositivePrompt } from "../../utils/imagePrompts" | |
| import { getContentType } from "@/lib/data/getContentType" | |
| import { getValidNumber } from "@/lib/utils/getValidNumber" | |
| const secretKey = createSecretKey(`${process.env.API_SECRET_JWT_KEY || ""}`, 'utf-8'); | |
| export async function GET(req: NextRequest) { | |
| const qs = queryString.parseUrl(req.url || "") | |
| const query = (qs || {}).query | |
| /* | |
| TODO: check the validity of the JWT token | |
| let token = "" | |
| try { | |
| token = decodeURIComponent(query?.t?.toString() || "").trim() | |
| // verify token | |
| const { payload, protectedHeader } = await jwtVerify(token, secretKey, { | |
| issuer: `${process.env.API_SECRET_JWT_ISSUER || ""}`, // issuer | |
| audience: `${process.env.API_SECRET_JWT_AUDIENCE || ""}`, // audience | |
| }); | |
| // log values to console | |
| console.log(payload); | |
| console.log(protectedHeader); | |
| } catch (err) { | |
| // token verification failed | |
| console.log("Token is invalid"); | |
| return NextResponse.json({ error: `access denied ${err}` }, { status: 400 }); | |
| } | |
| */ | |
| let prompt = "" | |
| try { | |
| prompt = decodeURIComponent(query?.p?.toString() || "").trim() | |
| } catch (err) {} | |
| if (!prompt) { | |
| return NextResponse.json({ error: 'no prompt provided' }, { status: 400 }); | |
| } | |
| let width = 512 | |
| try { | |
| const rawString = decodeURIComponent(query?.w?.toString() || "").trim() | |
| width = getValidNumber(rawString, 256, 8192, 512) | |
| } catch (err) {} | |
| let height = 288 | |
| try { | |
| const rawString = decodeURIComponent(query?.h?.toString() || "").trim() | |
| height = getValidNumber(rawString, 256, 8192, 288) | |
| } catch (err) {} | |
| let format = "binary" | |
| try { | |
| const f = decodeURIComponent(query?.f?.toString() || "").trim() | |
| if (f === "json" || f === "binary") { format = f } | |
| } catch (err) {} | |
| // console.log("calling await newRender") | |
| prompt = getPositivePrompt(prompt) | |
| const negativePrompt = getNegativePrompt() | |
| let render = await newRender({ | |
| prompt, | |
| negativePrompt, | |
| nbFrames: 1, | |
| nbFPS: 1, | |
| nbSteps: 8, | |
| width, | |
| height, | |
| turbo: true, | |
| shouldRenewCache: true, | |
| seed: generateSeed() | |
| }) | |
| let attempts = 10 | |
| while (attempts-- > 0) { | |
| if (render.status === "completed") { | |
| if (format === "json") { | |
| return NextResponse.json(render, { | |
| status: 200, | |
| statusText: "OK", | |
| }) | |
| } else { | |
| const contentType = getContentType(render.assetUrl) | |
| const base64String = render.assetUrl.split(";base64,").pop() || "" | |
| const data = Buffer.from(base64String, "base64") | |
| const headers = new Headers() | |
| headers.set('Content-Type', contentType) | |
| return new NextResponse(data, { | |
| status: 200, | |
| statusText: "OK", | |
| headers | |
| }) | |
| } | |
| } | |
| if (render.status === "error") { | |
| return NextResponse.json(render, { | |
| status: 200, | |
| statusText: "OK", | |
| }) | |
| } | |
| await sleep(2000) // minimum wait time | |
| // console.log("asking getRender") | |
| render = await getRender(render.renderId) | |
| } | |
| return NextResponse.json({ | |
| "error": "failed to call VideoChain (timeout expired)" | |
| }, { | |
| status: 500, | |
| }) | |
| } | |