File size: 2,544 Bytes
2eea766
f24ad59
d4a1dc1
8919651
2eea766
f24ad59
8919651
f24ad59
8919651
db70195
58b1ffb
2eea766
 
 
 
 
 
 
 
 
8919651
2eea766
f24ad59
 
 
 
db70195
 
2eea766
 
f24ad59
2eea766
f24ad59
2eea766
58b1ffb
2eea766
d4a1dc1
58b1ffb
 
 
 
2eea766
 
 
 
c1ce586
 
 
f24ad59
8e3d721
 
 
 
f24ad59
 
db70195
 
8e3d721
 
2eea766
58b1ffb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2eea766
f24ad59
2eea766
 
 
 
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
import { NextResponse, NextRequest } from "next/server"
import queryString from "query-string"
import { ClapProject, ClapSegment, ClapSegmentCategory, newClap, parseClap, serializeClap } from "@aitube/clap"
import { ClapCompletionMode } from "@aitube/client"

import { parseCompletionMode } from "@/app/api/parsers/parseCompletionMode"
import { throwIfInvalidToken } from "@/app/api/v1/auth/throwIfInvalidToken"

import { processShot } from "./processShot"
import { parseTurbo } from "@/app/api/parsers/parseTurbo"
import { sleep } from "@/lib/utils/sleep"

// a helper to generate videos for a Clap
// this is mostly used by external apps such as the Stories Factory
// this function will:
//
// - add missing videos to the shots
// - add missing video prompts
// - add missing video files
export async function POST(req: NextRequest) {
  await throwIfInvalidToken(req.headers.get("Authorization"))

  const qs = queryString.parseUrl(req.url || "")
  const query = (qs || {}).query
  
  const mode = parseCompletionMode(query?.c)
  const turbo = parseTurbo(query?.t)

  const blob = await req.blob()

  const existingClap: ClapProject = await parseClap(blob)

  if (!existingClap?.segments) { throw new Error(`no segment found in the provided clap!`) }
  
  // console.log(`api/edit/videos(): detected ${existingClap.segments.length} segments`)
  
  const shotsSegments: ClapSegment[] = existingClap.segments.filter(s => s.category === ClapSegmentCategory.CAMERA)
    
  // console.log(`api/edit/videos(): detected ${shotsSegments.length} shots`)


  if (shotsSegments.length > 32) {
    throw new Error(`Error, this endpoint being synchronous, it is designed for short stories only (max 32 shots).`)
  }

  const newerClap = mode === ClapCompletionMode.FULL ? existingClap : newClap({
    meta: existingClap.meta
  })

  // we process the shots in parallel (this will increase the queue size in the Gradio spaces)
  await Promise.all(shotsSegments.map(shotSegment =>
    processShot({
      shotSegment,
      existingClap,
      newerClap,
      mode,
      turbo,
    })
  ))

  // we currently have some parallelism issues..
  /*
  for (const shotSegment of shotsSegments) {
    await processShot({
      shotSegment,
      existingClap,
      newerClap,
      mode,
      turbo,
    })
    await sleep(500)
  }
  */

  // `api/edit/videos(): returning the clap augmented with videos`)

  return new NextResponse(await serializeClap(newerClap), {
    status: 200,
    headers: new Headers({ "content-type": "application/x-gzip" }),
  })
}