File size: 4,151 Bytes
198274c
 
 
 
 
 
 
80dd4ba
198274c
 
 
 
 
80dd4ba
 
198274c
1373ff5
0d06ec6
198274c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80dd4ba
 
 
198274c
80dd4ba
 
198274c
 
 
 
80dd4ba
 
 
198274c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72f62be
198274c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0d06ec6
 
198274c
0d06ec6
198274c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { RenderedScene, RenderRequest } from "../../types.mts"
import { generateSeed } from "../../utils/misc/generateSeed.mts"
import { tryApiCalls } from "../../utils/misc/tryApiCall.mts"
import { getValidNumber } from "../../utils/validators/getValidNumber.mts"

const accessToken = `${process.env.VC_MICROSERVICE_SECRET_TOKEN || ""}`

// @deprecated This endpoint has been decommissioned. Please use the AiTube API instead (check aitube.at/api/v1/render)
export const generateVideoWithAnimateDiffLightning = async (
  request: RenderRequest,
  response: RenderedScene,
): Promise<RenderedScene> => {
  
  throw new Error(`This endpoint has been decommissioned. Please use the AiTube API instead (check aitube.at/api/v1/render)`)
  const debug = true


  const actualFunction = async (): Promise<RenderedScene> => {

    const prompt = request.prompt || ""
    if (!prompt) {
      response.error = "prompt is empty"
      return response
    }
    
    // seed = seed || generateSeed()
    request.seed = request.seed || generateSeed()

    // see https://huggingface.co/spaces/jbilcke-hf/ai-tube-model-animatediff-lightning/blob/main/app.py#L15-L18
    const baseModel = "epiCRealism"

    // the motion LoRA - could be useful one day
    const motion = ""

    // can be 1, 2, 4 or 8
    // but values below 4 look bad
    const nbSteps = 4// getValidNumber(request.nbSteps, 1, 8, 4)
    const width = 512 // getValidNumber(request.width, 256, 1024, 512)
    const height = 288 // getValidNumber(request.height, 256, 1024, 256)

    const nbFrames = 16 // getValidNumber(request.nbFrames, 10, 60, 10)
    const nbFPS = 10 //  getValidNumber(request.nbFPS, 10, 60, 10)

    // by default AnimateDiff generates about 2 seconds of video at 10 fps
    // the Gradio API now has some code to optional fix that using FFmpeg,
    // but this will add some delay overhead, so use with care!
    const durationInSec = nbFrames / nbFPS
    // no, we need decimals
    // const durationInSec = Math.round(nbFrames / nbFPS)
    const framesPerSec = nbFPS

    try {
      if (debug) {
        console.log(`calling AnimateDiff Lightning API with params (some are hidden):`, {
          baseModel,
          motion,
          nbSteps,
          width,
          height,
          nbFrames,
          nbFPS,
          durationInSec,
          framesPerSec,
        })
      }

      const res = await fetch(`https://jbilcke-hf-ai-tube-model-animatediff.hf.space/api/predict`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          // Authorization: `Bearer ${token}`,
        },
        body: JSON.stringify({
          fn_index: 0, // <- important! it is currently 4, not 1!
          data: [
            accessToken,
            prompt,
            baseModel,
            width,
            height,
            motion,
            nbSteps,
            durationInSec,
            framesPerSec,
          ],
        }),
        cache: "no-store",
        // we can also use this (see https://vercel.com/blog/vercel-cache-api-nextjs-cache)
        // next: { revalidate: 1 }
      })

      // console.log("res:", res)

      const { data } = await res.json()

      // console.log("data:", data)
      // Recommendation: handle errors
      if (res.status !== 200 || !Array.isArray(data)) {
        // This will activate the closest `error.js` Error Boundary
        throw new Error(`Failed to fetch data (status: ${res.status})`)
      }
      // console.log("data:", data.slice(0, 50))
    
      const base64Content = (data?.[0] || "") as string

      if (!base64Content) {
        throw new Error(`invalid response (no content)`)
      }

      response.assetUrl = base64Content

      // this API already emits a data-uri with a content type
      return response // addBase64HeaderToMp4(base64Content)
    } catch (err) {
      if (debug) {
        console.error(`failed to call the AnimateDiff Lightning API:`)
        console.error(err)
      }
      throw err
    }
  }

  return tryApiCalls({
    func: actualFunction,
    debug,
    failureMessage: "failed to call the AnimateDiff Lightning API"
  })
}