jbilcke-hf HF staff commited on
Commit
01c8568
1 Parent(s): cd7b7cc

preparing the code for interactivityg

Browse files
src/app/main.tsx CHANGED
@@ -2,7 +2,7 @@
2
 
3
  import { useEffect, useRef, useState, useTransition } from "react"
4
 
5
- import { VideoPlayer } from "@/components/business/video-player"
6
 
7
  import {
8
  Select,
@@ -44,7 +44,7 @@ export default function Main() {
44
 
45
  []
46
  // note: using actionnables will add +30sec to the query
47
- // scene.actionnables
48
  )
49
 
50
  if (type !== ref?.current) {
@@ -54,9 +54,9 @@ export default function Main() {
54
  }
55
 
56
 
57
- if (rendered.videoUrl) {
58
  // console.log(`got a new url: ${newUrl}`)
59
- setUrl(rendered.videoUrl)
60
  setScene(scene)
61
  setSegments(rendered.segments)
62
  setTimeout(() => { updateView()}, 1000)
@@ -106,7 +106,7 @@ export default function Main() {
106
  </div>)}
107
  </div>
108
  </div>
109
- <VideoPlayer url={url} />
110
  </div>
111
  )
112
  }
 
2
 
3
  import { useEffect, useRef, useState, useTransition } from "react"
4
 
5
+ import { VideoRenderer } from "@/components/business/video-renderer"
6
 
7
  import {
8
  Select,
 
44
 
45
  []
46
  // note: using actionnables will add +30sec to the query
47
+ // scene.actionnables.slice(0, 5) // too many can slow us down it seems
48
  )
49
 
50
  if (type !== ref?.current) {
 
54
  }
55
 
56
 
57
+ if (rendered.assetUrl) {
58
  // console.log(`got a new url: ${newUrl}`)
59
+ setUrl(rendered.assetUrl)
60
  setScene(scene)
61
  setSegments(rendered.segments)
62
  setTimeout(() => { updateView()}, 1000)
 
106
  </div>)}
107
  </div>
108
  </div>
109
+ <VideoRenderer url={url} />
110
  </div>
111
  )
112
  }
src/app/render.ts CHANGED
@@ -1,14 +1,14 @@
1
  "use server"
2
 
3
- import { RenderAPIResponse } from "./types"
4
 
5
  // note: there is no / at the end in the variable
6
  // so we have to add it ourselves if needed
7
  const apiUrl = process.env.RENDERING_ENGINE_API
8
 
9
  export async function render(prompt: string, actionnables: string[] = []) {
10
- let defaulResult: RenderAPIResponse = {
11
- videoUrl: "",
12
  maskBase64: "",
13
  error: "",
14
  segments: []
@@ -28,8 +28,8 @@ export async function render(prompt: string, actionnables: string[] = []) {
28
  // nbFrames: 8 and nbSteps: 15 --> ~10 sec generation
29
  nbFrames: 8,
30
  nbSteps: 20,
31
- segmentation: "firstframe",
32
  actionnables,
 
33
  }),
34
  cache: 'no-store',
35
  // we can also use this (see https://vercel.com/blog/vercel-cache-api-nextjs-cache)
@@ -46,7 +46,7 @@ export async function render(prompt: string, actionnables: string[] = []) {
46
  throw new Error('Failed to fetch data')
47
  }
48
 
49
- const response = (await res.json()) as RenderAPIResponse
50
  // console.log("response:", response)
51
  return response
52
  } catch (err) {
 
1
  "use server"
2
 
3
+ import { RenderedScene } from "./types"
4
 
5
  // note: there is no / at the end in the variable
6
  // so we have to add it ourselves if needed
7
  const apiUrl = process.env.RENDERING_ENGINE_API
8
 
9
  export async function render(prompt: string, actionnables: string[] = []) {
10
+ let defaulResult: RenderedScene = {
11
+ assetUrl: "",
12
  maskBase64: "",
13
  error: "",
14
  segments: []
 
28
  // nbFrames: 8 and nbSteps: 15 --> ~10 sec generation
29
  nbFrames: 8,
30
  nbSteps: 20,
 
31
  actionnables,
32
+ segmentation: "firstframe", // one day we will remove this param, to make it automatic
33
  }),
34
  cache: 'no-store',
35
  // we can also use this (see https://vercel.com/blog/vercel-cache-api-nextjs-cache)
 
46
  throw new Error('Failed to fetch data')
47
  }
48
 
49
+ const response = (await res.json()) as RenderedScene
50
  // console.log("response:", response)
51
  return response
52
  } catch (err) {
src/app/types.ts CHANGED
@@ -27,20 +27,13 @@ export interface RenderRequest {
27
  export interface ImageSegment {
28
  id: number
29
  box: number[]
 
30
  label: string
31
  score: number
32
  }
33
 
34
-
35
- export interface ImageSegment {
36
- id: number
37
- box: number[]
38
- label: string
39
- score: number
40
- }
41
-
42
- export interface RenderAPIResponse {
43
- videoUrl: string
44
  error: string
45
  maskBase64: string
46
  segments: ImageSegment[]
 
27
  export interface ImageSegment {
28
  id: number
29
  box: number[]
30
+ color: number[]
31
  label: string
32
  score: number
33
  }
34
 
35
+ export interface RenderedScene {
36
+ assetUrl: string
 
 
 
 
 
 
 
 
37
  error: string
38
  maskBase64: string
39
  segments: ImageSegment[]
src/components/business/image-renderer.tsx ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useRef } from "react"
2
+
3
+ import { ImageSegment, RenderedScene } from "@/app/types"
4
+
5
+ export const ImageRenderer = ({
6
+ assetUrl = "",
7
+ maskBase64 = "",
8
+ segments = []
9
+ }: RenderedScene) => {
10
+ const imgRef = useRef<HTMLImageElement | null>(null)
11
+ const canvas = document.createElement('canvas')
12
+ const context = canvas.getContext('2d')
13
+
14
+ const getPixelColor = (x: number, y: number) => {
15
+ console.log("getting pixel color")
16
+ if (!context) {
17
+ throw new Error("Unable to get context from canvas")
18
+ }
19
+
20
+ const imgData = context.getImageData(x, y, 1, 1).data
21
+
22
+ return `[${imgData[0]},${imgData[1]},${imgData[2]},${imgData[3]/255}]`
23
+ }
24
+
25
+ const handleMouseDown = (event: React.MouseEvent) => {
26
+ const boundingRect = imgRef.current!.getBoundingClientRect()
27
+
28
+ const x = event.clientX - boundingRect.left
29
+ const y = event.clientY - boundingRect.top
30
+
31
+ if (maskBase64) {
32
+ const image = new Image()
33
+
34
+ image.onload = function () {
35
+ if (context) {
36
+ context.drawImage(image, 0, 0)
37
+
38
+ const clickedColor = getPixelColor(x, y) as any
39
+
40
+ let closestSegment: ImageSegment | null = null
41
+
42
+ let minDistance = Infinity
43
+
44
+ segments.forEach(segment => {
45
+ const segmentColor = segment.color.slice(0,3) // get the RGB part only
46
+
47
+ const distance = Math.sqrt(
48
+ Math.pow(clickedColor[0] - segmentColor[0], 2) +
49
+ Math.pow(clickedColor[1] - segmentColor[1], 2) +
50
+ Math.pow(clickedColor[2] - segmentColor[2], 2)
51
+ )
52
+
53
+ if(distance < minDistance) {
54
+ minDistance = distance;
55
+ closestSegment = segment;
56
+ }
57
+ })
58
+
59
+ console.log("closestSegment:", closestSegment)
60
+ console.log(closestSegment) // Here is the closest matching segment
61
+ }
62
+ }
63
+
64
+ image.src = maskBase64
65
+ // image.src = "data:image/png;base64," + maskBase64;
66
+ } else {
67
+ console.log("No mask available, aborting..")
68
+ }
69
+ }
70
+
71
+
72
+ if (!assetUrl) {
73
+ return <div className="flex w-full h-screen items-center justify-center text-center">
74
+ <div>Rendering first frame.. (might take around 30s)</div>
75
+ </div>
76
+ }
77
+
78
+ return (
79
+ <div className="w-full py-8 px-2">
80
+ <img
81
+ src={assetUrl}
82
+ ref={imgRef}
83
+ className="w-full rounded-md overflow-hidden"
84
+ onMouseDown={handleMouseDown}
85
+ />
86
+ </div>
87
+ )
88
+ }
src/components/business/{video-player.tsx → video-renderer.tsx} RENAMED
@@ -1,10 +1,10 @@
1
  "use client"
2
 
3
- export const VideoPlayer = ({ url }: { url?: string }) => {
4
 
5
  if (!url) {
6
  return <div className="flex w-full h-screen items-center justify-center text-center">
7
- <div>Rendering first scene (might take ~1 min)</div>
8
  </div>
9
  }
10
 
 
1
  "use client"
2
 
3
+ export const VideoRenderer = ({ url }: { url?: string }) => {
4
 
5
  if (!url) {
6
  return <div className="flex w-full h-screen items-center justify-center text-center">
7
+ <div>Rendering first frames.. (might take around 30s)</div>
8
  </div>
9
  }
10