jbilcke-hf HF staff commited on
Commit
5fb05e6
Β·
1 Parent(s): 652f343

debugging the api..

Browse files
.gitignore CHANGED
@@ -3,7 +3,7 @@ node_modules
3
  *.bin
4
  .DS_Store
5
  .venv
6
- models/
7
- sandbox/
8
- audio.pipe
9
- video.pipe
 
3
  *.bin
4
  .DS_Store
5
  .venv
6
+ ./database/completed/*.json
7
+ ./database/pending/*.json
8
+ *.mp4
9
+ sandbox
src/database/constants.mts CHANGED
@@ -1,3 +1,6 @@
1
 
2
  export const pendingTasksDirFilePath = './database/pending/'
3
  export const completedTasksDirFilePath = './database/completed/'
 
 
 
 
1
 
2
  export const pendingTasksDirFilePath = './database/pending/'
3
  export const completedTasksDirFilePath = './database/completed/'
4
+
5
+ export const shotFormatVersion = 1
6
+ export const sequenceFormatVersion = 1
src/index.mts CHANGED
@@ -3,7 +3,7 @@ import { createReadStream, promises as fs } from "fs"
3
  import express from "express"
4
 
5
  import { VideoTask, VideoSequenceRequest } from "./types.mts"
6
- import { requestToTask } from "./services/requestToTask.mts"
7
  import { savePendingTask } from "./database/savePendingTask.mts"
8
  import { getTask } from "./database/getTask.mts"
9
  import { main } from "./main.mts"
@@ -31,7 +31,7 @@ app.post("/", async (req, res) => {
31
 
32
  console.log(`creating task from request..`)
33
  try {
34
- task = await requestToTask(request)
35
  } catch (err) {
36
  console.error(`failed to create task: ${task}`)
37
  res.status(400)
@@ -79,18 +79,9 @@ app.get("/video/:id\.mp4", async (req, res) => {
79
  }
80
 
81
  let task: VideoTask = null
82
-
83
  try {
84
  task = await getTask(req.params.id)
85
  console.log("returning result to user..")
86
-
87
- const filePath = task.finalFilePath || task.tmpFilePath || ''
88
- if (!filePath) {
89
- res.status(400)
90
- res.write(JSON.stringify({ error: "video exists, but cannot be previewed yet" }))
91
- res.end()
92
- return
93
- }
94
  } catch (err) {
95
  res.status(404)
96
  res.write(JSON.stringify({ error: "this video doesn't exist" }))
@@ -98,6 +89,15 @@ app.get("/video/:id\.mp4", async (req, res) => {
98
  return
99
  }
100
 
 
 
 
 
 
 
 
 
 
101
  // file path exists, let's try to read it
102
  try {
103
  // do we need this?
 
3
  import express from "express"
4
 
5
  import { VideoTask, VideoSequenceRequest } from "./types.mts"
6
+ import { parseVideoRequest } from "./utils/parseVideoRequest.mts"
7
  import { savePendingTask } from "./database/savePendingTask.mts"
8
  import { getTask } from "./database/getTask.mts"
9
  import { main } from "./main.mts"
 
31
 
32
  console.log(`creating task from request..`)
33
  try {
34
+ task = await parseVideoRequest(request)
35
  } catch (err) {
36
  console.error(`failed to create task: ${task}`)
37
  res.status(400)
 
79
  }
80
 
81
  let task: VideoTask = null
 
82
  try {
83
  task = await getTask(req.params.id)
84
  console.log("returning result to user..")
 
 
 
 
 
 
 
 
85
  } catch (err) {
86
  res.status(404)
87
  res.write(JSON.stringify({ error: "this video doesn't exist" }))
 
89
  return
90
  }
91
 
92
+
93
+ const filePath = task.finalFilePath || task.tmpFilePath || ''
94
+ if (!filePath) {
95
+ res.status(400)
96
+ res.write(JSON.stringify({ error: "video exists, but cannot be previewed yet" }))
97
+ res.end()
98
+ return
99
+ }
100
+
101
  // file path exists, let's try to read it
102
  try {
103
  // do we need this?
src/types.mts CHANGED
@@ -124,8 +124,6 @@ export interface VideoShotMeta {
124
  actorDialoguePrompt: string
125
 
126
  seed: number
127
- upscale: boolean
128
-
129
  noise: boolean // add movie noise
130
 
131
  durationMs: number // in milliseconds
@@ -133,7 +131,7 @@ export interface VideoShotMeta {
133
 
134
  fps: number // 8, 12, 24, 30, 60
135
 
136
- resolution: number // 256, 512, 576, 720, 1080
137
 
138
  introTransition: VideoTransition
139
  introDurationMs: number // in milliseconds
@@ -151,6 +149,10 @@ export interface VideoShotMeta {
151
 
152
 
153
  export interface VideoShotData {
 
 
 
 
154
  hasGeneratedVideo: boolean
155
  hasUpscaledVideo: boolean
156
  hasGeneratedBackgroundAudio: boolean
@@ -194,7 +196,6 @@ export interface VideoSequenceMeta {
194
  actorDialoguePrompt: string
195
 
196
  seed: number
197
- upscale: boolean
198
 
199
  noise: boolean // add movie noise
200
 
@@ -210,6 +211,10 @@ export interface VideoSequenceMeta {
210
 
211
 
212
  export interface VideoSequenceData {
 
 
 
 
213
  nbCompletedShots: number
214
  nbTotalShots: number
215
  progressPercent: number
 
124
  actorDialoguePrompt: string
125
 
126
  seed: number
 
 
127
  noise: boolean // add movie noise
128
 
129
  durationMs: number // in milliseconds
 
131
 
132
  fps: number // 8, 12, 24, 30, 60
133
 
134
+ resolution: string // {width}x{height} (256, 512, 576, 720, 1080)
135
 
136
  introTransition: VideoTransition
137
  introDurationMs: number // in milliseconds
 
149
 
150
 
151
  export interface VideoShotData {
152
+
153
+ // used to check compatibility
154
+ version: number
155
+
156
  hasGeneratedVideo: boolean
157
  hasUpscaledVideo: boolean
158
  hasGeneratedBackgroundAudio: boolean
 
196
  actorDialoguePrompt: string
197
 
198
  seed: number
 
199
 
200
  noise: boolean // add movie noise
201
 
 
211
 
212
 
213
  export interface VideoSequenceData {
214
+
215
+ // used to check compatibility
216
+ version: number
217
+
218
  nbCompletedShots: number
219
  nbTotalShots: number
220
  progressPercent: number
src/utils/parseShotRequest.mts ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { v4 as uuidv4 } from "uuid"
2
+
3
+ // convert a request (which might be invalid)
4
+
5
+ import { VideoSequence, VideoShot, VideoShotMeta } from "../types.mts"
6
+ import { generateSeed } from "../services/generateSeed.mts"
7
+ import { getValidNumber } from "./getValidNumber.mts"
8
+ import { shotFormatVersion } from "../database/constants.mts"
9
+
10
+ export const parseShotRequest = async (sequence: VideoSequence, maybeShotMeta: VideoShotMeta): Promise<VideoShot> => {
11
+
12
+ const shot: VideoShot = {
13
+ id: maybeShotMeta.id || uuidv4(),
14
+
15
+ shotPrompt: `${maybeShotMeta.shotPrompt || ""}`,
16
+
17
+ // describe the background audio (crowd, birds, wind, sea etc..)
18
+ backgroundAudioPrompt: `${maybeShotMeta.backgroundAudioPrompt || ""}`,
19
+
20
+ // describe the foreground audio (cars revving, footsteps, objects breaking, explosion etc)
21
+ foregroundAudioPrompt: `${maybeShotMeta.foregroundAudioPrompt || ""}`,
22
+
23
+ // describe the main actor visible in the shot (optional)
24
+ actorPrompt: `${maybeShotMeta.actorPrompt || ""}`,
25
+
26
+ // describe the main actor voice (man, woman, old, young, amused, annoyed.. etc)
27
+ actorVoicePrompt: `${maybeShotMeta.actorVoicePrompt || ""}`,
28
+
29
+ // describe the main actor dialogue line
30
+ actorDialoguePrompt: `${maybeShotMeta.actorDialoguePrompt || ""}`,
31
+
32
+ // a video sequence SHOULD NOT HAVE a consistent seed, to avoid weird geometry similarities
33
+ seed: getValidNumber(maybeShotMeta.seed, 0, 4294967295, generateSeed()),
34
+
35
+ // a video sequence SHOULD HAVE a consistent grain
36
+ noise: sequence.noise,
37
+
38
+ // a video sequence CAN HAVE inconsistent scene duration, like in any real movie
39
+ durationMs: getValidNumber(maybeShotMeta.durationMs, 0, 6000, 3000),
40
+
41
+ // a video sequence CAN HAVE inconsistent iteration steps
42
+ steps: getValidNumber(maybeShotMeta.steps || sequence.steps, 1, 60, 35),
43
+
44
+ // a video sequence MUST HAVE consistent frames per second
45
+ fps: getValidNumber(sequence.fps, 8, 60, 24),
46
+
47
+ // a video sequence MUST HAVE a consistent resolution
48
+ resolution: sequence.resolution,
49
+
50
+ // a video sequence CAN HAVE intro transitions for each shot
51
+ introTransition: 'fade',
52
+ introDurationMs: 500,
53
+
54
+ // for internal use
55
+
56
+ version: shotFormatVersion,
57
+ hasGeneratedVideo: false,
58
+ hasUpscaledVideo: false,
59
+ hasGeneratedBackgroundAudio: false,
60
+ hasGeneratedForegroundAudio: false,
61
+ hasGeneratedActor: false,
62
+ hasInterpolatedVideo: false,
63
+ hasAddedAudio: false,
64
+ hasPostProcessedVideo: false,
65
+ nbCompletedSteps: 0,
66
+
67
+ // 0. in queue
68
+ // 1. generate with Zeroscope
69
+ // 2. upscale with Zeroscope XL
70
+ // 3. interpolate with FILE
71
+ // 4. generate audio background
72
+ // 5. generate audio foreground
73
+ // 6. add audio to video
74
+ // 7. post-processing
75
+ nbTotalSteps: 7,
76
+ progressPercent: 0,
77
+ completedAt: '',
78
+ completed: false,
79
+ error: '',
80
+ tmpFilePath: '',
81
+ finalFilePath: '',
82
+ }
83
+
84
+ return shot
85
+ }
src/{services/requestToTask.mts β†’ utils/parseVideoRequest.mts} RENAMED
@@ -3,12 +3,14 @@ import { v4 as uuidv4 } from "uuid"
3
  // convert a request (which might be invalid)
4
 
5
  import { VideoSequenceRequest, VideoTask } from "../types.mts"
6
- import { generateSeed } from "./generateSeed.mts"
7
- import { getValidNumber } from "../utils/getValidNumber.mts"
8
- import { getValidResolution } from "../utils/getValidResolution.mts"
 
 
9
 
10
- // into a valid task
11
- export const requestToTask = async (request: VideoSequenceRequest): Promise<VideoTask> => {
12
 
13
  const task: VideoTask = {
14
  // ------------ VideoSequenceMeta -------------
@@ -34,8 +36,6 @@ export const requestToTask = async (request: VideoSequenceRequest): Promise<Vide
34
 
35
  seed: getValidNumber(request.sequence.seed, 0, 4294967295, generateSeed()),
36
 
37
- upscale: request.sequence.upscale === true,
38
-
39
  noise: request.sequence.noise === true,
40
 
41
  steps: getValidNumber(request.sequence.steps, 1, 60, 35),
@@ -48,6 +48,7 @@ export const requestToTask = async (request: VideoSequenceRequest): Promise<Vide
48
  outroDurationMs: 3000,
49
 
50
  // ---------- VideoSequenceData ---------
 
51
  nbCompletedShots: 0,
52
  nbTotalShots: 0,
53
  progressPercent: 0,
@@ -62,54 +63,17 @@ export const requestToTask = async (request: VideoSequenceRequest): Promise<Vide
62
  shots: [],
63
  }
64
 
 
65
 
66
- // optional background audio prompt
67
- const backgroundAudioPrompt = `${query.backgroundAudioPrompt || ""}`
68
-
69
- // optional foreground audio prompt
70
- const foregroundAudioPrompt = `${query.foregroundAudioPrompt || ""}`
71
-
72
- // optional seed
73
- const defaultSeed = generateSeed()
74
- const seedStr = getValidNumber(Number(`${query.seed || defaultSeed}`)
75
- const maybeSeed = Number(seedStr)
76
- const seed = isNaN(maybeSeed) || ! isFinite(maybeSeed) ? defaultSeed : maybeSeed
77
-
78
- // in production we want those ON by default
79
- const upscale = `${query.upscale || "true"}` === "true"
80
- const interpolate = `${query.upscale || "true"}` === "true"
81
- const noise = `${query.noise || "true"}` === "true"
82
-
83
-
84
- const defaultDuration = 3
85
- const maxDuration = 5
86
- const durationStr = Number(`${query.duration || defaultDuration}`)
87
- const maybeDuration = Number(durationStr)
88
- const duration = Math.min(maxDuration, Math.max(1, isNaN(maybeDuration) || !isFinite(maybeDuration) ? defaultDuration : maybeDuration))
89
-
90
- const defaultSteps = 35
91
- const stepsStr = Number(`${query.steps || defaultSteps}`)
92
- const maybeSteps = Number(stepsStr)
93
- const nbSteps = Math.min(60, Math.max(1, isNaN(maybeSteps) || !isFinite(maybeSteps) ? defaultSteps : maybeSteps))
94
-
95
- // const frames per second
96
- const defaultFps = 24
97
- const fpsStr = Number(`${query.fps || defaultFps}`)
98
- const maybeFps = Number(fpsStr)
99
- const nbFrames = Math.min(60, Math.max(8, isNaN(maybeFps) || !isFinite(maybeFps) ? defaultFps : maybeFps))
100
-
101
- const defaultResolution = 576
102
- const resolutionStr = Number(`${query.resolution || defaultResolution}`)
103
- const maybeResolution = Number(resolutionStr)
104
- const resolution = Math.min(1080, Math.max(256, isNaN(maybeResolution) || !isFinite(maybeResolution) ? defaultResolution : maybeResolution))
105
-
106
- const actorPrompt = `${query.actorPrompt || ""}`
107
-
108
- const actorVoicePrompt = `${query.actorVoicePrompt || ""}`
109
-
110
- const actorDialoguePrompt = `${query.actorDialoguePrompt || ""}`
111
-
112
 
 
113
 
114
  return task
115
  }
 
3
  // convert a request (which might be invalid)
4
 
5
  import { VideoSequenceRequest, VideoTask } from "../types.mts"
6
+ import { generateSeed } from "../services/generateSeed.mts"
7
+ import { getValidNumber } from "./getValidNumber.mts"
8
+ import { getValidResolution } from "./getValidResolution.mts"
9
+ import { parseShotRequest } from "./parseShotRequest.mts"
10
+ import { sequenceFormatVersion } from "../database/constants.mts"
11
 
12
+
13
+ export const parseVideoRequest = async (request: VideoSequenceRequest): Promise<VideoTask> => {
14
 
15
  const task: VideoTask = {
16
  // ------------ VideoSequenceMeta -------------
 
36
 
37
  seed: getValidNumber(request.sequence.seed, 0, 4294967295, generateSeed()),
38
 
 
 
39
  noise: request.sequence.noise === true,
40
 
41
  steps: getValidNumber(request.sequence.steps, 1, 60, 35),
 
48
  outroDurationMs: 3000,
49
 
50
  // ---------- VideoSequenceData ---------
51
+ version: sequenceFormatVersion,
52
  nbCompletedShots: 0,
53
  nbTotalShots: 0,
54
  progressPercent: 0,
 
63
  shots: [],
64
  }
65
 
66
+ const maybeShots = Array.isArray(request.shots) ? request.shots : []
67
 
68
+ for (const maybeShot of maybeShots) {
69
+ try {
70
+ const shot = await parseShotRequest(task, maybeShot)
71
+ task.shots.push(shot)
72
+ } catch (err) {
73
+ console.log(`error parsing shot: `, maybeShot)
74
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
 
76
+ }
77
 
78
  return task
79
  }