jbilcke-hf HF staff commited on
Commit
e0c4dc2
·
1 Parent(s): 9f14b6c

ok, I think it works now

Browse files
src/app/engine/render.ts CHANGED
@@ -2,7 +2,7 @@
2
 
3
 
4
 
5
- import { RenderedScene } from "@/types"
6
  import { Engine, EngineType } from "./engines"
7
 
8
  // note: there is no / at the end in the variable
@@ -15,10 +15,12 @@ export async function newRender({
15
  prompt,
16
  actionnables = [],
17
  engine,
 
18
  }: {
19
  prompt: string
20
  actionnables: string[]
21
  engine: Engine
 
22
  }) {
23
  if (!prompt) {
24
  console.error(`cannot call the rendering API without a prompt, aborting..`)
@@ -31,8 +33,6 @@ export async function newRender({
31
 
32
  const nbFrames = engine.type.includes("video") ? 8 : 1
33
 
34
- const cacheKey = `render/${JSON.stringify({ prompt, actionnables, nbFrames, type: engine.type })}`
35
-
36
  // return await Gorgon.get(cacheKey, async () => {
37
 
38
  let defaulResult: RenderedScene = {
@@ -49,18 +49,24 @@ export async function newRender({
49
 
50
  const isForVideo = nbFrames > 1
51
 
52
-
53
- console.log("REQUEST:", JSON.stringify({
54
- prompt,
55
- // nbFrames: 8 and nbSteps: 15 --> ~10 sec generation
56
- nbFrames, // when nbFrames is 1, we will only generate static images
57
- nbSteps: isForVideo ? 25 : 35, // 20 = fast, 30 = better, 50 = best
58
- actionnables,
59
- segmentation: "firstframe", // one day we will remove this param, to make it automatic
60
- width: isForVideo ? 576 : 1024,
61
- height: isForVideo ? 320 : 512,
62
- }))
63
-
 
 
 
 
 
 
64
  const res = await fetch(`${apiUrl}/render`, {
65
  method: "POST",
66
  headers: {
@@ -68,16 +74,7 @@ export async function newRender({
68
  "Content-Type": "application/json",
69
  // Authorization: `Bearer ${process.env.VC_SECRET_ACCESS_TOKEN}`,
70
  },
71
- body: JSON.stringify({
72
- prompt,
73
- // nbFrames: 8 and nbSteps: 15 --> ~10 sec generation
74
- nbFrames, // when nbFrames is 1, we will only generate static images
75
- nbSteps: isForVideo ? 30 : 35, // 20 = fast, 30 = better, 50 = best
76
- actionnables,
77
- segmentation: "firstframe", // one day we will remove this param, to make it automatic
78
- width: isForVideo ? 576 : 1024,
79
- height: isForVideo ? 320 : 768,
80
- }),
81
  cache: 'no-store',
82
  // we can also use this (see https://vercel.com/blog/vercel-cache-api-nextjs-cache)
83
  // next: { revalidate: 1 }
 
2
 
3
 
4
 
5
+ import { RenderRequest, RenderedScene } from "@/types"
6
  import { Engine, EngineType } from "./engines"
7
 
8
  // note: there is no / at the end in the variable
 
15
  prompt,
16
  actionnables = [],
17
  engine,
18
+ clearCache,
19
  }: {
20
  prompt: string
21
  actionnables: string[]
22
  engine: Engine
23
+ clearCache: boolean
24
  }) {
25
  if (!prompt) {
26
  console.error(`cannot call the rendering API without a prompt, aborting..`)
 
33
 
34
  const nbFrames = engine.type.includes("video") ? 8 : 1
35
 
 
 
36
  // return await Gorgon.get(cacheKey, async () => {
37
 
38
  let defaulResult: RenderedScene = {
 
49
 
50
  const isForVideo = nbFrames > 1
51
 
52
+ const request = {
53
+ prompt,
54
+ // nbFrames: 8 and nbSteps: 15 --> ~10 sec generation
55
+ nbFrames, // when nbFrames is 1, we will only generate static images
56
+ nbSteps: isForVideo ? 30 : 35, // 20 = fast, 30 = better, 50 = best
57
+ actionnables,
58
+ segmentation: "firstframe", // one day we will remove this param, to make it automatic
59
+ width: isForVideo ? 576 : 1024,
60
+ height: isForVideo ? 320 : 768,
61
+
62
+ // note that we never disable the cache completely for VideoQuest
63
+ // that's because in the feedbacks people prefer speed to avoid frustration
64
+ cache: clearCache ? "renew" : "use",
65
+
66
+ } as Partial<RenderRequest>
67
+
68
+ console.table(request)
69
+
70
  const res = await fetch(`${apiUrl}/render`, {
71
  method: "POST",
72
  headers: {
 
74
  "Content-Type": "application/json",
75
  // Authorization: `Bearer ${process.env.VC_SECRET_ACCESS_TOKEN}`,
76
  },
77
+ body: JSON.stringify(request),
 
 
 
 
 
 
 
 
 
78
  cache: 'no-store',
79
  // we can also use this (see https://vercel.com/blog/vercel-cache-api-nextjs-cache)
80
  // next: { revalidate: 1 }
src/app/games/vernian.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { imfell } from "@/lib/fonts"
2
  import { Game } from "./types"
3
  import { InventoryItem } from "../../types"
4
 
@@ -79,7 +79,7 @@ export const game: Game = {
79
  "cartesian_video",
80
  "spherical_image",
81
  ],
82
- className: imfell.className,
83
  initialSituation,
84
  initialActionnables,
85
  inventory,
 
1
+ import { moondance } from "@/lib/fonts"
2
  import { Game } from "./types"
3
  import { InventoryItem } from "../../types"
4
 
 
79
  "cartesian_video",
80
  "spherical_image",
81
  ],
82
+ className: moondance.className,
83
  initialSituation,
84
  initialActionnables,
85
  inventory,
src/app/interface/top-menu/index.tsx CHANGED
@@ -19,18 +19,23 @@ export function TopMenu({
19
  engine,
20
  defaultGame,
21
  game,
 
 
22
  onChangeEngine,
23
  onChangeGame,
24
  onToggleDebug,
25
- debug,
26
  }: {
27
  engine: Engine,
28
  defaultGame: string
29
  game: Game
 
 
30
  onChangeEngine: (newEngine: EngineType) => void
31
  onChangeGame: (newGameType: GameType) => void
32
  onToggleDebug: (isToggledOn: boolean) => void
33
- debug: boolean
 
34
  }) {
35
  return (
36
  <div className={cn(
@@ -65,7 +70,14 @@ export function TopMenu({
65
  <Label>Debug</Label>
66
  </div>
67
  <div className="flex flex-row items-center space-x-3 font-mono">
68
- <Label className="flex text-sm">Rendering engine:</Label>
 
 
 
 
 
 
 
69
  <Select
70
  defaultValue={game.engines.includes(engine.type) ? engine.type : game.engines[0]}
71
  onValueChange={(value) => { onChangeEngine(value as EngineType) }}>
 
19
  engine,
20
  defaultGame,
21
  game,
22
+ debug,
23
+ clearCache,
24
  onChangeEngine,
25
  onChangeGame,
26
  onToggleDebug,
27
+ onToggleClearCache,
28
  }: {
29
  engine: Engine,
30
  defaultGame: string
31
  game: Game
32
+ debug: boolean
33
+ clearCache: boolean
34
  onChangeEngine: (newEngine: EngineType) => void
35
  onChangeGame: (newGameType: GameType) => void
36
  onToggleDebug: (isToggledOn: boolean) => void
37
+ onToggleClearCache: (shouldClearCache: boolean) => void
38
+
39
  }) {
40
  return (
41
  <div className={cn(
 
70
  <Label>Debug</Label>
71
  </div>
72
  <div className="flex flex-row items-center space-x-3 font-mono">
73
+ <Switch
74
+ checked={clearCache}
75
+ onCheckedChange={onToggleClearCache}
76
+ />
77
+ <Label>No cache</Label>
78
+ </div>
79
+ <div className="flex flex-row items-center space-x-3 font-mono">
80
+ <Label className="flex text-sm">Engine:</Label>
81
  <Select
82
  defaultValue={game.engines.includes(engine.type) ? engine.type : game.engines[0]}
83
  onValueChange={(value) => { onChangeEngine(value as EngineType) }}>
src/app/main.tsx CHANGED
@@ -55,6 +55,9 @@ export default function Main() {
55
  const requestedDebug = (searchParams.get('debug') === "true")
56
  const [debug, setDebug] = useState<boolean>(requestedDebug)
57
 
 
 
 
58
  const [situation, setSituation] = useState("")
59
 
60
  const [dialogue, setDialogue] = useState("")
@@ -91,10 +94,10 @@ export default function Main() {
91
  Array.isArray(nextActionnables) && nextActionnables.length
92
  ? nextActionnables
93
  : game.initialActionnables
94
- )
95
- })
96
 
97
- console.log("got the first version of our scene!", newRendered)
 
98
 
99
  // detect if type game type changed while we were busy
100
  // note that currently we reload the whol page when tha happens,
@@ -102,15 +105,25 @@ export default function Main() {
102
  if (game?.type !== gameRef?.current) {
103
  console.log("game type changed! aborting..")
104
  return
 
 
 
105
 
 
 
 
 
 
 
 
106
  }
107
- // we cheat a bit by displaying the previous image as a placeholder
108
- // this is better than displaying a blank image!
109
- newRendered.assetUrl = rendered.assetUrl
110
- newRendered.maskUrl = rendered.maskUrl
111
 
112
  historyRef.current.unshift(newRendered)
113
  setRendered(newRendered)
 
 
 
 
114
  })
115
  }
116
 
@@ -121,7 +134,7 @@ export default function Main() {
121
  if (!historyRef.current[0]?.renderId || historyRef.current[0]?.status !== "pending") {
122
 
123
  // console.log("let's try again in a moments")
124
- loopRef.current = setTimeout(() => checkRenderedLoop(), 200)
125
  return
126
  }
127
 
@@ -255,6 +268,23 @@ export default function Main() {
255
  setDebug(isToggledOn)
256
  }
257
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  const handleSelectGame = (newGameType: GameType) => {
259
  gameRef.current = newGameType
260
  setGame(getGame(newGameType))
@@ -412,10 +442,12 @@ export default function Main() {
412
  engine={engine}
413
  game={game}
414
  defaultGame={gameRef.current}
 
 
415
  onToggleDebug={handleToggleDebug}
416
  onChangeGame={handleSelectGame}
417
  onChangeEngine={handleSelectEngine}
418
- debug={debug}
419
  />
420
 
421
  <DndProvider backend={HTML5Backend}>
 
55
  const requestedDebug = (searchParams.get('debug') === "true")
56
  const [debug, setDebug] = useState<boolean>(requestedDebug)
57
 
58
+ const requestedClearCache = (searchParams.get('clearCache') ? (searchParams.get('clearCache') === "true") : false)
59
+ const [clearCache, setClearCache] = useState<boolean>(requestedClearCache)
60
+
61
  const [situation, setSituation] = useState("")
62
 
63
  const [dialogue, setDialogue] = useState("")
 
94
  Array.isArray(nextActionnables) && nextActionnables.length
95
  ? nextActionnables
96
  : game.initialActionnables
97
+ ),
 
98
 
99
+ clearCache
100
+ })
101
 
102
  // detect if type game type changed while we were busy
103
  // note that currently we reload the whol page when tha happens,
 
105
  if (game?.type !== gameRef?.current) {
106
  console.log("game type changed! aborting..")
107
  return
108
+ }
109
+
110
+ console.log("got the first version of our scene!", newRendered)
111
 
112
+ // in cache we didn't hit the cache and the request is still pending
113
+ // we cheat a bit by displaying the previous image as a placeholder
114
+ if (!newRendered.assetUrl && rendered.assetUrl && rendered.maskUrl) {
115
+ console.log("image is not in cache, using previous image as a placeholder..")
116
+ // this is better than displaying a blank image, no?
117
+ newRendered.assetUrl = rendered.assetUrl
118
+ newRendered.maskUrl = rendered.maskUrl
119
  }
 
 
 
 
120
 
121
  historyRef.current.unshift(newRendered)
122
  setRendered(newRendered)
123
+
124
+ if (newRendered.status === "completed") {
125
+ setBusy(busyRef.current = false)
126
+ }
127
  })
128
  }
129
 
 
134
  if (!historyRef.current[0]?.renderId || historyRef.current[0]?.status !== "pending") {
135
 
136
  // console.log("let's try again in a moments")
137
+ loopRef.current = setTimeout(() => checkRenderedLoop(), 1000)
138
  return
139
  }
140
 
 
268
  setDebug(isToggledOn)
269
  }
270
 
271
+ const handleToggleClearCache = (shouldClearCache: boolean) => {
272
+ const current = new URLSearchParams(Array.from(searchParams.entries()))
273
+ current.set("clearCache", `${shouldClearCache}`)
274
+ const search = current.toString()
275
+ const query = search ? `?${search}` : ""
276
+
277
+ // for some reason, this doesn't work?!
278
+ router.replace(`${pathname}${query}`, { })
279
+
280
+ // workaround.. but it is strange that router.replace doesn't work..
281
+ let newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' + search.toString()
282
+ window.history.pushState({path: newurl}, '', newurl)
283
+
284
+ setClearCache(shouldClearCache)
285
+ }
286
+
287
+
288
  const handleSelectGame = (newGameType: GameType) => {
289
  gameRef.current = newGameType
290
  setGame(getGame(newGameType))
 
442
  engine={engine}
443
  game={game}
444
  defaultGame={gameRef.current}
445
+ debug={debug}
446
+ clearCache={clearCache}
447
  onToggleDebug={handleToggleDebug}
448
  onChangeGame={handleSelectGame}
449
  onChangeEngine={handleSelectEngine}
450
+ onToggleClearCache={handleToggleClearCache}
451
  />
452
 
453
  <DndProvider backend={HTML5Backend}>
src/lib/fonts.ts CHANGED
@@ -1,4 +1,12 @@
1
- import { Inter, Edu_SA_Beginner, Orbitron, Amatic_SC, Macondo_Swash_Caps, IM_Fell_English_SC } from "next/font/google"
 
 
 
 
 
 
 
 
2
  import localFont from "next/font/local"
3
 
4
  export const inter = Inter({
@@ -11,6 +19,13 @@ export const edu = Edu_SA_Beginner({
11
  variable: "--font-edu",
12
  })
13
 
 
 
 
 
 
 
 
14
  export const orbitron = Orbitron({
15
  subsets: ["latin"],
16
  variable: "--font-orbitron",
 
1
+ import {
2
+ Inter,
3
+ Edu_SA_Beginner,
4
+ Orbitron,
5
+ Amatic_SC,
6
+ Macondo_Swash_Caps,
7
+ IM_Fell_English_SC,
8
+ Moon_Dance
9
+ } from "next/font/google"
10
  import localFont from "next/font/local"
11
 
12
  export const inter = Inter({
 
19
  variable: "--font-edu",
20
  })
21
 
22
+ export const moondance = Moon_Dance({
23
+ subsets: ["latin"],
24
+ weight: "400",
25
+ variable: "--font-moondance",
26
+ })
27
+
28
+
29
  export const orbitron = Orbitron({
30
  subsets: ["latin"],
31
  variable: "--font-orbitron",
src/types.ts CHANGED
@@ -1,5 +1,7 @@
1
  export type ProjectionMode = 'cartesian' | 'spherical'
2
 
 
 
3
  export interface RenderRequest {
4
  prompt: string
5
 
@@ -28,6 +30,8 @@ export interface RenderRequest {
28
  height: number // fixed at 512 for now
29
 
30
  projection: ProjectionMode
 
 
31
  }
32
 
33
  export interface ImageSegment {
 
1
  export type ProjectionMode = 'cartesian' | 'spherical'
2
 
3
+ export type CacheMode = "use" | "renew" | "ignore"
4
+
5
  export interface RenderRequest {
6
  prompt: string
7
 
 
30
  height: number // fixed at 512 for now
31
 
32
  projection: ProjectionMode
33
+
34
+ cache: CacheMode
35
  }
36
 
37
  export interface ImageSegment {