Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
Commit
β’
5b3357c
1
Parent(s):
95bbb7f
working on adding turbo
Browse files
.env
CHANGED
@@ -31,6 +31,9 @@ VC_SDXL_SPACE_API_URL="https://jbilcke-hf-image-server.hf.space"
|
|
31 |
#--------------------- LCM INFERENCE SERVERS ---------------------
|
32 |
VC_LCM_SPACE_API_URL="https://jbilcke-hf-fast-image-server.hf.space"
|
33 |
|
|
|
|
|
|
|
34 |
#----------------- ZEROSCOPE INFERENCE SERVERS -------------------
|
35 |
VC_ZEROSCOPE_SPACE_API_URL_1="https://jbilcke-hf-zeroscope-server-1.hf.space"
|
36 |
VC_ZEROSCOPE_SPACE_API_URL_2="https://jbilcke-hf-zeroscope-server-2.hf.space"
|
|
|
31 |
#--------------------- LCM INFERENCE SERVERS ---------------------
|
32 |
VC_LCM_SPACE_API_URL="https://jbilcke-hf-fast-image-server.hf.space"
|
33 |
|
34 |
+
#--------------------- SDXL TURBO INFERENCE SERVERS ---------------------
|
35 |
+
VC_SDXL_TURBO_SPACE_API_URL="https://jbilcke-hf-faster-image-server.hf.space"
|
36 |
+
|
37 |
#----------------- ZEROSCOPE INFERENCE SERVERS -------------------
|
38 |
VC_ZEROSCOPE_SPACE_API_URL_1="https://jbilcke-hf-zeroscope-server-1.hf.space"
|
39 |
VC_ZEROSCOPE_SPACE_API_URL_2="https://jbilcke-hf-zeroscope-server-2.hf.space"
|
src/production/renderImage.mts
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
import { generateImageLCMAsBase64 } from "../providers/image-generation/generateImageLCMGradio.mts"
|
|
|
2 |
import { generateImageSDXLAsBase64 } from "../providers/image-generation/generateImageSDXLGradio.mts"
|
3 |
import { generateImageSDXL360AsBase64 } from "../providers/image-generation/generateImageSDXL360.mts"
|
4 |
import { RenderedScene, RenderRequest } from "../types.mts"
|
@@ -10,10 +11,19 @@ export async function renderImage(
|
|
10 |
|
11 |
const isSpherical = request.projection === 'spherical'
|
12 |
|
|
|
|
|
|
|
13 |
const generateImageAsBase64 = isSpherical
|
14 |
? generateImageSDXL360AsBase64
|
15 |
: request.turbo
|
16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
: generateImageSDXLAsBase64
|
18 |
|
19 |
// console.log(`going to generate an image using ${request.projection || "default (cartesian)"} projection`)
|
|
|
1 |
import { generateImageLCMAsBase64 } from "../providers/image-generation/generateImageLCMGradio.mts"
|
2 |
+
import { generateImageSDXLTurboAsBase64 } from "../providers/image-generation/generateImageSDXLTurbo.mts"
|
3 |
import { generateImageSDXLAsBase64 } from "../providers/image-generation/generateImageSDXLGradio.mts"
|
4 |
import { generateImageSDXL360AsBase64 } from "../providers/image-generation/generateImageSDXL360.mts"
|
5 |
import { RenderedScene, RenderRequest } from "../types.mts"
|
|
|
11 |
|
12 |
const isSpherical = request.projection === 'spherical'
|
13 |
|
14 |
+
// we don't want to switch too much between model types in VideoChain,
|
15 |
+
// because for speed we need to pre-load the servers,
|
16 |
+
// but there is no point in pre-loading many servers for many models
|
17 |
const generateImageAsBase64 = isSpherical
|
18 |
? generateImageSDXL360AsBase64
|
19 |
: request.turbo
|
20 |
+
|
21 |
+
// turbo models are models that are slightly less beautiful
|
22 |
+
// but much, much faster to run
|
23 |
+
// for the moment we use SDXL + LCM, as it offers better scene coherence,
|
24 |
+
// but we might switch to SDXL Turbo in the future if its quality improves
|
25 |
+
? generateImageLCMAsBase64 // generateImageSDXLTurboAsBase64
|
26 |
+
|
27 |
: generateImageSDXLAsBase64
|
28 |
|
29 |
// console.log(`going to generate an image using ${request.projection || "default (cartesian)"} projection`)
|
src/production/renderVideo.mts
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
import { RenderedScene, RenderRequest } from "../types.mts"
|
2 |
-
|
|
|
|
|
3 |
|
4 |
export async function renderVideo(
|
5 |
request: RenderRequest,
|
|
|
1 |
import { RenderedScene, RenderRequest } from "../types.mts"
|
2 |
+
|
3 |
+
// import { generateVideo } from "../providers/video-generation/generateVideoWithZeroscope.mts"
|
4 |
+
import { generateVideo } from "../providers/video-generation/generateVideoWithHotshotGradioAPI.mts"
|
5 |
|
6 |
export async function renderVideo(
|
7 |
request: RenderRequest,
|
src/providers/image-generation/generateImageSDXLTurbo.mts
ADDED
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
import { client } from "@gradio/client"
|
3 |
+
|
4 |
+
import { generateSeed } from "../../utils/misc/generateSeed.mts"
|
5 |
+
import { getValidNumber } from "../../utils/validators/getValidNumber.mts"
|
6 |
+
import { convertToWebp } from "../../utils/image/convertToWebp.mts"
|
7 |
+
|
8 |
+
|
9 |
+
const instance = `${process.env.VC_SDXL_TURBO_SPACE_API_URL || ""}`
|
10 |
+
const secretToken = `${process.env.VC_MICROSERVICE_SECRET_TOKEN || ""}`
|
11 |
+
|
12 |
+
// console.log("DEBUG:", JSON.stringify({ instances, secretToken }, null, 2))
|
13 |
+
|
14 |
+
export async function generateImageSDXLTurboAsBase64(options: {
|
15 |
+
positivePrompt: string;
|
16 |
+
negativePrompt?: string;
|
17 |
+
seed?: number;
|
18 |
+
width?: number;
|
19 |
+
height?: number;
|
20 |
+
nbSteps?: number;
|
21 |
+
}): Promise<string> {
|
22 |
+
|
23 |
+
// console.log("querying " + instance)
|
24 |
+
const positivePrompt = options?.positivePrompt || ""
|
25 |
+
if (!positivePrompt) {
|
26 |
+
throw new Error("missing prompt")
|
27 |
+
}
|
28 |
+
|
29 |
+
// the negative prompt CAN be missing, since we use a trick
|
30 |
+
// where we make the interface mandatory in the TS doc,
|
31 |
+
// but browsers might send something partial
|
32 |
+
const negativePrompt = options?.negativePrompt || ""
|
33 |
+
|
34 |
+
// we treat 0 as meaning "random seed"
|
35 |
+
const seed = (options?.seed ? options.seed : 0) || generateSeed()
|
36 |
+
|
37 |
+
const maxRequestedResolution = 1024
|
38 |
+
const maxModelResolution = 512
|
39 |
+
|
40 |
+
const requestedWidth = getValidNumber(options?.width, 256, maxRequestedResolution, maxModelResolution)
|
41 |
+
const requestedHeight = getValidNumber(options?.height, 256, maxRequestedResolution, maxModelResolution)
|
42 |
+
|
43 |
+
// we try to preserve the original image ratio
|
44 |
+
const ratioH = requestedHeight / requestedWidth
|
45 |
+
const ratioW = requestedWidth / requestedHeight
|
46 |
+
|
47 |
+
// we always try to ccrank the resolution to the max
|
48 |
+
let width = ratioW < 1 ? Math.round(ratioW * maxModelResolution) : maxModelResolution
|
49 |
+
let height = ratioH < 1 ? Math.round(ratioH * maxModelResolution) : maxModelResolution
|
50 |
+
|
51 |
+
const positive = [
|
52 |
+
|
53 |
+
// oh well.. is it too late to move this to the bottom?
|
54 |
+
"beautiful",
|
55 |
+
|
56 |
+
// too opinionated, so let's remove it
|
57 |
+
// "intricate details",
|
58 |
+
|
59 |
+
positivePrompt,
|
60 |
+
|
61 |
+
"award winning",
|
62 |
+
"high resolution"
|
63 |
+
].filter(word => word)
|
64 |
+
.join(", ")
|
65 |
+
|
66 |
+
const negative = [
|
67 |
+
negativePrompt,
|
68 |
+
"watermark",
|
69 |
+
"copyright",
|
70 |
+
"blurry",
|
71 |
+
// "artificial",
|
72 |
+
// "cropped",
|
73 |
+
"low quality",
|
74 |
+
"ugly"
|
75 |
+
].filter(word => word)
|
76 |
+
.join(", ")
|
77 |
+
|
78 |
+
const api = await client(instance, {
|
79 |
+
hf_token: `${process.env.VC_HF_API_TOKEN}` as any
|
80 |
+
})
|
81 |
+
|
82 |
+
const rawResponse = (await api.predict("/run", [
|
83 |
+
positive, // string in 'Prompt' Textbox component
|
84 |
+
negative, // string in 'Negative prompt' Textbox component
|
85 |
+
seed, // number (numeric value between 0 and 2147483647) in 'Seed' Slider component
|
86 |
+
width, // number (numeric value between 256 and 1024) in 'Width' Slider component
|
87 |
+
height, // number (numeric value between 256 and 1024) in 'Height' Slider component
|
88 |
+
secretToken
|
89 |
+
])) as any
|
90 |
+
|
91 |
+
const result = rawResponse?.data?.[0] as string
|
92 |
+
if (!result?.length) {
|
93 |
+
throw new Error(`the returned image was empty`)
|
94 |
+
}
|
95 |
+
|
96 |
+
try {
|
97 |
+
const finalImage = await convertToWebp(result)
|
98 |
+
return finalImage
|
99 |
+
} catch (err) {
|
100 |
+
// console.log("err:", err)
|
101 |
+
throw new Error(err)
|
102 |
+
}
|
103 |
+
}
|