File size: 2,775 Bytes
96f407e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"use server"

import Replicate from "replicate"

import { generateSeed } from "../../utils/misc/generateSeed.mts"
import { sleep } from "../../utils/misc/sleep.mts"

const replicateToken = `${process.env.VC_REPLICATE_API_TOKEN || ""}`
const replicateModel = `wyhsirius/lia`
const replicateModelVersion = "4ce4e4aff5bd28c6958b1e3e7628ea80718be56672d92ea8039039a3a152e67d"

if (!replicateToken) {
  throw new Error(`you need to configure your VC_REPLICATE_API_TOKEN`)
}

const replicate = new Replicate({ auth: replicateToken })

/**
 * Generate a video with hotshot through Replicate
 * 
 * Note that if nbFrames == 1, then it will generate a jpg
 * 
 */
export async function generateVideoWithHotshotReplicate({
   
  }): Promise<string> {

  if (!replicateModel) {
    throw new Error(`you need to configure the replicateModel`)
  }

  if (!replicateModelVersion) {
    throw new Error(`you need to configure the replicateModelVersion`)
  }

  const prediction = await replicate.predictions.create({
    version: replicateModelVersion,
    input: {
      img_source: ,
      negative_prompt: negativePrompt,

      // this is not a URL but a model name
      hf_lora_url: replicateLora?.length ? undefined : huggingFaceLora,

      // this is a URL to the .tar (we can get it from the "trainings" page)
      replicate_weights_url: huggingFaceLora?.length ? undefined : replicateLora,

      width,
      height,

      // those are used to create an upsampling or downsampling
      // original_width: width,
      // original_height: height,
      // target_width: width,
      // target_height: height,

      steps: nbSteps,
    
      
      // note: right now it only makes sense to use either 1 (a jpg)
      video_length: nbFrames, // nb frames

      video_duration: videoDuration, // video duration in ms
      
      seed: !isNaN(seed) && isFinite(seed) ? seed : generateSeed()
    }
  })
    
  // console.log("prediction:", prediction)

  // Replicate requires at least 30 seconds of mandatory delay
  await sleep(30000)

  let res: Response
  let pollingCount = 0
  do {
    // Check every 5 seconds
    await sleep(5000)

    res = await fetch(`https://api.replicate.com/v1/predictions/${prediction.id}`, {
      method: "GET",
      headers: {
        Authorization: `Token ${replicateToken}`,
      },
      cache: 'no-store',
    })

    if (res.status === 200) {
      const response = (await res.json()) as any
      const error = `${response?.error || ""}`
      if (error) {
        throw new Error(error)
      }
    }

    pollingCount++

    // To prevent indefinite polling, we can stop after a certain number, here 30 (i.e. about 2 and half minutes)
    if (pollingCount >= 30) {
      throw new Error('Request time out.')
    }
  } while (true)
}