jbilcke-hf HF staff commited on
Commit
2f67628
·
1 Parent(s): bb503b1

use @aitube/clap

Browse files
src/core/clap/getClapAssetSourceType.mts DELETED
@@ -1,25 +0,0 @@
1
- import { ClapAssetSource } from "./types.mts"
2
-
3
- export function getClapAssetSourceType(input: string = ""): ClapAssetSource {
4
-
5
- const str = `${input || ""}`.trim()
6
-
7
- if (!str || !str.length) {
8
- return "EMPTY"
9
- }
10
-
11
- if (str.startsWith("https://") || str.startsWith("http://")) {
12
- return "REMOTE"
13
- }
14
-
15
- // note that "path" assets are potentially a security risk, they need to be treated with care
16
- if (str.startsWith("/") || str.startsWith("../") || str.startsWith("./")) {
17
- return "PATH"
18
- }
19
-
20
- if (str.startsWith("data:")) {
21
- return "DATA"
22
- }
23
-
24
- return "PROMPT"
25
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/core/clap/parseClap.mts DELETED
@@ -1,320 +0,0 @@
1
-
2
- import { v4 as uuidv4 } from "uuid"
3
- import YAML from "yaml"
4
-
5
- import { ClapHeader, ClapMeta, ClapModel, ClapProject, ClapScene, ClapSegment } from "./types.mts"
6
- import { getValidNumber } from "../parsers/getValidNumber.mts"
7
- import { dataUriToBlob } from "../base64/dataUriToBlob.mts"
8
-
9
- type StringOrBlob = string | Blob
10
-
11
- /**
12
- * Import a clap file from various data sources into an ClapProject
13
- *
14
- * Inputs can be:
15
- * - a Clap project (which is an object)
16
- * - an URL to a remote .clap file
17
- * - a string containing a YAML array
18
- * - a data uri containing a gzipped YAML array
19
- * - a Blob containing a gzipped YAML array
20
- *
21
- * note: it is not really async, because for some reason YAML.parse is a blocking call like for JSON,
22
- * there is no async version although we are now in the 20s not 90s
23
- */
24
- export async function parseClap(src?: ClapProject | string | Blob, debug = false): Promise<ClapProject> {
25
-
26
- try {
27
- if (
28
- typeof src === "object" &&
29
- Array.isArray( (src as any)?.scenes) &&
30
- Array.isArray((src as any)?.models)
31
- ) {
32
- if (debug) {
33
- console.log("parseClap: input is already a Clap file, nothing to do:", src)
34
- }
35
- // we can skip verification
36
- return src as ClapProject
37
- }
38
- } catch (err) {
39
- // well, this is not a clap project
40
- }
41
-
42
- let stringOrBlob = (src || "") as StringOrBlob
43
-
44
- // both should work
45
- const dataUriHeader1 = "data:application/x-gzip;base64,"
46
- const dataUriHeader2 = "data:application/octet-stream;base64,"
47
-
48
- const inputIsString = typeof stringOrBlob === "string"
49
- const inputIsDataUri = typeof stringOrBlob === "string" ? stringOrBlob.startsWith(dataUriHeader1) || stringOrBlob.startsWith(dataUriHeader2) : false
50
- const inputIsRemoteFile = typeof stringOrBlob === "string" ? (stringOrBlob.startsWith("http://") || stringOrBlob.startsWith("https://")) : false
51
-
52
- let inputIsBlob = typeof stringOrBlob !== "string"
53
-
54
- let inputYamlArrayString = ""
55
-
56
- if (debug) {
57
- console.log(`parseClap: pre-analysis: ${JSON.stringify({
58
- inputIsString,
59
- inputIsBlob,
60
- inputIsDataUri,
61
- inputIsRemoteFile
62
- }, null, 2)}`)
63
- }
64
-
65
- if (typeof stringOrBlob === "string") {
66
- if (debug) {
67
- console.log("parseClap: input is a string ", stringOrBlob.slice(0, 120))
68
- }
69
- if (inputIsDataUri) {
70
- if (debug) {
71
- console.log(`parseClap: input is a data uri archive`)
72
- }
73
- stringOrBlob = dataUriToBlob(stringOrBlob, "application/x-gzip")
74
- if (debug) {
75
- console.log(`parseClap: inputBlob = `, stringOrBlob)
76
- }
77
- inputIsBlob = true
78
- } else if (inputIsRemoteFile) {
79
- try {
80
- if (debug) {
81
- console.log(`parseClap: input is a remote .clap file`)
82
- }
83
- const res = await fetch(stringOrBlob)
84
- stringOrBlob = await res.blob()
85
- if (!stringOrBlob) { throw new Error("blob is empty") }
86
- inputIsBlob = true
87
- } catch (err) {
88
- // url seems invalid
89
- throw new Error(`failed to download the .clap file (${err})`)
90
- }
91
- } else {
92
- if (debug) {
93
- console.log("parseClap: input is a text string containing a YAML array")
94
- }
95
- inputYamlArrayString = stringOrBlob
96
- inputIsBlob = false
97
- }
98
- }
99
-
100
- if (typeof stringOrBlob !== "string" && stringOrBlob) {
101
- if (debug) {
102
- console.log("parseClap: decompressing the blob..")
103
- }
104
- // Decompress the input blob using gzip
105
- const decompressedStream = stringOrBlob.stream().pipeThrough(new DecompressionStream('gzip'))
106
-
107
- try {
108
- // Convert the stream to text using a Response object
109
- const decompressedOutput = new Response(decompressedStream)
110
- // decompressedOutput.headers.set("Content-Type", "application/x-gzip")
111
- if (debug) {
112
- console.log("parseClap: decompressedOutput: ", decompressedOutput)
113
- }
114
- // const blobAgain = await decompressedOutput.blob()
115
- inputYamlArrayString = await decompressedOutput.text()
116
-
117
- if (debug && inputYamlArrayString) {
118
- console.log("parseClap: successfully decompressed the blob!")
119
- }
120
- } catch (err) {
121
- const message = `parseClap: failed to decompress (${err})`
122
- console.error(message)
123
- throw new Error(message)
124
- }
125
- }
126
-
127
- // we don't need this anymore I think
128
- // new Blob([inputStringOrBlob], { type: "application/x-yaml" })
129
-
130
- let maybeArray: any = {}
131
- try {
132
- if (debug) {
133
- console.log("parseClap: parsing the YAML array..")
134
- }
135
- // Parse YAML string to raw data
136
- maybeArray = YAML.parse(inputYamlArrayString)
137
- } catch (err) {
138
- throw new Error("invalid clap file (input string is not YAML)")
139
- }
140
-
141
- if (!Array.isArray(maybeArray) || maybeArray.length < 2) {
142
- throw new Error("invalid clap file (need a clap format header block and project metadata block)")
143
- }
144
-
145
- if (debug) {
146
- console.log("parseClap: the YAML seems okay, continuing decoding..")
147
- }
148
-
149
- const maybeClapHeader = maybeArray[0] as ClapHeader
150
-
151
- if (maybeClapHeader.format !== "clap-0") {
152
- throw new Error("invalid clap file (sorry, but you can't make up version numbers like that)")
153
- }
154
-
155
-
156
- const maybeClapMeta = maybeArray[1] as ClapMeta
157
-
158
- const clapMeta: ClapMeta = {
159
- id: typeof maybeClapMeta.title === "string" ? maybeClapMeta.id : uuidv4(),
160
- title: typeof maybeClapMeta.title === "string" ? maybeClapMeta.title : "",
161
- description: typeof maybeClapMeta.description === "string" ? maybeClapMeta.description : "",
162
- synopsis: typeof maybeClapMeta.synopsis === "string" ? maybeClapMeta.synopsis : "",
163
- licence: typeof maybeClapMeta.licence === "string" ? maybeClapMeta.licence : "",
164
- orientation: maybeClapMeta.orientation === "portrait" ? "portrait" : maybeClapMeta.orientation === "square" ? "square" : "landscape",
165
- durationInMs: getValidNumber(maybeClapMeta.durationInMs, 1000, Number.MAX_SAFE_INTEGER, 4000),
166
- width: getValidNumber(maybeClapMeta.width, 128, 8192, 1024),
167
- height: getValidNumber(maybeClapMeta.height, 128, 8192, 576),
168
- defaultVideoModel: typeof maybeClapMeta.defaultVideoModel === "string" ? maybeClapMeta.defaultVideoModel : "SVD",
169
- extraPositivePrompt: Array.isArray(maybeClapMeta.extraPositivePrompt) ? maybeClapMeta.extraPositivePrompt : [],
170
- screenplay: typeof maybeClapMeta.screenplay === "string" ? maybeClapMeta.screenplay : "",
171
- isLoop: typeof maybeClapMeta.isLoop === "boolean" ? maybeClapMeta.isLoop : false,
172
- isInteractive: typeof maybeClapMeta.isInteractive === "boolean" ? maybeClapMeta.isInteractive : false,
173
- }
174
-
175
- /*
176
- in case we want to support streaming (mix of models and segments etc), we could do it this way:
177
-
178
- const maybeModelsOrSegments = rawData.slice(2)
179
- maybeModelsOrSegments.forEach((unknownElement: any) => {
180
- if (isValidNumber(unknownElement?.track)) {
181
- maybeSegments.push(unknownElement as ClapSegment)
182
- } else {
183
- maybeModels.push(unknownElement as ClapModel)
184
- }
185
- })
186
- */
187
-
188
-
189
- const expectedNumberOfModels = maybeClapHeader.numberOfModels || 0
190
- const expectedNumberOfScenes = maybeClapHeader.numberOfScenes || 0
191
- const expectedNumberOfSegments = maybeClapHeader.numberOfSegments || 0
192
-
193
- // note: we assume the order is strictly enforced!
194
- // if you implement streaming (mix of models and segments) you will have to rewrite this!
195
-
196
- const afterTheHeaders = 2
197
- const afterTheModels = afterTheHeaders + expectedNumberOfModels
198
-
199
- const afterTheScenes = afterTheModels + expectedNumberOfScenes
200
-
201
- // note: if there are no expected models, maybeModels will be empty
202
- const maybeModels = maybeArray.slice(afterTheHeaders, afterTheModels) as ClapModel[]
203
-
204
- // note: if there are no expected scenes, maybeScenes will be empty
205
- const maybeScenes = maybeArray.slice(afterTheModels, afterTheScenes) as ClapScene[]
206
-
207
- const maybeSegments = maybeArray.slice(afterTheScenes) as ClapSegment[]
208
-
209
- const clapModels: ClapModel[] = maybeModels.map(({
210
- id,
211
- category,
212
- triggerName,
213
- label,
214
- description,
215
- author,
216
- thumbnailUrl,
217
- seed,
218
- assetSourceType,
219
- assetUrl,
220
- age,
221
- gender,
222
- region,
223
- appearance,
224
- voiceVendor,
225
- voiceId,
226
- }) => ({
227
- // TODO: we should verify each of those, probably
228
- id,
229
- category,
230
- triggerName,
231
- label,
232
- description,
233
- author,
234
- thumbnailUrl,
235
- seed,
236
- assetSourceType,
237
- assetUrl,
238
- age,
239
- gender,
240
- region,
241
- appearance,
242
- voiceVendor,
243
- voiceId,
244
- }))
245
-
246
- const clapScenes: ClapScene[] = maybeScenes.map(({
247
- id,
248
- scene,
249
- line,
250
- rawLine,
251
- sequenceFullText,
252
- sequenceStartAtLine,
253
- sequenceEndAtLine,
254
- startAtLine,
255
- endAtLine,
256
- events,
257
- }) => ({
258
- id,
259
- scene,
260
- line,
261
- rawLine,
262
- sequenceFullText,
263
- sequenceStartAtLine,
264
- sequenceEndAtLine,
265
- startAtLine,
266
- endAtLine,
267
- events: events.map(e => e)
268
- }))
269
-
270
- const clapSegments: ClapSegment[] = maybeSegments.map(({
271
- id,
272
- track,
273
- startTimeInMs,
274
- endTimeInMs,
275
- category,
276
- modelId,
277
- sceneId,
278
- prompt,
279
- label,
280
- outputType,
281
- renderId,
282
- status,
283
- assetUrl,
284
- assetDurationInMs,
285
- createdBy,
286
- editedBy,
287
- outputGain,
288
- seed,
289
- }) => ({
290
- // TODO: we should verify each of those, probably
291
- id,
292
- track,
293
- startTimeInMs,
294
- endTimeInMs,
295
- category,
296
- modelId,
297
- sceneId,
298
- prompt,
299
- label,
300
- outputType,
301
- renderId,
302
- status,
303
- assetUrl,
304
- assetDurationInMs,
305
- createdBy,
306
- editedBy,
307
- outputGain,
308
- seed,
309
- }))
310
-
311
- if (debug) {
312
- console.log(`parseClap: successfully parsed ${clapModels.length} models, ${clapScenes.length} scenes and ${clapSegments.length} segments`)
313
- }
314
- return {
315
- meta: clapMeta,
316
- models: clapModels,
317
- scenes: clapScenes,
318
- segments: clapSegments
319
- }
320
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/core/clap/types.mts DELETED
@@ -1,203 +0,0 @@
1
-
2
- export type ClapSegmentCategory =
3
- | "splat"
4
- | "mesh"
5
- | "depth"
6
- | "event"
7
- | "interface"
8
- | "phenomenon"
9
- | "video"
10
- | "storyboard"
11
- | "transition"
12
- | "characters"
13
- | "location"
14
- | "time"
15
- | "era"
16
- | "lighting"
17
- | "weather"
18
- | "action"
19
- | "music"
20
- | "sound"
21
- | "dialogue"
22
- | "style"
23
- | "camera"
24
- | "generic"
25
-
26
- export type ClapOutputType =
27
- | "text"
28
- | "animation"
29
- | "interface"
30
- | "event"
31
- | "phenomenon"
32
- | "transition"
33
- | "image"
34
- | "video"
35
- | "audio"
36
-
37
- export type ClapSegmentStatus =
38
- | "to_generate"
39
- | "to_interpolate"
40
- | "to_upscale"
41
- | "completed"
42
- | "error"
43
-
44
- export type ClapAuthor =
45
- | "auto" // the element was edited automatically using basic if/else logical rules
46
- | "ai" // the element was edited using a large language model
47
- | "human" // the element was edited by a human
48
-
49
- export type ClapAssetSource =
50
- | "REMOTE" // http:// or https://
51
-
52
- // note that "path" assets are potentially a security risk, they need to be treated with care
53
- | "PATH" // a file path eg. /path or ./path/to/ or ../path/to/
54
-
55
- | "DATA" // a data URI, starting with data:
56
-
57
- | "PROMPT" // by default, a plain text prompt
58
-
59
- | "EMPTY"
60
-
61
- export type ClapModelGender =
62
- | "male"
63
- | "female"
64
- | "person"
65
- | "object"
66
-
67
- export type ClapModelAppearance = "serious" | "neutral" | "friendly" | "chill"
68
-
69
- // this is used for accent, style..
70
- export type ClapModelRegion =
71
- | "american"
72
- | "british"
73
- | "australian"
74
- | "canadian"
75
- | "indian"
76
- | "french"
77
- | "italian"
78
- | "german"
79
- | "chinese"
80
-
81
- // note: this is all very subjective, so please use good judgment
82
- //
83
- // "deep" might indicate a deeper voice tone, thicker, rich in harmonics
84
- // in this context, it is used to indicate voices that could
85
- // be associated with African American (AADOS) characters
86
- //
87
- // "high" could be used for some other countries, eg. asia
88
- export type ClapModelTimbre = "high" | "neutral" | "deep"
89
-
90
- export type ClapVoiceVendor = "ElevenLabs" | "XTTS"
91
-
92
- export type ClapVoice = {
93
- name: string
94
- gender: ClapModelGender
95
- age: number
96
- region: ClapModelRegion
97
- timbre: ClapModelTimbre
98
- appearance: ClapModelAppearance
99
- voiceVendor: ClapVoiceVendor
100
- voiceId: string
101
- }
102
-
103
- export type ClapHeader = {
104
- format: "clap-0"
105
- numberOfModels: number
106
- numberOfScenes: number
107
- numberOfSegments: number
108
- }
109
-
110
- export type ClapMeta = {
111
- id: string
112
- title: string
113
- description: string
114
- synopsis: string
115
- licence: string
116
- orientation: string
117
-
118
- // the default duration of the experience
119
- // the real one might last longer if made interactive
120
- durationInMs: number
121
-
122
- width: number
123
- height: number
124
- defaultVideoModel: string
125
- extraPositivePrompt: string[]
126
- screenplay: string
127
- isLoop: boolean
128
- isInteractive: boolean
129
- }
130
-
131
- export type ClapSceneEvent = {
132
- id: string
133
- type: "description" | "dialogue" | "action"
134
- character?: string
135
- description: string
136
- behavior: string
137
- startAtLine: number
138
- endAtLine: number
139
- }
140
-
141
- export type ClapScene = {
142
- id: string
143
- scene: string
144
- line: string
145
- rawLine: string
146
- sequenceFullText: string
147
- sequenceStartAtLine: number
148
- sequenceEndAtLine: number
149
- startAtLine: number
150
- endAtLine: number
151
- events: ClapSceneEvent[]
152
- }
153
-
154
- export type ClapSegment = {
155
- id: string
156
- track: number
157
- startTimeInMs: number
158
- endTimeInMs: number
159
- category: ClapSegmentCategory
160
- modelId: string
161
- sceneId: string
162
- prompt: string
163
- label: string
164
- outputType: ClapOutputType
165
- renderId: string
166
- status: ClapSegmentStatus
167
- assetUrl: string
168
- assetDurationInMs: number
169
- createdBy: ClapAuthor
170
- editedBy: ClapAuthor
171
- outputGain: number
172
- seed: number
173
- }
174
-
175
- export type ClapModel = {
176
- id: string
177
- category: ClapSegmentCategory
178
- triggerName: string
179
- label: string
180
- description: string
181
- author: string
182
- thumbnailUrl: string
183
- seed: number
184
-
185
- assetSourceType: ClapAssetSource
186
- assetUrl: string
187
-
188
- // those are only used by certain types of models
189
- age: number
190
- gender: ClapModelGender
191
- region: ClapModelRegion
192
- appearance: ClapModelAppearance
193
- voiceVendor: ClapVoiceVendor
194
- voiceId: string
195
- }
196
-
197
- export type ClapProject = {
198
- meta: ClapMeta
199
- models: ClapModel[]
200
- scenes: ClapScene[]
201
- segments: ClapSegment[]
202
- // let's keep room for other stuff (screenplay etc)
203
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/core/exporters/clapWithStoryboardsToVideoFile.mts CHANGED
@@ -1,6 +1,6 @@
1
  import { join } from "node:path"
2
 
3
- import { ClapProject } from "../clap/types.mts"
4
  import { concatenateVideosWithAudio } from "../ffmpeg/concatenateVideosWithAudio.mts"
5
  import { writeBase64ToFile } from "../files/writeBase64ToFile.mts"
6
  import { getRandomDirectory } from "../files/getRandomDirectory.mts"
@@ -8,7 +8,6 @@ import { addTextToVideo } from "../ffmpeg/addTextToVideo.mts"
8
  import { startOfSegment1IsWithinSegment2 } from "../utils/startOfSegment1IsWithinSegment2.mts"
9
  import { deleteFile } from "../files/deleteFile.mts"
10
  import { extractBase64 } from "../base64/extractBase64.mts"
11
- import { ClapSegment } from "../clap/types.mts"
12
  import { imageToVideoBase64 } from "../ffmpeg/imageToVideoBase64.mts"
13
 
14
  export async function clapWithStoryboardsToVideoFile({
 
1
  import { join } from "node:path"
2
 
3
+ import { ClapProject, ClapSegment } from "@aitube/clap"
4
  import { concatenateVideosWithAudio } from "../ffmpeg/concatenateVideosWithAudio.mts"
5
  import { writeBase64ToFile } from "../files/writeBase64ToFile.mts"
6
  import { getRandomDirectory } from "../files/getRandomDirectory.mts"
 
8
  import { startOfSegment1IsWithinSegment2 } from "../utils/startOfSegment1IsWithinSegment2.mts"
9
  import { deleteFile } from "../files/deleteFile.mts"
10
  import { extractBase64 } from "../base64/extractBase64.mts"
 
11
  import { imageToVideoBase64 } from "../ffmpeg/imageToVideoBase64.mts"
12
 
13
  export async function clapWithStoryboardsToVideoFile({
src/core/exporters/clapWithVideosToVideoFile.mts CHANGED
@@ -1,6 +1,6 @@
1
  import { join } from "node:path"
2
 
3
- import { ClapProject } from "../clap/types.mts"
4
  import { concatenateVideosWithAudio } from "../ffmpeg/concatenateVideosWithAudio.mts"
5
  import { writeBase64ToFile } from "../files/writeBase64ToFile.mts"
6
  import { getRandomDirectory } from "../files/getRandomDirectory.mts"
@@ -8,7 +8,6 @@ import { addTextToVideo } from "../ffmpeg/addTextToVideo.mts"
8
  import { startOfSegment1IsWithinSegment2 } from "../utils/startOfSegment1IsWithinSegment2.mts"
9
  import { deleteFile } from "../files/deleteFile.mts"
10
  import { extractBase64 } from "../base64/extractBase64.mts"
11
- import { ClapSegment } from "../clap/types.mts"
12
 
13
  export async function clapWithVideosToVideoFile({
14
  clap,
 
1
  import { join } from "node:path"
2
 
3
+ import { ClapProject, ClapSegment } from "@aitube/clap"
4
  import { concatenateVideosWithAudio } from "../ffmpeg/concatenateVideosWithAudio.mts"
5
  import { writeBase64ToFile } from "../files/writeBase64ToFile.mts"
6
  import { getRandomDirectory } from "../files/getRandomDirectory.mts"
 
8
  import { startOfSegment1IsWithinSegment2 } from "../utils/startOfSegment1IsWithinSegment2.mts"
9
  import { deleteFile } from "../files/deleteFile.mts"
10
  import { extractBase64 } from "../base64/extractBase64.mts"
 
11
 
12
  export async function clapWithVideosToVideoFile({
13
  clap,
src/index.mts CHANGED
@@ -1,9 +1,9 @@
1
 
 
 
2
  import express from "express"
3
- import { Blob } from "buffer"
4
 
5
- import { parseClap } from "./core/clap/parseClap.mts"
6
- import { ClapProject } from "./core/clap/types.mts"
7
  import { clapToTmpVideoFilePath } from "./main.mts"
8
  import { deleteFile } from "./core/files/deleteFile.mts"
9
 
 
1
 
2
+ import { Blob } from "node:buffer"
3
+
4
  import express from "express"
5
+ import { parseClap, ClapProject } from "@aitube/clap"
6
 
 
 
7
  import { clapToTmpVideoFilePath } from "./main.mts"
8
  import { deleteFile } from "./core/files/deleteFile.mts"
9
 
src/main.mts CHANGED
@@ -1,6 +1,7 @@
1
  import { join } from "node:path"
2
 
3
- import { ClapProject } from "./core/clap/types.mts";
 
4
  import { concatenateAudio } from "./core/ffmpeg/concatenateAudio.mts";
5
  import { concatenateVideosWithAudio } from "./core/ffmpeg/concatenateVideosWithAudio.mts";
6
  import { writeBase64ToFile } from "./core/files/writeBase64ToFile.mts";
 
1
  import { join } from "node:path"
2
 
3
+ import { ClapProject } from "@aitube/clap";
4
+
5
  import { concatenateAudio } from "./core/ffmpeg/concatenateAudio.mts";
6
  import { concatenateVideosWithAudio } from "./core/ffmpeg/concatenateVideosWithAudio.mts";
7
  import { writeBase64ToFile } from "./core/files/writeBase64ToFile.mts";