Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
Commit
•
0d218b1
1
Parent(s):
83defd6
let's use @aitube/clap inside AiTube
Browse files- .env +2 -0
- next.config.js +3 -0
- package-lock.json +96 -75
- package.json +3 -2
- src/app/api/actions/ai-tube-hf/downloadClapProject.ts +3 -3
- src/app/api/generate/models/generateAudioID.ts +12 -0
- src/app/api/generate/models/generateImageID.ts +68 -0
- src/app/api/generate/models/route.ts +75 -0
- src/app/api/generate/models/systemPrompt.ts +3 -0
- src/app/api/generate/story/route.ts +4 -7
- src/app/api/generate/storyboards/generateStoryboard.ts +1 -2
- src/app/api/generate/storyboards/route.ts +13 -14
- src/app/api/generate/video/route.ts +2 -1
- src/app/api/generators/clap/addLatentScenesToClap.ts +1 -5
- src/app/api/generators/clap/continueClap.ts +2 -5
- src/app/api/generators/clap/generateClap.ts +4 -6
- src/app/api/generators/search/unknownObjectToLatentSearchResults.ts +2 -1
- src/app/api/resolvers/clap/route.ts +1 -0
- src/app/api/resolvers/image/route.ts +1 -1
- src/app/api/resolvers/video/route.ts +2 -1
- src/app/dream/spoiler.tsx +1 -2
- src/components/interface/latent-engine/core/engine.tsx +3 -4
- src/components/interface/latent-engine/core/generators/fetchLatentClap.ts +1 -2
- src/components/interface/latent-engine/core/prompts/getCharacterPrompt.ts +1 -1
- src/components/interface/latent-engine/core/prompts/getVideoPrompt.ts +1 -1
- src/components/interface/latent-engine/core/types.ts +1 -1
- src/components/interface/latent-engine/core/useLatentEngine.ts +4 -8
- src/components/interface/latent-engine/resolvers/deprecated.txt +1 -1
- src/components/interface/latent-engine/resolvers/generic/index.tsx +1 -1
- src/components/interface/latent-engine/resolvers/image/index.tsx +1 -1
- src/components/interface/latent-engine/resolvers/interface/index.tsx +1 -1
- src/components/interface/latent-engine/resolvers/resolveSegment.ts +1 -1
- src/components/interface/latent-engine/resolvers/resolveSegments.ts +1 -1
- src/components/interface/latent-engine/resolvers/video/index.tsx +1 -1
- src/components/interface/latent-engine/resolvers/video/index_legacy.tsx +1 -1
- src/components/interface/latent-engine/resolvers/video/index_notSoGood.tsx +1 -1
- src/lib/business/getClapAssetSourceType.ts +1 -1
- src/lib/clap/clap-specification-draft.md +0 -162
- src/lib/clap/clapToDataUri.ts +0 -10
- src/lib/clap/emptyClap.ts +0 -18
- src/lib/clap/generateClapFromSimpleStory.ts +0 -149
- src/lib/clap/getClapAssetSource.ts +0 -25
- src/lib/clap/newClap.ts +0 -37
- src/lib/clap/newSegment.ts +0 -46
- src/lib/clap/parseClap.ts +0 -319
- src/lib/clap/serializeClap.ts +0 -169
- src/lib/clap/types.ts +0 -203
- src/lib/prompts/generateSeed.ts +0 -3
- src/lib/utils/generateSeed.ts +0 -3
- src/lib/utils/startOfSegment1IsWithinSegment2.ts +1 -1
.env
CHANGED
@@ -3,6 +3,8 @@ API_SECRET_JWT_KEY=""
|
|
3 |
API_SECRET_JWT_ISSUER=""
|
4 |
API_SECRET_JWT_AUDIENCE=""
|
5 |
|
|
|
|
|
6 |
NEXT_PUBLIC_DOMAIN="https://aitube.at"
|
7 |
|
8 |
NEXT_PUBLIC_SHOW_BETA_FEATURES="false"
|
|
|
3 |
API_SECRET_JWT_ISSUER=""
|
4 |
API_SECRET_JWT_AUDIENCE=""
|
5 |
|
6 |
+
AI_TUBE_CLAP_EXPORTER_URL="https://jbilcke-hf-ai-tube-clap-exporter.hf.space"
|
7 |
+
|
8 |
NEXT_PUBLIC_DOMAIN="https://aitube.at"
|
9 |
|
10 |
NEXT_PUBLIC_SHOW_BETA_FEATURES="false"
|
next.config.js
CHANGED
@@ -1,6 +1,9 @@
|
|
1 |
/** @type {import('next').NextConfig} */
|
2 |
const nextConfig = {
|
3 |
output: 'standalone',
|
|
|
|
|
|
|
4 |
experimental: {
|
5 |
serverActions: {
|
6 |
|
|
|
1 |
/** @type {import('next').NextConfig} */
|
2 |
const nextConfig = {
|
3 |
output: 'standalone',
|
4 |
+
transpilePackages: [
|
5 |
+
// '@aitube/clap'
|
6 |
+
],
|
7 |
experimental: {
|
8 |
serverActions: {
|
9 |
|
package-lock.json
CHANGED
@@ -8,6 +8,7 @@
|
|
8 |
"name": "ai-tube",
|
9 |
"version": "0.0.0",
|
10 |
"dependencies": {
|
|
|
11 |
"@huggingface/hub": "0.12.3-oauth",
|
12 |
"@huggingface/inference": "^2.6.7",
|
13 |
"@jcoreio/async-throttle": "^1.6.0",
|
@@ -95,7 +96,7 @@
|
|
95 |
"temp-dir": "^3.0.0",
|
96 |
"ts-node": "^10.9.2",
|
97 |
"type-fest": "^4.8.2",
|
98 |
-
"typescript": "5.4.
|
99 |
"usehooks-ts": "^2.9.1",
|
100 |
"uuid": "^9.0.1",
|
101 |
"yaml": "^2.3.4",
|
@@ -118,6 +119,18 @@
|
|
118 |
"node": ">=0.10.0"
|
119 |
}
|
120 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
"node_modules/@alloc/quick-lru": {
|
122 |
"version": "5.2.0",
|
123 |
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
|
@@ -1494,14 +1507,14 @@
|
|
1494 |
}
|
1495 |
},
|
1496 |
"node_modules/@mediapipe/tasks-vision": {
|
1497 |
-
"version": "0.10.13-rc.
|
1498 |
-
"resolved": "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.13-rc.
|
1499 |
-
"integrity": "sha512-
|
1500 |
},
|
1501 |
"node_modules/@next/env": {
|
1502 |
-
"version": "14.2.
|
1503 |
-
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.
|
1504 |
-
"integrity": "sha512-
|
1505 |
},
|
1506 |
"node_modules/@next/eslint-plugin-next": {
|
1507 |
"version": "13.4.10",
|
@@ -1512,9 +1525,9 @@
|
|
1512 |
}
|
1513 |
},
|
1514 |
"node_modules/@next/swc-darwin-arm64": {
|
1515 |
-
"version": "14.2.
|
1516 |
-
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.
|
1517 |
-
"integrity": "sha512-
|
1518 |
"cpu": [
|
1519 |
"arm64"
|
1520 |
],
|
@@ -1527,9 +1540,9 @@
|
|
1527 |
}
|
1528 |
},
|
1529 |
"node_modules/@next/swc-darwin-x64": {
|
1530 |
-
"version": "14.2.
|
1531 |
-
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.
|
1532 |
-
"integrity": "sha512-
|
1533 |
"cpu": [
|
1534 |
"x64"
|
1535 |
],
|
@@ -1542,9 +1555,9 @@
|
|
1542 |
}
|
1543 |
},
|
1544 |
"node_modules/@next/swc-linux-arm64-gnu": {
|
1545 |
-
"version": "14.2.
|
1546 |
-
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.
|
1547 |
-
"integrity": "sha512-
|
1548 |
"cpu": [
|
1549 |
"arm64"
|
1550 |
],
|
@@ -1557,9 +1570,9 @@
|
|
1557 |
}
|
1558 |
},
|
1559 |
"node_modules/@next/swc-linux-arm64-musl": {
|
1560 |
-
"version": "14.2.
|
1561 |
-
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.
|
1562 |
-
"integrity": "sha512-
|
1563 |
"cpu": [
|
1564 |
"arm64"
|
1565 |
],
|
@@ -1572,9 +1585,9 @@
|
|
1572 |
}
|
1573 |
},
|
1574 |
"node_modules/@next/swc-linux-x64-gnu": {
|
1575 |
-
"version": "14.2.
|
1576 |
-
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.
|
1577 |
-
"integrity": "sha512-
|
1578 |
"cpu": [
|
1579 |
"x64"
|
1580 |
],
|
@@ -1587,9 +1600,9 @@
|
|
1587 |
}
|
1588 |
},
|
1589 |
"node_modules/@next/swc-linux-x64-musl": {
|
1590 |
-
"version": "14.2.
|
1591 |
-
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.
|
1592 |
-
"integrity": "sha512-
|
1593 |
"cpu": [
|
1594 |
"x64"
|
1595 |
],
|
@@ -1602,9 +1615,9 @@
|
|
1602 |
}
|
1603 |
},
|
1604 |
"node_modules/@next/swc-win32-arm64-msvc": {
|
1605 |
-
"version": "14.2.
|
1606 |
-
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.
|
1607 |
-
"integrity": "sha512-
|
1608 |
"cpu": [
|
1609 |
"arm64"
|
1610 |
],
|
@@ -1617,9 +1630,9 @@
|
|
1617 |
}
|
1618 |
},
|
1619 |
"node_modules/@next/swc-win32-ia32-msvc": {
|
1620 |
-
"version": "14.2.
|
1621 |
-
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.
|
1622 |
-
"integrity": "sha512-
|
1623 |
"cpu": [
|
1624 |
"ia32"
|
1625 |
],
|
@@ -1632,9 +1645,9 @@
|
|
1632 |
}
|
1633 |
},
|
1634 |
"node_modules/@next/swc-win32-x64-msvc": {
|
1635 |
-
"version": "14.2.
|
1636 |
-
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.
|
1637 |
-
"integrity": "sha512-
|
1638 |
"cpu": [
|
1639 |
"x64"
|
1640 |
],
|
@@ -3792,9 +3805,9 @@
|
|
3792 |
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
|
3793 |
},
|
3794 |
"node_modules/clsx": {
|
3795 |
-
"version": "2.1.
|
3796 |
-
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.
|
3797 |
-
"integrity": "sha512-
|
3798 |
"engines": {
|
3799 |
"node": ">=6"
|
3800 |
}
|
@@ -4274,9 +4287,9 @@
|
|
4274 |
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
|
4275 |
},
|
4276 |
"node_modules/electron-to-chromium": {
|
4277 |
-
"version": "1.4.
|
4278 |
-
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.
|
4279 |
-
"integrity": "sha512-
|
4280 |
},
|
4281 |
"node_modules/elliptic": {
|
4282 |
"version": "6.5.4",
|
@@ -4404,13 +4417,13 @@
|
|
4404 |
}
|
4405 |
},
|
4406 |
"node_modules/es-iterator-helpers": {
|
4407 |
-
"version": "1.0.
|
4408 |
-
"resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.
|
4409 |
-
"integrity": "sha512-
|
4410 |
"dependencies": {
|
4411 |
"call-bind": "^1.0.7",
|
4412 |
"define-properties": "^1.2.1",
|
4413 |
-
"es-abstract": "^1.23.
|
4414 |
"es-errors": "^1.3.0",
|
4415 |
"es-set-tostringtag": "^2.0.3",
|
4416 |
"function-bind": "^1.1.2",
|
@@ -6335,11 +6348,11 @@
|
|
6335 |
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
|
6336 |
},
|
6337 |
"node_modules/next": {
|
6338 |
-
"version": "14.2.
|
6339 |
-
"resolved": "https://registry.npmjs.org/next/-/next-14.2.
|
6340 |
-
"integrity": "sha512-
|
6341 |
"dependencies": {
|
6342 |
-
"@next/env": "14.2.
|
6343 |
"@swc/helpers": "0.5.5",
|
6344 |
"busboy": "1.6.0",
|
6345 |
"caniuse-lite": "^1.0.30001579",
|
@@ -6354,15 +6367,15 @@
|
|
6354 |
"node": ">=18.17.0"
|
6355 |
},
|
6356 |
"optionalDependencies": {
|
6357 |
-
"@next/swc-darwin-arm64": "14.2.
|
6358 |
-
"@next/swc-darwin-x64": "14.2.
|
6359 |
-
"@next/swc-linux-arm64-gnu": "14.2.
|
6360 |
-
"@next/swc-linux-arm64-musl": "14.2.
|
6361 |
-
"@next/swc-linux-x64-gnu": "14.2.
|
6362 |
-
"@next/swc-linux-x64-musl": "14.2.
|
6363 |
-
"@next/swc-win32-arm64-msvc": "14.2.
|
6364 |
-
"@next/swc-win32-ia32-msvc": "14.2.
|
6365 |
-
"@next/swc-win32-x64-msvc": "14.2.
|
6366 |
},
|
6367 |
"peerDependencies": {
|
6368 |
"@opentelemetry/api": "^1.1.0",
|
@@ -6616,9 +6629,9 @@
|
|
6616 |
}
|
6617 |
},
|
6618 |
"node_modules/openai": {
|
6619 |
-
"version": "4.38.
|
6620 |
-
"resolved": "https://registry.npmjs.org/openai/-/openai-4.38.
|
6621 |
-
"integrity": "sha512-
|
6622 |
"dependencies": {
|
6623 |
"@types/node": "^18.11.18",
|
6624 |
"@types/node-fetch": "^2.6.4",
|
@@ -6746,9 +6759,9 @@
|
|
6746 |
}
|
6747 |
},
|
6748 |
"node_modules/path-scurry/node_modules/lru-cache": {
|
6749 |
-
"version": "10.2.
|
6750 |
-
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.
|
6751 |
-
"integrity": "sha512-
|
6752 |
"engines": {
|
6753 |
"node": "14 || >=16.14"
|
6754 |
}
|
@@ -6990,6 +7003,14 @@
|
|
6990 |
"node": ">=6"
|
6991 |
}
|
6992 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6993 |
"node_modules/qs": {
|
6994 |
"version": "6.12.1",
|
6995 |
"resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz",
|
@@ -7433,9 +7454,9 @@
|
|
7433 |
}
|
7434 |
},
|
7435 |
"node_modules/scheduler": {
|
7436 |
-
"version": "0.23.
|
7437 |
-
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.
|
7438 |
-
"integrity": "sha512-
|
7439 |
"dependencies": {
|
7440 |
"loose-envify": "^1.1.0"
|
7441 |
}
|
@@ -8097,9 +8118,9 @@
|
|
8097 |
}
|
8098 |
},
|
8099 |
"node_modules/three": {
|
8100 |
-
"version": "0.
|
8101 |
-
"resolved": "https://registry.npmjs.org/three/-/three-0.
|
8102 |
-
"integrity": "sha512-
|
8103 |
"peer": true
|
8104 |
},
|
8105 |
"node_modules/to-regex-range": {
|
@@ -8227,9 +8248,9 @@
|
|
8227 |
}
|
8228 |
},
|
8229 |
"node_modules/type-fest": {
|
8230 |
-
"version": "4.
|
8231 |
-
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.
|
8232 |
-
"integrity": "sha512-
|
8233 |
"engines": {
|
8234 |
"node": ">=16"
|
8235 |
},
|
@@ -8315,9 +8336,9 @@
|
|
8315 |
}
|
8316 |
},
|
8317 |
"node_modules/typescript": {
|
8318 |
-
"version": "5.4.
|
8319 |
-
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.
|
8320 |
-
"integrity": "sha512-
|
8321 |
"bin": {
|
8322 |
"tsc": "bin/tsc",
|
8323 |
"tsserver": "bin/tsserver"
|
|
|
8 |
"name": "ai-tube",
|
9 |
"version": "0.0.0",
|
10 |
"dependencies": {
|
11 |
+
"@aitube/clap": "^0.0.6",
|
12 |
"@huggingface/hub": "0.12.3-oauth",
|
13 |
"@huggingface/inference": "^2.6.7",
|
14 |
"@jcoreio/async-throttle": "^1.6.0",
|
|
|
96 |
"temp-dir": "^3.0.0",
|
97 |
"ts-node": "^10.9.2",
|
98 |
"type-fest": "^4.8.2",
|
99 |
+
"typescript": "^5.4.5",
|
100 |
"usehooks-ts": "^2.9.1",
|
101 |
"uuid": "^9.0.1",
|
102 |
"yaml": "^2.3.4",
|
|
|
119 |
"node": ">=0.10.0"
|
120 |
}
|
121 |
},
|
122 |
+
"node_modules/@aitube/clap": {
|
123 |
+
"version": "0.0.6",
|
124 |
+
"resolved": "https://registry.npmjs.org/@aitube/clap/-/clap-0.0.6.tgz",
|
125 |
+
"integrity": "sha512-SPo90RBnOJCmp+DqzxllNOcp38AbHSzqkAbYEudRiubqWHDF1GGqYi25gCdG7bFIWH+8evjSiiwsjkzedpbhoA==",
|
126 |
+
"dependencies": {
|
127 |
+
"pure-uuid": "^1.8.1",
|
128 |
+
"yaml": "^2.4.1"
|
129 |
+
},
|
130 |
+
"peerDependencies": {
|
131 |
+
"typescript": "^5.4.5"
|
132 |
+
}
|
133 |
+
},
|
134 |
"node_modules/@alloc/quick-lru": {
|
135 |
"version": "5.2.0",
|
136 |
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
|
|
|
1507 |
}
|
1508 |
},
|
1509 |
"node_modules/@mediapipe/tasks-vision": {
|
1510 |
+
"version": "0.10.13-rc.20240426",
|
1511 |
+
"resolved": "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.13-rc.20240426.tgz",
|
1512 |
+
"integrity": "sha512-YyickIMLXr2/pEOZ00bHYWfWmCAwC8uRv0Ek6haQvnzahwfiw4Evlka3XRa8SxL4X7p432puS558xAm5h0SJTA=="
|
1513 |
},
|
1514 |
"node_modules/@next/env": {
|
1515 |
+
"version": "14.2.3",
|
1516 |
+
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.3.tgz",
|
1517 |
+
"integrity": "sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA=="
|
1518 |
},
|
1519 |
"node_modules/@next/eslint-plugin-next": {
|
1520 |
"version": "13.4.10",
|
|
|
1525 |
}
|
1526 |
},
|
1527 |
"node_modules/@next/swc-darwin-arm64": {
|
1528 |
+
"version": "14.2.3",
|
1529 |
+
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.3.tgz",
|
1530 |
+
"integrity": "sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==",
|
1531 |
"cpu": [
|
1532 |
"arm64"
|
1533 |
],
|
|
|
1540 |
}
|
1541 |
},
|
1542 |
"node_modules/@next/swc-darwin-x64": {
|
1543 |
+
"version": "14.2.3",
|
1544 |
+
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.3.tgz",
|
1545 |
+
"integrity": "sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==",
|
1546 |
"cpu": [
|
1547 |
"x64"
|
1548 |
],
|
|
|
1555 |
}
|
1556 |
},
|
1557 |
"node_modules/@next/swc-linux-arm64-gnu": {
|
1558 |
+
"version": "14.2.3",
|
1559 |
+
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.3.tgz",
|
1560 |
+
"integrity": "sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==",
|
1561 |
"cpu": [
|
1562 |
"arm64"
|
1563 |
],
|
|
|
1570 |
}
|
1571 |
},
|
1572 |
"node_modules/@next/swc-linux-arm64-musl": {
|
1573 |
+
"version": "14.2.3",
|
1574 |
+
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.3.tgz",
|
1575 |
+
"integrity": "sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==",
|
1576 |
"cpu": [
|
1577 |
"arm64"
|
1578 |
],
|
|
|
1585 |
}
|
1586 |
},
|
1587 |
"node_modules/@next/swc-linux-x64-gnu": {
|
1588 |
+
"version": "14.2.3",
|
1589 |
+
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz",
|
1590 |
+
"integrity": "sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==",
|
1591 |
"cpu": [
|
1592 |
"x64"
|
1593 |
],
|
|
|
1600 |
}
|
1601 |
},
|
1602 |
"node_modules/@next/swc-linux-x64-musl": {
|
1603 |
+
"version": "14.2.3",
|
1604 |
+
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz",
|
1605 |
+
"integrity": "sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==",
|
1606 |
"cpu": [
|
1607 |
"x64"
|
1608 |
],
|
|
|
1615 |
}
|
1616 |
},
|
1617 |
"node_modules/@next/swc-win32-arm64-msvc": {
|
1618 |
+
"version": "14.2.3",
|
1619 |
+
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz",
|
1620 |
+
"integrity": "sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==",
|
1621 |
"cpu": [
|
1622 |
"arm64"
|
1623 |
],
|
|
|
1630 |
}
|
1631 |
},
|
1632 |
"node_modules/@next/swc-win32-ia32-msvc": {
|
1633 |
+
"version": "14.2.3",
|
1634 |
+
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz",
|
1635 |
+
"integrity": "sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==",
|
1636 |
"cpu": [
|
1637 |
"ia32"
|
1638 |
],
|
|
|
1645 |
}
|
1646 |
},
|
1647 |
"node_modules/@next/swc-win32-x64-msvc": {
|
1648 |
+
"version": "14.2.3",
|
1649 |
+
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz",
|
1650 |
+
"integrity": "sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==",
|
1651 |
"cpu": [
|
1652 |
"x64"
|
1653 |
],
|
|
|
3805 |
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
|
3806 |
},
|
3807 |
"node_modules/clsx": {
|
3808 |
+
"version": "2.1.1",
|
3809 |
+
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
3810 |
+
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
3811 |
"engines": {
|
3812 |
"node": ">=6"
|
3813 |
}
|
|
|
4287 |
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
|
4288 |
},
|
4289 |
"node_modules/electron-to-chromium": {
|
4290 |
+
"version": "1.4.750",
|
4291 |
+
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.750.tgz",
|
4292 |
+
"integrity": "sha512-9ItEpeu15hW5m8jKdriL+BQrgwDTXEL9pn4SkillWFu73ZNNNQ2BKKLS+ZHv2vC9UkNhosAeyfxOf/5OSeTCPA=="
|
4293 |
},
|
4294 |
"node_modules/elliptic": {
|
4295 |
"version": "6.5.4",
|
|
|
4417 |
}
|
4418 |
},
|
4419 |
"node_modules/es-iterator-helpers": {
|
4420 |
+
"version": "1.0.19",
|
4421 |
+
"resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz",
|
4422 |
+
"integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==",
|
4423 |
"dependencies": {
|
4424 |
"call-bind": "^1.0.7",
|
4425 |
"define-properties": "^1.2.1",
|
4426 |
+
"es-abstract": "^1.23.3",
|
4427 |
"es-errors": "^1.3.0",
|
4428 |
"es-set-tostringtag": "^2.0.3",
|
4429 |
"function-bind": "^1.1.2",
|
|
|
6348 |
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
|
6349 |
},
|
6350 |
"node_modules/next": {
|
6351 |
+
"version": "14.2.3",
|
6352 |
+
"resolved": "https://registry.npmjs.org/next/-/next-14.2.3.tgz",
|
6353 |
+
"integrity": "sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A==",
|
6354 |
"dependencies": {
|
6355 |
+
"@next/env": "14.2.3",
|
6356 |
"@swc/helpers": "0.5.5",
|
6357 |
"busboy": "1.6.0",
|
6358 |
"caniuse-lite": "^1.0.30001579",
|
|
|
6367 |
"node": ">=18.17.0"
|
6368 |
},
|
6369 |
"optionalDependencies": {
|
6370 |
+
"@next/swc-darwin-arm64": "14.2.3",
|
6371 |
+
"@next/swc-darwin-x64": "14.2.3",
|
6372 |
+
"@next/swc-linux-arm64-gnu": "14.2.3",
|
6373 |
+
"@next/swc-linux-arm64-musl": "14.2.3",
|
6374 |
+
"@next/swc-linux-x64-gnu": "14.2.3",
|
6375 |
+
"@next/swc-linux-x64-musl": "14.2.3",
|
6376 |
+
"@next/swc-win32-arm64-msvc": "14.2.3",
|
6377 |
+
"@next/swc-win32-ia32-msvc": "14.2.3",
|
6378 |
+
"@next/swc-win32-x64-msvc": "14.2.3"
|
6379 |
},
|
6380 |
"peerDependencies": {
|
6381 |
"@opentelemetry/api": "^1.1.0",
|
|
|
6629 |
}
|
6630 |
},
|
6631 |
"node_modules/openai": {
|
6632 |
+
"version": "4.38.5",
|
6633 |
+
"resolved": "https://registry.npmjs.org/openai/-/openai-4.38.5.tgz",
|
6634 |
+
"integrity": "sha512-Ym5GJL98ZhLJJ7enBx53jjG3vwN/fsB+Ozh46nnRZZS9W1NiYqbwkJ+sXd3dkCIiWIgcyyOPL2Zr8SQAzbpj3g==",
|
6635 |
"dependencies": {
|
6636 |
"@types/node": "^18.11.18",
|
6637 |
"@types/node-fetch": "^2.6.4",
|
|
|
6759 |
}
|
6760 |
},
|
6761 |
"node_modules/path-scurry/node_modules/lru-cache": {
|
6762 |
+
"version": "10.2.1",
|
6763 |
+
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.1.tgz",
|
6764 |
+
"integrity": "sha512-tS24spDe/zXhWbNPErCHs/AGOzbKGHT+ybSBqmdLm8WZ1xXLWvH8Qn71QPAlqVhd0qUTWjy+Kl9JmISgDdEjsA==",
|
6765 |
"engines": {
|
6766 |
"node": "14 || >=16.14"
|
6767 |
}
|
|
|
7003 |
"node": ">=6"
|
7004 |
}
|
7005 |
},
|
7006 |
+
"node_modules/pure-uuid": {
|
7007 |
+
"version": "1.8.1",
|
7008 |
+
"resolved": "https://registry.npmjs.org/pure-uuid/-/pure-uuid-1.8.1.tgz",
|
7009 |
+
"integrity": "sha512-PIwHXU7NZb/wTBwUfzCSjI85tfwx6DQOm74sRLtNLH8KHsFZEvAQbBQdz7E5ij8SNSv9WGdQPWiiM6NpNIeNfA==",
|
7010 |
+
"engines": {
|
7011 |
+
"node": ">=8.0.0"
|
7012 |
+
}
|
7013 |
+
},
|
7014 |
"node_modules/qs": {
|
7015 |
"version": "6.12.1",
|
7016 |
"resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz",
|
|
|
7454 |
}
|
7455 |
},
|
7456 |
"node_modules/scheduler": {
|
7457 |
+
"version": "0.23.2",
|
7458 |
+
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
|
7459 |
+
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
|
7460 |
"dependencies": {
|
7461 |
"loose-envify": "^1.1.0"
|
7462 |
}
|
|
|
8118 |
}
|
8119 |
},
|
8120 |
"node_modules/three": {
|
8121 |
+
"version": "0.164.1",
|
8122 |
+
"resolved": "https://registry.npmjs.org/three/-/three-0.164.1.tgz",
|
8123 |
+
"integrity": "sha512-iC/hUBbl1vzFny7f5GtqzVXYjMJKaTPxiCxXfrvVdBi1Sf+jhd1CAkitiFwC7mIBFCo3MrDLJG97yisoaWig0w==",
|
8124 |
"peer": true
|
8125 |
},
|
8126 |
"node_modules/to-regex-range": {
|
|
|
8248 |
}
|
8249 |
},
|
8250 |
"node_modules/type-fest": {
|
8251 |
+
"version": "4.17.0",
|
8252 |
+
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.17.0.tgz",
|
8253 |
+
"integrity": "sha512-9flrz1zkfLRH3jO3bLflmTxryzKMxVa7841VeMgBaNQGY6vH4RCcpN/sQLB7mQQYh1GZ5utT2deypMuCy4yicw==",
|
8254 |
"engines": {
|
8255 |
"node": ">=16"
|
8256 |
},
|
|
|
8336 |
}
|
8337 |
},
|
8338 |
"node_modules/typescript": {
|
8339 |
+
"version": "5.4.5",
|
8340 |
+
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
|
8341 |
+
"integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
|
8342 |
"bin": {
|
8343 |
"tsc": "bin/tsc",
|
8344 |
"tsserver": "bin/tsserver"
|
package.json
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
{
|
2 |
-
"name": "
|
3 |
"version": "0.0.0",
|
4 |
"private": true,
|
5 |
"scripts": {
|
@@ -9,6 +9,7 @@
|
|
9 |
"lint": "next lint"
|
10 |
},
|
11 |
"dependencies": {
|
|
|
12 |
"@huggingface/hub": "0.12.3-oauth",
|
13 |
"@huggingface/inference": "^2.6.7",
|
14 |
"@jcoreio/async-throttle": "^1.6.0",
|
@@ -96,7 +97,7 @@
|
|
96 |
"temp-dir": "^3.0.0",
|
97 |
"ts-node": "^10.9.2",
|
98 |
"type-fest": "^4.8.2",
|
99 |
-
"typescript": "5.4.
|
100 |
"usehooks-ts": "^2.9.1",
|
101 |
"uuid": "^9.0.1",
|
102 |
"yaml": "^2.3.4",
|
|
|
1 |
{
|
2 |
+
"name": "@aitube/website",
|
3 |
"version": "0.0.0",
|
4 |
"private": true,
|
5 |
"scripts": {
|
|
|
9 |
"lint": "next lint"
|
10 |
},
|
11 |
"dependencies": {
|
12 |
+
"@aitube/clap": "^0.0.6",
|
13 |
"@huggingface/hub": "0.12.3-oauth",
|
14 |
"@huggingface/inference": "^2.6.7",
|
15 |
"@jcoreio/async-throttle": "^1.6.0",
|
|
|
97 |
"temp-dir": "^3.0.0",
|
98 |
"ts-node": "^10.9.2",
|
99 |
"type-fest": "^4.8.2",
|
100 |
+
"typescript": "^5.4.5",
|
101 |
"usehooks-ts": "^2.9.1",
|
102 |
"uuid": "^9.0.1",
|
103 |
"yaml": "^2.3.4",
|
src/app/api/actions/ai-tube-hf/downloadClapProject.ts
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
import { v4 as uuidv4 } from "uuid"
|
2 |
import { Credentials } from "@/lib/huggingface/hub/src"
|
3 |
|
4 |
-
import { ClapProject } from "
|
|
|
5 |
import { ChannelInfo, MediaInfo, VideoRequest } from "@/types/general"
|
6 |
import { defaultVideoModel } from "@/app/config"
|
7 |
-
import { parseClap } from "@/lib/clap/parseClap"
|
8 |
|
9 |
import { parseVideoModelName } from "../../utils/parseVideoModelName"
|
10 |
import { computeOrientationProjectionWidthHeight } from "../../utils/computeOrientationProjectionWidthHeight"
|
@@ -35,7 +35,7 @@ export async function downloadClapProject({
|
|
35 |
expectedMimeType: "application/gzip"
|
36 |
})
|
37 |
|
38 |
-
const clapProject = await parseClap(clapString)
|
39 |
|
40 |
const id = clapProject.meta.id || uuidv4()
|
41 |
|
|
|
1 |
import { v4 as uuidv4 } from "uuid"
|
2 |
import { Credentials } from "@/lib/huggingface/hub/src"
|
3 |
|
4 |
+
import { ClapProject, parseClap } from "@aitube/clap"
|
5 |
+
|
6 |
import { ChannelInfo, MediaInfo, VideoRequest } from "@/types/general"
|
7 |
import { defaultVideoModel } from "@/app/config"
|
|
|
8 |
|
9 |
import { parseVideoModelName } from "../../utils/parseVideoModelName"
|
10 |
import { computeOrientationProjectionWidthHeight } from "../../utils/computeOrientationProjectionWidthHeight"
|
|
|
35 |
expectedMimeType: "application/gzip"
|
36 |
})
|
37 |
|
38 |
+
const clapProject: ClapProject = await parseClap(clapString)
|
39 |
|
40 |
const id = clapProject.meta.id || uuidv4()
|
41 |
|
src/app/api/generate/models/generateAudioID.ts
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export async function generateAudioID({
|
2 |
+
prompt,
|
3 |
+
// negativePrompt,
|
4 |
+
seed,
|
5 |
+
}: {
|
6 |
+
prompt: string
|
7 |
+
// negativePrompt?: string
|
8 |
+
seed?: number
|
9 |
+
}) {
|
10 |
+
// TODO: call Parler-TTS
|
11 |
+
return "TODO JULIAN"
|
12 |
+
}
|
src/app/api/generate/models/generateImageID.ts
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
import { generateSeed } from "@aitube/clap"
|
3 |
+
|
4 |
+
import { sleep } from "@/lib/utils/sleep"
|
5 |
+
import { getValidNumber } from "@/lib/utils/getValidNumber"
|
6 |
+
|
7 |
+
import { newRender, getRender } from "../../providers/videochain/renderWithVideoChain"
|
8 |
+
import { getNegativePrompt, getPositivePrompt } from "../../utils/imagePrompts"
|
9 |
+
|
10 |
+
export async function generateImageID({
|
11 |
+
prompt,
|
12 |
+
// negativePrompt,
|
13 |
+
seed,
|
14 |
+
}: {
|
15 |
+
prompt: string
|
16 |
+
// negativePrompt?: string
|
17 |
+
seed?: number
|
18 |
+
}) {
|
19 |
+
|
20 |
+
// those can be constants for a face ID
|
21 |
+
// also we want something a bit portrait-ish
|
22 |
+
// but this risk creating a lot of variability in poses
|
23 |
+
// so perhaps we should use a controlnet to condition the face scale and position,
|
24 |
+
// to make sure it is uniform in size across all models
|
25 |
+
const width = 1024
|
26 |
+
const height = 768
|
27 |
+
|
28 |
+
// console.log("calling await newRender")
|
29 |
+
prompt = getPositivePrompt(prompt)
|
30 |
+
const negativePrompt = getNegativePrompt()
|
31 |
+
|
32 |
+
let render = await newRender({
|
33 |
+
prompt,
|
34 |
+
negativePrompt,
|
35 |
+
nbFrames: 1,
|
36 |
+
nbFPS: 1,
|
37 |
+
|
38 |
+
// note: for the model ID we might want to maximize things here,
|
39 |
+
// and maybe not use the "turbo" - but I'm not sure
|
40 |
+
width,
|
41 |
+
height,
|
42 |
+
nbSteps: 8,
|
43 |
+
turbo: true,
|
44 |
+
|
45 |
+
shouldRenewCache: true,
|
46 |
+
seed: seed || generateSeed()
|
47 |
+
})
|
48 |
+
|
49 |
+
let attempts = 10
|
50 |
+
|
51 |
+
while (attempts-- > 0) {
|
52 |
+
if (render.status === "completed") {
|
53 |
+
return render.assetUrl
|
54 |
+
}
|
55 |
+
|
56 |
+
if (render.status === "error") {
|
57 |
+
console.error(render.error)
|
58 |
+
throw new Error(`failed to generate the image ${render.error}`)
|
59 |
+
}
|
60 |
+
|
61 |
+
await sleep(2000) // minimum wait time
|
62 |
+
|
63 |
+
// console.log("asking getRender")
|
64 |
+
render = await getRender(render.renderId)
|
65 |
+
}
|
66 |
+
|
67 |
+
throw new Error(`failed to generate the image`)
|
68 |
+
}
|
src/app/api/generate/models/route.ts
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { NextResponse, NextRequest } from "next/server"
|
2 |
+
import queryString from "query-string"
|
3 |
+
|
4 |
+
import { parseClap, serializeClap, ClapModel } from "@aitube/clap"
|
5 |
+
import { getToken } from "@/app/api/auth/getToken"
|
6 |
+
|
7 |
+
import { generateImageID } from "./generateImageID"
|
8 |
+
import { generateAudioID } from "./generateAudioID"
|
9 |
+
|
10 |
+
export async function POST(req: NextRequest) {
|
11 |
+
|
12 |
+
const qs = queryString.parseUrl(req.url || "")
|
13 |
+
const query = (qs || {}).query
|
14 |
+
|
15 |
+
// TODO: use query parameters to determine *what* to generate:
|
16 |
+
/*
|
17 |
+
let prompt = ""
|
18 |
+
try {
|
19 |
+
prompt = decodeURIComponent(query?.p?.toString() || "").trim()
|
20 |
+
} catch (err) {}
|
21 |
+
if (!prompt) {
|
22 |
+
return NextResponse.json({ error: 'no prompt provided' }, { status: 400 });
|
23 |
+
}
|
24 |
+
|
25 |
+
if (!prompt.length) { throw new Error(`please provide a prompt`) }
|
26 |
+
*/
|
27 |
+
|
28 |
+
console.log("[api/generate/models] request:", prompt)
|
29 |
+
|
30 |
+
const jwtToken = await getToken({ user: "anonymous" })
|
31 |
+
|
32 |
+
const blob = await req.blob()
|
33 |
+
|
34 |
+
const clap = await parseClap(blob)
|
35 |
+
|
36 |
+
if (!clap.models.length) { throw new Error(`please provide at least one model`) }
|
37 |
+
|
38 |
+
for (const model of clap.models) {
|
39 |
+
|
40 |
+
// TASK 1: GENERATE THE IMAGE PROMPT IF MISSING
|
41 |
+
if (!model.imagePrompt) {
|
42 |
+
model.imagePrompt = "a man with a beard"
|
43 |
+
}
|
44 |
+
|
45 |
+
// TASK 2: GENERATE THE IMAGE ID IF MISSING
|
46 |
+
if (!model.imageId) {
|
47 |
+
model.imageId = await generateImageID({
|
48 |
+
prompt: model.imagePrompt,
|
49 |
+
seed: model.seed
|
50 |
+
})
|
51 |
+
}
|
52 |
+
|
53 |
+
// TASK 3: GENERATE THE AUDIO PROMPT IF MISSING
|
54 |
+
if (!model.audioPrompt) {
|
55 |
+
model.audioPrompt = "a man with a beard"
|
56 |
+
}
|
57 |
+
|
58 |
+
// TASK 4: GENERATE THE AUDIO ID IF MISSING
|
59 |
+
|
60 |
+
// TODO here: call Parler-TTS or a generic audio generator
|
61 |
+
if (!model.audioId) {
|
62 |
+
model.audioId = await generateAudioID({
|
63 |
+
prompt: model.audioPrompt,
|
64 |
+
seed: model.seed
|
65 |
+
})
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
+
console.log(`[api/generate/models] returning the clap extended with the model`)
|
70 |
+
|
71 |
+
return new NextResponse(await serializeClap(clap), {
|
72 |
+
status: 200,
|
73 |
+
headers: new Headers({ "content-type": "application/x-gzip" }),
|
74 |
+
})
|
75 |
+
}
|
src/app/api/generate/models/systemPrompt.ts
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
|
3 |
+
export const systemPrompt = ""
|
src/app/api/generate/story/route.ts
CHANGED
@@ -1,13 +1,10 @@
|
|
1 |
import { NextResponse, NextRequest } from "next/server"
|
|
|
2 |
|
3 |
-
import { generateClapFromSimpleStory } from "@/lib/clap/generateClapFromSimpleStory"
|
4 |
-
import { serializeClap } from "@/lib/clap/serializeClap"
|
5 |
-
import { getValidNumber } from "@/lib/utils/getValidNumber"
|
6 |
-
import { newClap } from "@/lib/clap/newClap"
|
7 |
import { predict } from "../../providers/huggingface/predictWithHuggingFace"
|
8 |
-
import { systemPrompt } from "./systemPrompt"
|
9 |
import { parseRawStringToYAML } from "../../utils/parseRawStringToYAML"
|
10 |
-
|
|
|
11 |
|
12 |
export type LatentStory = {
|
13 |
title: string
|
@@ -61,7 +58,7 @@ export async function POST(req: NextRequest) {
|
|
61 |
let currentElapsedTimeInMs = 0
|
62 |
let currentSegmentDurationInMs = defaultSegmentDurationInMs
|
63 |
|
64 |
-
const clap = newClap({
|
65 |
meta: {
|
66 |
title: "Not needed", // we don't need a title actually
|
67 |
description: "This video has been generated using AI",
|
|
|
1 |
import { NextResponse, NextRequest } from "next/server"
|
2 |
+
import { ClapProject, getValidNumber, newClap, newSegment, serializeClap } from "@aitube/clap"
|
3 |
|
|
|
|
|
|
|
|
|
4 |
import { predict } from "../../providers/huggingface/predictWithHuggingFace"
|
|
|
5 |
import { parseRawStringToYAML } from "../../utils/parseRawStringToYAML"
|
6 |
+
|
7 |
+
import { systemPrompt } from "./systemPrompt"
|
8 |
|
9 |
export type LatentStory = {
|
10 |
title: string
|
|
|
58 |
let currentElapsedTimeInMs = 0
|
59 |
let currentSegmentDurationInMs = defaultSegmentDurationInMs
|
60 |
|
61 |
+
const clap: ClapProject = newClap({
|
62 |
meta: {
|
63 |
title: "Not needed", // we don't need a title actually
|
64 |
description: "This video has been generated using AI",
|
src/app/api/generate/storyboards/generateStoryboard.ts
CHANGED
@@ -1,9 +1,8 @@
|
|
|
|
1 |
|
2 |
import { newRender, getRender } from "../../providers/videochain/renderWithVideoChain"
|
3 |
-
import { generateSeed } from "@/lib/utils/generateSeed"
|
4 |
import { sleep } from "@/lib/utils/sleep"
|
5 |
import { getNegativePrompt, getPositivePrompt } from "../../utils/imagePrompts"
|
6 |
-
import { getValidNumber } from "@/lib/utils/getValidNumber"
|
7 |
|
8 |
export async function generateStoryboard({
|
9 |
prompt,
|
|
|
1 |
+
import { generateSeed, getValidNumber } from "@aitube/clap"
|
2 |
|
3 |
import { newRender, getRender } from "../../providers/videochain/renderWithVideoChain"
|
|
|
4 |
import { sleep } from "@/lib/utils/sleep"
|
5 |
import { getNegativePrompt, getPositivePrompt } from "../../utils/imagePrompts"
|
|
|
6 |
|
7 |
export async function generateStoryboard({
|
8 |
prompt,
|
src/app/api/generate/storyboards/route.ts
CHANGED
@@ -1,13 +1,12 @@
|
|
1 |
import { NextResponse, NextRequest } from "next/server"
|
2 |
|
3 |
-
import { serializeClap } from "
|
4 |
-
|
5 |
import { startOfSegment1IsWithinSegment2 } from "@/lib/utils/startOfSegment1IsWithinSegment2"
|
6 |
import { getVideoPrompt } from "@/components/interface/latent-engine/core/prompts/getVideoPrompt"
|
7 |
-
import { newSegment } from "@/lib/clap/newSegment"
|
8 |
-
import { newRender, getRender } from "../../providers/videochain/renderWithVideoChain"
|
9 |
import { getToken } from "@/app/api/auth/getToken"
|
10 |
-
|
|
|
11 |
import { getPositivePrompt } from "../../utils/imagePrompts"
|
12 |
import { generateStoryboard } from "./generateStoryboard"
|
13 |
|
@@ -24,13 +23,13 @@ export async function POST(req: NextRequest) {
|
|
24 |
|
25 |
const blob = await req.blob()
|
26 |
|
27 |
-
const clap = await parseClap(blob)
|
28 |
|
29 |
if (!clap?.segments) { throw new Error(`no segment found in the provided clap!`) }
|
30 |
|
31 |
console.log(`[api/generate/storyboards] detected ${clap.segments.length} segments`)
|
32 |
|
33 |
-
const shotsSegments = clap.segments.filter(s => s.category === "camera")
|
34 |
console.log(`[api/generate/storyboards] detected ${shotsSegments.length} shots`)
|
35 |
|
36 |
if (shotsSegments.length > 32) {
|
@@ -39,15 +38,15 @@ export async function POST(req: NextRequest) {
|
|
39 |
|
40 |
for (const shotSegment of shotsSegments) {
|
41 |
|
42 |
-
const shotSegments = clap.segments.filter(s =>
|
43 |
startOfSegment1IsWithinSegment2(s, shotSegment)
|
44 |
)
|
45 |
|
46 |
-
const shotStoryboardSegments = shotSegments.filter(s =>
|
47 |
s.category === "storyboard"
|
48 |
)
|
49 |
|
50 |
-
let shotStoryboardSegment = shotStoryboardSegments.at(0)
|
51 |
|
52 |
console.log(`[api/generate/storyboards] shot [${shotSegment.startTimeInMs}:${shotSegment.endTimeInMs}] has ${shotSegments.length} segments (${shotStoryboardSegments.length} storyboards)`)
|
53 |
|
@@ -67,14 +66,14 @@ export async function POST(req: NextRequest) {
|
|
67 |
}
|
68 |
|
69 |
// TASK 2: GENERATE MISSING STORYBOARD PROMPT
|
70 |
-
if (!shotStoryboardSegment
|
71 |
// storyboard is missing, let's generate it
|
72 |
shotStoryboardSegment.prompt = getVideoPrompt(shotSegments, {}, [])
|
73 |
console.log(`[api/generate/storyboards] generating storyboard prompt: ${shotStoryboardSegment.prompt}`)
|
74 |
}
|
75 |
|
76 |
// TASK 3: GENERATE MISSING STORYBOARD BITMAP
|
77 |
-
if (!shotStoryboardSegment.assetUrl) {
|
78 |
console.log(`[api/generate/storyboards] generating image..`)
|
79 |
|
80 |
try {
|
@@ -88,9 +87,9 @@ export async function POST(req: NextRequest) {
|
|
88 |
throw err
|
89 |
}
|
90 |
|
91 |
-
console.log(`[api/generate/storyboards] generated storyboard image: ${shotStoryboardSegment
|
92 |
} else {
|
93 |
-
console.log(`[api/generate/storyboards] there is already a storyboard image: ${shotStoryboardSegment
|
94 |
}
|
95 |
}
|
96 |
|
|
|
1 |
import { NextResponse, NextRequest } from "next/server"
|
2 |
|
3 |
+
import { ClapProject, ClapSegment, newSegment, parseClap, serializeClap } from "@aitube/clap"
|
4 |
+
|
5 |
import { startOfSegment1IsWithinSegment2 } from "@/lib/utils/startOfSegment1IsWithinSegment2"
|
6 |
import { getVideoPrompt } from "@/components/interface/latent-engine/core/prompts/getVideoPrompt"
|
|
|
|
|
7 |
import { getToken } from "@/app/api/auth/getToken"
|
8 |
+
|
9 |
+
import { newRender, getRender } from "../../providers/videochain/renderWithVideoChain"
|
10 |
import { getPositivePrompt } from "../../utils/imagePrompts"
|
11 |
import { generateStoryboard } from "./generateStoryboard"
|
12 |
|
|
|
23 |
|
24 |
const blob = await req.blob()
|
25 |
|
26 |
+
const clap: ClapProject = await parseClap(blob)
|
27 |
|
28 |
if (!clap?.segments) { throw new Error(`no segment found in the provided clap!`) }
|
29 |
|
30 |
console.log(`[api/generate/storyboards] detected ${clap.segments.length} segments`)
|
31 |
|
32 |
+
const shotsSegments: ClapSegment[] = clap.segments.filter(s => s.category === "camera")
|
33 |
console.log(`[api/generate/storyboards] detected ${shotsSegments.length} shots`)
|
34 |
|
35 |
if (shotsSegments.length > 32) {
|
|
|
38 |
|
39 |
for (const shotSegment of shotsSegments) {
|
40 |
|
41 |
+
const shotSegments: ClapSegment[] = clap.segments.filter(s =>
|
42 |
startOfSegment1IsWithinSegment2(s, shotSegment)
|
43 |
)
|
44 |
|
45 |
+
const shotStoryboardSegments: ClapSegment[] = shotSegments.filter(s =>
|
46 |
s.category === "storyboard"
|
47 |
)
|
48 |
|
49 |
+
let shotStoryboardSegment: ClapSegment | undefined = shotStoryboardSegments.at(0)
|
50 |
|
51 |
console.log(`[api/generate/storyboards] shot [${shotSegment.startTimeInMs}:${shotSegment.endTimeInMs}] has ${shotSegments.length} segments (${shotStoryboardSegments.length} storyboards)`)
|
52 |
|
|
|
66 |
}
|
67 |
|
68 |
// TASK 2: GENERATE MISSING STORYBOARD PROMPT
|
69 |
+
if (shotStoryboardSegment && !shotStoryboardSegment?.prompt) {
|
70 |
// storyboard is missing, let's generate it
|
71 |
shotStoryboardSegment.prompt = getVideoPrompt(shotSegments, {}, [])
|
72 |
console.log(`[api/generate/storyboards] generating storyboard prompt: ${shotStoryboardSegment.prompt}`)
|
73 |
}
|
74 |
|
75 |
// TASK 3: GENERATE MISSING STORYBOARD BITMAP
|
76 |
+
if (shotStoryboardSegment && !shotStoryboardSegment.assetUrl) {
|
77 |
console.log(`[api/generate/storyboards] generating image..`)
|
78 |
|
79 |
try {
|
|
|
87 |
throw err
|
88 |
}
|
89 |
|
90 |
+
console.log(`[api/generate/storyboards] generated storyboard image: ${shotStoryboardSegment?.assetUrl?.slice?.(0, 50)}...`)
|
91 |
} else {
|
92 |
+
console.log(`[api/generate/storyboards] there is already a storyboard image: ${shotStoryboardSegment?.assetUrl?.slice?.(0, 50)}...`)
|
93 |
}
|
94 |
}
|
95 |
|
src/app/api/generate/video/route.ts
CHANGED
@@ -2,7 +2,8 @@ import { NextResponse, NextRequest } from "next/server"
|
|
2 |
|
3 |
// we hide/wrap the micro-service under a unified AiTube API
|
4 |
export async function POST(req: NextRequest, res: NextResponse) {
|
5 |
-
|
|
|
6 |
}
|
7 |
/*
|
8 |
Alternative solution (in case the redirect doesn't work):
|
|
|
2 |
|
3 |
// we hide/wrap the micro-service under a unified AiTube API
|
4 |
export async function POST(req: NextRequest, res: NextResponse) {
|
5 |
+
|
6 |
+
NextResponse.redirect(`${process.env.AI_TUBE_CLAP_EXPORTER_URL || "http://localhost:7860"}`)
|
7 |
}
|
8 |
/*
|
9 |
Alternative solution (in case the redirect doesn't work):
|
src/app/api/generators/clap/addLatentScenesToClap.ts
CHANGED
@@ -1,12 +1,8 @@
|
|
1 |
"use server"
|
2 |
|
3 |
-
import {
|
4 |
-
import { newSegment } from "@/lib/clap/newSegment"
|
5 |
|
6 |
import { LatentScenes } from "./types"
|
7 |
-
import { serializeClap } from "@/lib/clap/serializeClap"
|
8 |
-
import { getEmptyClap } from "@/lib/clap/emptyClap"
|
9 |
-
import { ClapProject } from "@/lib/clap/types"
|
10 |
|
11 |
let defaultSegmentDurationInMs = 2000
|
12 |
|
|
|
1 |
"use server"
|
2 |
|
3 |
+
import { ClapProject, newSegment } from "@aitube/clap"
|
|
|
4 |
|
5 |
import { LatentScenes } from "./types"
|
|
|
|
|
|
|
6 |
|
7 |
let defaultSegmentDurationInMs = 2000
|
8 |
|
src/app/api/generators/clap/continueClap.ts
CHANGED
@@ -1,13 +1,10 @@
|
|
1 |
"use server"
|
2 |
|
|
|
3 |
|
4 |
import { LatentScenes } from "./types"
|
5 |
import { addLatentScenesToClap } from "./addLatentScenesToClap"
|
6 |
import { getLatentScenes } from "./getLatentScenes"
|
7 |
-
import { serializeClap } from "@/lib/clap/serializeClap"
|
8 |
-
import { newClap } from "@/lib/clap/newClap"
|
9 |
-
import { getEmptyClap } from "@/lib/clap/emptyClap"
|
10 |
-
import { ClapProject } from "@/lib/clap/types"
|
11 |
|
12 |
/**
|
13 |
* Imagine the continuity of a Clap file
|
@@ -60,7 +57,7 @@ export async function continueClap({
|
|
60 |
// technically, it could also be transported as text
|
61 |
// (and gzipped automatically between the HTTP server and browser)
|
62 |
// but I think it is better to keep the idea of a dedicated file format
|
63 |
-
const archive = await serializeClap(clap)
|
64 |
|
65 |
return archive
|
66 |
}
|
|
|
1 |
"use server"
|
2 |
|
3 |
+
import { ClapProject, serializeClap } from "@aitube/clap"
|
4 |
|
5 |
import { LatentScenes } from "./types"
|
6 |
import { addLatentScenesToClap } from "./addLatentScenesToClap"
|
7 |
import { getLatentScenes } from "./getLatentScenes"
|
|
|
|
|
|
|
|
|
8 |
|
9 |
/**
|
10 |
* Imagine the continuity of a Clap file
|
|
|
57 |
// technically, it could also be transported as text
|
58 |
// (and gzipped automatically between the HTTP server and browser)
|
59 |
// but I think it is better to keep the idea of a dedicated file format
|
60 |
+
const archive: Blob = await serializeClap(clap)
|
61 |
|
62 |
return archive
|
63 |
}
|
src/app/api/generators/clap/generateClap.ts
CHANGED
@@ -1,12 +1,10 @@
|
|
1 |
"use server"
|
2 |
|
3 |
-
import { serializeClap } from "@/lib/clap/serializeClap"
|
4 |
-
import { newClap } from "@/lib/clap/newClap"
|
5 |
-
import { getEmptyClap } from "@/lib/clap/emptyClap"
|
6 |
|
7 |
import { LatentScenes } from "./types"
|
8 |
import { addLatentScenesToClap } from "./addLatentScenesToClap"
|
9 |
import { getLatentScenes } from "./getLatentScenes"
|
|
|
10 |
|
11 |
/**
|
12 |
* Generate a Clap file from scratch using a prompt
|
@@ -22,13 +20,13 @@ export async function generateClap({
|
|
22 |
debug: false,
|
23 |
}): Promise<Blob> {
|
24 |
|
25 |
-
const empty = await getEmptyClap()
|
26 |
|
27 |
if (!prompt?.length) {
|
28 |
return empty
|
29 |
}
|
30 |
|
31 |
-
let clap = newClap({
|
32 |
meta: {
|
33 |
title: "Latent content", // TODO "
|
34 |
description: "",
|
@@ -56,7 +54,7 @@ export async function generateClap({
|
|
56 |
debug,
|
57 |
})
|
58 |
|
59 |
-
const archive = await serializeClap(clap)
|
60 |
|
61 |
return archive
|
62 |
}
|
|
|
1 |
"use server"
|
2 |
|
|
|
|
|
|
|
3 |
|
4 |
import { LatentScenes } from "./types"
|
5 |
import { addLatentScenesToClap } from "./addLatentScenesToClap"
|
6 |
import { getLatentScenes } from "./getLatentScenes"
|
7 |
+
import { ClapProject, getEmptyClap, newClap, serializeClap } from "@aitube/clap"
|
8 |
|
9 |
/**
|
10 |
* Generate a Clap file from scratch using a prompt
|
|
|
20 |
debug: false,
|
21 |
}): Promise<Blob> {
|
22 |
|
23 |
+
const empty: Blob = await getEmptyClap()
|
24 |
|
25 |
if (!prompt?.length) {
|
26 |
return empty
|
27 |
}
|
28 |
|
29 |
+
let clap: ClapProject = newClap({
|
30 |
meta: {
|
31 |
title: "Latent content", // TODO "
|
32 |
description: "",
|
|
|
54 |
debug,
|
55 |
})
|
56 |
|
57 |
+
const archive: Blob = await serializeClap(clap)
|
58 |
|
59 |
return archive
|
60 |
}
|
src/app/api/generators/search/unknownObjectToLatentSearchResults.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
-
import { generateSeed } from "
|
|
|
2 |
import { parseString } from "../../utils/parseString"
|
3 |
import { parseStringArray } from "../../utils/parseStringArray"
|
4 |
import { LatentSearchResult, LatentSearchResults } from "./types"
|
|
|
1 |
+
import { generateSeed } from "@aitube/clap"
|
2 |
+
|
3 |
import { parseString } from "../../utils/parseString"
|
4 |
import { parseStringArray } from "../../utils/parseStringArray"
|
5 |
import { LatentSearchResult, LatentSearchResults } from "./types"
|
src/app/api/resolvers/clap/route.ts
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
import { NextResponse, NextRequest } from "next/server"
|
2 |
import queryString from "query-string"
|
|
|
3 |
import { generateClap } from "../../generators/clap/generateClap"
|
4 |
|
5 |
export async function GET(req: NextRequest) {
|
|
|
1 |
import { NextResponse, NextRequest } from "next/server"
|
2 |
import queryString from "query-string"
|
3 |
+
|
4 |
import { generateClap } from "../../generators/clap/generateClap"
|
5 |
|
6 |
export async function GET(req: NextRequest) {
|
src/app/api/resolvers/image/route.ts
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
import { NextResponse, NextRequest } from "next/server"
|
2 |
import { createSecretKey } from "node:crypto"
|
3 |
|
|
|
4 |
import queryString from "query-string"
|
5 |
|
6 |
import { newRender, getRender } from "../../providers/videochain/renderWithVideoChain"
|
7 |
-
import { generateSeed } from "@/lib/utils/generateSeed"
|
8 |
import { sleep } from "@/lib/utils/sleep"
|
9 |
import { getNegativePrompt, getPositivePrompt } from "../../utils/imagePrompts"
|
10 |
import { getContentType } from "@/lib/data/getContentType"
|
|
|
1 |
import { NextResponse, NextRequest } from "next/server"
|
2 |
import { createSecretKey } from "node:crypto"
|
3 |
|
4 |
+
import { generateSeed } from "@aitube/clap"
|
5 |
import queryString from "query-string"
|
6 |
|
7 |
import { newRender, getRender } from "../../providers/videochain/renderWithVideoChain"
|
|
|
8 |
import { sleep } from "@/lib/utils/sleep"
|
9 |
import { getNegativePrompt, getPositivePrompt } from "../../utils/imagePrompts"
|
10 |
import { getContentType } from "@/lib/data/getContentType"
|
src/app/api/resolvers/video/route.ts
CHANGED
@@ -3,8 +3,9 @@ import queryString from "query-string"
|
|
3 |
import { createSecretKey } from "crypto"
|
4 |
import { jwtVerify } from "jose"
|
5 |
|
|
|
|
|
6 |
import { newRender, getRender } from "../../providers/videochain/renderWithVideoChain"
|
7 |
-
import { generateSeed } from "@/lib/utils/generateSeed"
|
8 |
import { sleep } from "@/lib/utils/sleep"
|
9 |
import { getNegativePrompt, getPositivePrompt } from "../../utils/imagePrompts"
|
10 |
import { getContentType } from "@/lib/data/getContentType"
|
|
|
3 |
import { createSecretKey } from "crypto"
|
4 |
import { jwtVerify } from "jose"
|
5 |
|
6 |
+
import { generateSeed } from "@aitube/clap"
|
7 |
+
|
8 |
import { newRender, getRender } from "../../providers/videochain/renderWithVideoChain"
|
|
|
9 |
import { sleep } from "@/lib/utils/sleep"
|
10 |
import { getNegativePrompt, getPositivePrompt } from "../../utils/imagePrompts"
|
11 |
import { getContentType } from "@/lib/data/getContentType"
|
src/app/dream/spoiler.tsx
CHANGED
@@ -1,8 +1,7 @@
|
|
1 |
import { LatentQueryProps } from "@/types/general"
|
|
|
2 |
|
3 |
import { Main } from "../main"
|
4 |
-
import { generateClapFromSimpleStory } from "@/lib/clap/generateClapFromSimpleStory"
|
5 |
-
import { clapToDataUri } from "@/lib/clap/clapToDataUri"
|
6 |
import { getNewMediaInfo } from "../api/generators/search/getNewMediaInfo"
|
7 |
import { getToken } from "../api/auth/getToken"
|
8 |
|
|
|
1 |
import { LatentQueryProps } from "@/types/general"
|
2 |
+
import { clapToDataUri, generateClapFromSimpleStory } from "@aitube/clap"
|
3 |
|
4 |
import { Main } from "../main"
|
|
|
|
|
5 |
import { getNewMediaInfo } from "../api/generators/search/getNewMediaInfo"
|
6 |
import { getToken } from "../api/auth/getToken"
|
7 |
|
src/components/interface/latent-engine/core/engine.tsx
CHANGED
@@ -5,8 +5,6 @@ import { useLocalStorage } from "usehooks-ts"
|
|
5 |
|
6 |
import { cn } from "@/lib/utils/cn"
|
7 |
import { MediaInfo } from "@/types/general"
|
8 |
-
import { serializeClap } from "@/lib/clap/serializeClap"
|
9 |
-
import { generateClapFromSimpleStory } from "@/lib/clap/generateClapFromSimpleStory"
|
10 |
|
11 |
import { useLatentEngine } from "./useLatentEngine"
|
12 |
import { PlayPauseButton } from "../components/play-pause-button"
|
@@ -15,6 +13,7 @@ import { ContentLayer } from "../components/content-layer"
|
|
15 |
import { localStorageKeys } from "@/app/state/localStorageKeys"
|
16 |
import { defaultSettings } from "@/app/state/defaultSettings"
|
17 |
import { useStore } from "@/app/state/useStore"
|
|
|
18 |
|
19 |
function LatentEngine({
|
20 |
media,
|
@@ -87,8 +86,8 @@ function LatentEngine({
|
|
87 |
// there is a bug, we can't unpack the .clap when it's from a data-uri :/
|
88 |
|
89 |
// open(mediaUrl)
|
90 |
-
const mockClap = generateClapFromSimpleStory()
|
91 |
-
const mockArchive = await serializeClap(mockClap)
|
92 |
// for some reason conversion to data uri doesn't work
|
93 |
// const mockDataUri = await blobToDataUri(mockArchive, "application/x-gzip")
|
94 |
// console.log("mockDataUri:", mockDataUri)
|
|
|
5 |
|
6 |
import { cn } from "@/lib/utils/cn"
|
7 |
import { MediaInfo } from "@/types/general"
|
|
|
|
|
8 |
|
9 |
import { useLatentEngine } from "./useLatentEngine"
|
10 |
import { PlayPauseButton } from "../components/play-pause-button"
|
|
|
13 |
import { localStorageKeys } from "@/app/state/localStorageKeys"
|
14 |
import { defaultSettings } from "@/app/state/defaultSettings"
|
15 |
import { useStore } from "@/app/state/useStore"
|
16 |
+
import { ClapProject, generateClapFromSimpleStory, serializeClap } from "@aitube/clap"
|
17 |
|
18 |
function LatentEngine({
|
19 |
media,
|
|
|
86 |
// there is a bug, we can't unpack the .clap when it's from a data-uri :/
|
87 |
|
88 |
// open(mediaUrl)
|
89 |
+
const mockClap: ClapProject = generateClapFromSimpleStory()
|
90 |
+
const mockArchive: Blob = await serializeClap(mockClap)
|
91 |
// for some reason conversion to data uri doesn't work
|
92 |
// const mockDataUri = await blobToDataUri(mockArchive, "application/x-gzip")
|
93 |
// console.log("mockDataUri:", mockDataUri)
|
src/components/interface/latent-engine/core/generators/fetchLatentClap.ts
CHANGED
@@ -1,5 +1,4 @@
|
|
1 |
-
import { parseClap } from "
|
2 |
-
import { ClapProject } from "@/lib/clap/types"
|
3 |
|
4 |
export async function fetchLatentClap(prompt: string): Promise<ClapProject> {
|
5 |
|
|
|
1 |
+
import { ClapProject, parseClap } from "@aitube/clap"
|
|
|
2 |
|
3 |
export async function fetchLatentClap(prompt: string): Promise<ClapProject> {
|
4 |
|
src/components/interface/latent-engine/core/prompts/getCharacterPrompt.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
import { ClapModel } from "
|
2 |
|
3 |
export function getCharacterPrompt(model: ClapModel): string {
|
4 |
|
|
|
1 |
+
import { ClapModel } from "@aitube/clap"
|
2 |
|
3 |
export function getCharacterPrompt(model: ClapModel): string {
|
4 |
|
src/components/interface/latent-engine/core/prompts/getVideoPrompt.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
import { ClapModel, ClapSegment } from "
|
2 |
|
3 |
import { deduplicatePrompt } from "../../utils/prompting/deduplicatePrompt"
|
4 |
|
|
|
1 |
+
import { ClapModel, ClapSegment } from "@aitube/clap"
|
2 |
|
3 |
import { deduplicatePrompt } from "../../utils/prompting/deduplicatePrompt"
|
4 |
|
src/components/interface/latent-engine/core/types.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
import { ClapProject, ClapSegment } from "
|
2 |
import { InteractiveSegmenterResult } from "@mediapipe/tasks-vision"
|
3 |
import { MouseEventHandler, ReactNode } from "react"
|
4 |
|
|
|
1 |
+
import { ClapProject, ClapSegment } from "@aitube/clap"
|
2 |
import { InteractiveSegmenterResult } from "@mediapipe/tasks-vision"
|
3 |
import { MouseEventHandler, ReactNode } from "react"
|
4 |
|
src/components/interface/latent-engine/core/useLatentEngine.ts
CHANGED
@@ -1,16 +1,12 @@
|
|
1 |
|
2 |
import { create } from "zustand"
|
3 |
|
4 |
-
import { ClapModel, ClapProject } from "
|
5 |
-
import { newClap } from "@/lib/clap/newClap"
|
6 |
-
import { sleep } from "@/lib/utils/sleep"
|
7 |
-
// import { getSegmentationCanvas } from "@/lib/on-device-ai/getSegmentationCanvas"
|
8 |
|
9 |
import { LatentEngineStore } from "./types"
|
10 |
import { resolveSegments } from "../resolvers/resolveSegments"
|
11 |
import { fetchLatentClap } from "./generators/fetchLatentClap"
|
12 |
-
|
13 |
-
import { parseClap } from "@/lib/clap/parseClap"
|
14 |
import { InteractiveSegmenterResult, MPMask } from "@mediapipe/tasks-vision"
|
15 |
import { segmentFrame } from "@/lib/on-device-ai/segmentFrameOnClick"
|
16 |
import { drawSegmentation } from "../utils/canvas/drawSegmentation"
|
@@ -396,7 +392,7 @@ export const useLatentEngine = create<LatentEngineStore>((set, get) => ({
|
|
396 |
segments: clap.segments
|
397 |
})
|
398 |
|
399 |
-
const prefilterSegmentsForPerformanceReasons = clap.segments.filter(s =>
|
400 |
s.startTimeInMs >= positionInMs &&
|
401 |
s.startTimeInMs < maxBufferDurationInMs
|
402 |
)
|
@@ -424,7 +420,7 @@ export const useLatentEngine = create<LatentEngineStore>((set, get) => ({
|
|
424 |
|
425 |
// we select the segments in the current shot
|
426 |
|
427 |
-
const shotSegmentsToPreload = prefilterSegmentsForPerformanceReasons.filter(s =>
|
428 |
s.startTimeInMs >= bufferAheadOfCurrentPositionInMs &&
|
429 |
s.startTimeInMs < (bufferAheadOfCurrentPositionInMs + videoDurationInMs)
|
430 |
)
|
|
|
1 |
|
2 |
import { create } from "zustand"
|
3 |
|
4 |
+
import { ClapModel, ClapProject, ClapSegment, newClap, parseClap } from "@aitube/clap"
|
|
|
|
|
|
|
5 |
|
6 |
import { LatentEngineStore } from "./types"
|
7 |
import { resolveSegments } from "../resolvers/resolveSegments"
|
8 |
import { fetchLatentClap } from "./generators/fetchLatentClap"
|
9 |
+
|
|
|
10 |
import { InteractiveSegmenterResult, MPMask } from "@mediapipe/tasks-vision"
|
11 |
import { segmentFrame } from "@/lib/on-device-ai/segmentFrameOnClick"
|
12 |
import { drawSegmentation } from "../utils/canvas/drawSegmentation"
|
|
|
392 |
segments: clap.segments
|
393 |
})
|
394 |
|
395 |
+
const prefilterSegmentsForPerformanceReasons: ClapSegment[] = clap.segments.filter(s =>
|
396 |
s.startTimeInMs >= positionInMs &&
|
397 |
s.startTimeInMs < maxBufferDurationInMs
|
398 |
)
|
|
|
420 |
|
421 |
// we select the segments in the current shot
|
422 |
|
423 |
+
const shotSegmentsToPreload: ClapSegment[] = prefilterSegmentsForPerformanceReasons.filter(s =>
|
424 |
s.startTimeInMs >= bufferAheadOfCurrentPositionInMs &&
|
425 |
s.startTimeInMs < (bufferAheadOfCurrentPositionInMs + videoDurationInMs)
|
426 |
)
|
src/components/interface/latent-engine/resolvers/deprecated.txt
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
import { useEffect, useState } from "react";
|
4 |
|
5 |
-
import { ClapProject, ClapSegment } from "
|
6 |
import { resolveSegment } from "./resolveSegment";
|
7 |
|
8 |
export function LatentComponent({
|
|
|
2 |
|
3 |
import { useEffect, useState } from "react";
|
4 |
|
5 |
+
import { ClapProject, ClapSegment } from "@aitube/clap";
|
6 |
import { resolveSegment } from "./resolveSegment";
|
7 |
|
8 |
export function LatentComponent({
|
src/components/interface/latent-engine/resolvers/generic/index.tsx
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
import { v4 as uuidv4 } from "uuid"
|
4 |
|
5 |
-
import { ClapProject, ClapSegment } from "
|
6 |
|
7 |
import { LayerElement } from "../../core/types"
|
8 |
|
|
|
2 |
|
3 |
import { v4 as uuidv4 } from "uuid"
|
4 |
|
5 |
+
import { ClapProject, ClapSegment } from "@aitube/clap"
|
6 |
|
7 |
import { LayerElement } from "../../core/types"
|
8 |
|
src/components/interface/latent-engine/resolvers/image/index.tsx
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
"use client"
|
2 |
|
3 |
-
import { ClapProject, ClapSegment } from "
|
4 |
import { generateImage } from "./generateImage"
|
5 |
import { LayerElement } from "../../core/types"
|
6 |
import { useStore } from "@/app/state/useStore"
|
|
|
1 |
"use client"
|
2 |
|
3 |
+
import { ClapProject, ClapSegment } from "@aitube/clap"
|
4 |
import { generateImage } from "./generateImage"
|
5 |
import { LayerElement } from "../../core/types"
|
6 |
import { useStore } from "@/app/state/useStore"
|
src/components/interface/latent-engine/resolvers/interface/index.tsx
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
import RunCSS, { extendRunCSS } from "runcss"
|
4 |
|
5 |
-
import { ClapProject, ClapSegment } from "
|
6 |
import { generateHtml } from "./generateHtml"
|
7 |
import { AIContentDisclaimer } from "../../components/intros/ai-content-disclaimer"
|
8 |
import { LayerElement } from "../../core/types"
|
|
|
2 |
|
3 |
import RunCSS, { extendRunCSS } from "runcss"
|
4 |
|
5 |
+
import { ClapProject, ClapSegment } from "@aitube/clap"
|
6 |
import { generateHtml } from "./generateHtml"
|
7 |
import { AIContentDisclaimer } from "../../components/intros/ai-content-disclaimer"
|
8 |
import { LayerElement } from "../../core/types"
|
src/components/interface/latent-engine/resolvers/resolveSegment.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
import { ClapProject, ClapSegment } from "
|
2 |
|
3 |
import { LatentComponentResolver, LayerElement } from "../core/types"
|
4 |
|
|
|
1 |
+
import { ClapProject, ClapSegment } from "@aitube/clap"
|
2 |
|
3 |
import { LatentComponentResolver, LayerElement } from "../core/types"
|
4 |
|
src/components/interface/latent-engine/resolvers/resolveSegments.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
import { ClapProject, ClapSegmentCategory } from "
|
2 |
|
3 |
import { resolveSegment } from "./resolveSegment"
|
4 |
import { LayerElement } from "../core/types"
|
|
|
1 |
+
import { ClapProject, ClapSegmentCategory } from "@aitube/clap"
|
2 |
|
3 |
import { resolveSegment } from "./resolveSegment"
|
4 |
import { LayerElement } from "../core/types"
|
src/components/interface/latent-engine/resolvers/video/index.tsx
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
"use client"
|
2 |
|
3 |
-
import { ClapProject, ClapSegment } from "
|
4 |
|
5 |
import { LayerElement } from "../../core/types"
|
6 |
|
|
|
1 |
"use client"
|
2 |
|
3 |
+
import { ClapProject, ClapSegment } from "@aitube/clap"
|
4 |
|
5 |
import { LayerElement } from "../../core/types"
|
6 |
|
src/components/interface/latent-engine/resolvers/video/index_legacy.tsx
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
"use client"
|
2 |
|
3 |
-
import { ClapProject, ClapSegment } from "
|
4 |
import { PromiseResponseType, waitPromisesUntil } from "@/lib/utils/waitPromisesUntil"
|
5 |
import { generateVideo } from "./generateVideo"
|
6 |
import { BasicVideo } from "./basic-video"
|
|
|
1 |
"use client"
|
2 |
|
3 |
+
import { ClapProject, ClapSegment } from "@aitube/clap"
|
4 |
import { PromiseResponseType, waitPromisesUntil } from "@/lib/utils/waitPromisesUntil"
|
5 |
import { generateVideo } from "./generateVideo"
|
6 |
import { BasicVideo } from "./basic-video"
|
src/components/interface/latent-engine/resolvers/video/index_notSoGood.tsx
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
"use client"
|
2 |
|
3 |
-
import { ClapProject, ClapSegment } from "
|
4 |
import { PromiseResponseType, waitPromisesUntil } from "@/lib/utils/waitPromisesUntil"
|
5 |
import { VideoLoop } from "./video-loop"
|
6 |
import { generateVideo } from "./generateVideo"
|
|
|
1 |
"use client"
|
2 |
|
3 |
+
import { ClapProject, ClapSegment } from "@aitube/clap"
|
4 |
import { PromiseResponseType, waitPromisesUntil } from "@/lib/utils/waitPromisesUntil"
|
5 |
import { VideoLoop } from "./video-loop"
|
6 |
import { generateVideo } from "./generateVideo"
|
src/lib/business/getClapAssetSourceType.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
import { ClapAssetSource } from "
|
2 |
|
3 |
export function getClapAssetSourceSource(input: string = ""): ClapAssetSource {
|
4 |
|
|
|
1 |
+
import { ClapAssetSource } from "@aitube/clap"
|
2 |
|
3 |
export function getClapAssetSourceSource(input: string = ""): ClapAssetSource {
|
4 |
|
src/lib/clap/clap-specification-draft.md
DELETED
@@ -1,162 +0,0 @@
|
|
1 |
-
# CLAP Format Specification
|
2 |
-
|
3 |
-
- Status: DRAFT
|
4 |
-
- Document revision: 0.0.1
|
5 |
-
- Last updated: Feb 6th, 2024
|
6 |
-
- Author(s): Julian BILCKE (@flngr)
|
7 |
-
|
8 |
-
## BEFORE YOU READ
|
9 |
-
|
10 |
-
The CLAP format spec is experimental and not finished yet!
|
11 |
-
There might be inconsistencies, unnecessary redundancies or blatant omissions.
|
12 |
-
|
13 |
-
## What are CLAP files?
|
14 |
-
|
15 |
-
The CLAP format (.clap) is a file format designed for AI video projects.
|
16 |
-
|
17 |
-
It preserves prompts and assets into the same container, making it easier to share an AI video project between different people or applications.
|
18 |
-
|
19 |
-
## Structure
|
20 |
-
|
21 |
-
A CLAP is an array of objects serialized into a YAML text string, then finally compressed using gzip to a binary file.
|
22 |
-
|
23 |
-
The file extension is `.clap`
|
24 |
-
The mime type is `application/x-yaml`
|
25 |
-
|
26 |
-
There can be 5 different types of objects:
|
27 |
-
|
28 |
-
- one HEADER
|
29 |
-
- one METADATA
|
30 |
-
- zero, one or more MODEL(s)
|
31 |
-
- zero, one or more SCENE(s)
|
32 |
-
- zero, one or more SEGMENT(s)
|
33 |
-
|
34 |
-
This can be represented in javascript like this:
|
35 |
-
|
36 |
-
```javascript
|
37 |
-
[
|
38 |
-
clapHeader, // one metadata object
|
39 |
-
clapMeta, // one metadata object
|
40 |
-
...clapModels, // optional array of models
|
41 |
-
...clapScenes, // optional array of scenes
|
42 |
-
...clapSegments // optional array of segments
|
43 |
-
]
|
44 |
-
```
|
45 |
-
|
46 |
-
## Header
|
47 |
-
|
48 |
-
The HEADER provides information about how to decode a CLAP.
|
49 |
-
|
50 |
-
Knowing in advance the number of models, scenes and segments helps the decoder parsing the information,
|
51 |
-
and in some implementation, help with debugging, logging, and provisioning memory usage.
|
52 |
-
|
53 |
-
However in the future, it is possible that a different scheme is used, in order to support streaming.
|
54 |
-
|
55 |
-
Either by recognizing the shape of each object (fields), or by using a specific field eg. a `_type`.
|
56 |
-
|
57 |
-
```typescript
|
58 |
-
{
|
59 |
-
// used to know which format version is used.
|
60 |
-
// CLAP is still in development and the format is not fully specified yet,
|
61 |
-
// during the period most .clap file will have the "clap-0" format
|
62 |
-
format: "clap-0"
|
63 |
-
|
64 |
-
numberOfModels: number // integer
|
65 |
-
numberOfScenes: number // integer
|
66 |
-
numberOfSegments: number // integer
|
67 |
-
}
|
68 |
-
```
|
69 |
-
|
70 |
-
## Metadata
|
71 |
-
|
72 |
-
```typescript
|
73 |
-
{
|
74 |
-
id: string // "<a valid UUID V4>"
|
75 |
-
title: string // "project title"
|
76 |
-
description: string // "project description"
|
77 |
-
licence: string // "information about licensing"
|
78 |
-
|
79 |
-
// this provides information about the image ratio
|
80 |
-
// this might be removed in the final spec, as this
|
81 |
-
// can be re-computed from width and height
|
82 |
-
orientation: "landscape" | "vertical" | "square"
|
83 |
-
|
84 |
-
// the expected duration of the project
|
85 |
-
durationInMs: number
|
86 |
-
|
87 |
-
// the suggested width and height of the video
|
88 |
-
// note that this is just an indicator,
|
89 |
-
// and might be superseeded by the application reading the .clap file
|
90 |
-
width: number // integer between 256 and 8192 (value in pixels)
|
91 |
-
height: number // integer between 256 and 8192 (value in pixels)
|
92 |
-
|
93 |
-
// name of the suggested video model to use
|
94 |
-
// note that this is just an indicator,
|
95 |
-
// and might be superseeded by the application reading the .clap file
|
96 |
-
defaultVideoModel: string
|
97 |
-
|
98 |
-
// additional prompt to use in the video generation
|
99 |
-
// this helps adding some magic touch and flair to the videos,
|
100 |
-
// but perhaps the field should be renamed
|
101 |
-
extraPositivePrompt: string
|
102 |
-
|
103 |
-
// the screenplay (script) of the video
|
104 |
-
screenplay: string
|
105 |
-
|
106 |
-
// whether to loop the content by default or not
|
107 |
-
isLoop: boolean
|
108 |
-
|
109 |
-
// helper to indicate whether the .clap might contain interactive elements
|
110 |
-
isInteractive: boolean
|
111 |
-
}
|
112 |
-
```
|
113 |
-
|
114 |
-
## Models
|
115 |
-
|
116 |
-
Before talking about models, first we should describe the concept of entity:
|
117 |
-
|
118 |
-
in a story, an entity is something (person, place, vehicle, animal, robot, alien, object) with a name, a description of the appearance, an age, mileage or quality, an origin, and so on.
|
119 |
-
|
120 |
-
An example could be "a giant magical school bus, with appearance of a cat with wheels, and which talks"
|
121 |
-
|
122 |
-
The CLAP model would be an instance (an interpretation) of this entity, where we would assign it an identity:
|
123 |
-
- a name and age
|
124 |
-
- a visual style (a photo of the magic school bus cat)
|
125 |
-
- a voice style
|
126 |
-
- and maybe other things eg. an origin or background story
|
127 |
-
|
128 |
-
As you can see, it can be difficult to create clearly separated categories, like "vehicule", "character", or "location"
|
129 |
-
(the magical cat bus could turn into a location in some scene, a speaking character in another etc)
|
130 |
-
|
131 |
-
This is why there is a common schema for all models:
|
132 |
-
|
133 |
-
```typescript
|
134 |
-
{
|
135 |
-
id: string
|
136 |
-
category: ClapSegmentCategory
|
137 |
-
triggerName: string
|
138 |
-
label: string
|
139 |
-
description: string
|
140 |
-
author: string
|
141 |
-
thumbnailUrl: string
|
142 |
-
seed: number
|
143 |
-
|
144 |
-
assetSourceType: ClapAssetSource
|
145 |
-
assetUrl: string
|
146 |
-
|
147 |
-
age: number
|
148 |
-
gender: ClapModelGender
|
149 |
-
region: ClapModelRegion
|
150 |
-
appearance: ClapModelAppearance
|
151 |
-
voiceVendor: ClapVoiceVendor
|
152 |
-
voiceId: string
|
153 |
-
}
|
154 |
-
```
|
155 |
-
|
156 |
-
## Atomic types
|
157 |
-
|
158 |
-
...
|
159 |
-
|
160 |
-
## TO BE CONTINUED
|
161 |
-
|
162 |
-
(you can read "./types.ts" for more information)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/clap/clapToDataUri.ts
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
import { blobToDataUri } from "@/app/api/utils/blobToDataUri"
|
2 |
-
|
3 |
-
import { serializeClap } from "./serializeClap"
|
4 |
-
import { ClapProject } from "./types"
|
5 |
-
|
6 |
-
export async function clapToDataUri(clap: ClapProject): Promise<string> {
|
7 |
-
const archive = await serializeClap(clap)
|
8 |
-
const dataUri = await blobToDataUri(archive, "application/x-gzip")
|
9 |
-
return dataUri
|
10 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/clap/emptyClap.ts
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
import { newClap } from "./newClap"
|
2 |
-
import { serializeClap } from "./serializeClap"
|
3 |
-
|
4 |
-
let globalState: {
|
5 |
-
blob?: Blob
|
6 |
-
} = {
|
7 |
-
blob: undefined
|
8 |
-
}
|
9 |
-
|
10 |
-
export async function getEmptyClap(): Promise<Blob> {
|
11 |
-
if (globalState.blob) { return globalState.blob }
|
12 |
-
|
13 |
-
const clap = newClap()
|
14 |
-
|
15 |
-
globalState.blob = await serializeClap(clap)
|
16 |
-
|
17 |
-
return globalState.blob
|
18 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/clap/generateClapFromSimpleStory.ts
DELETED
@@ -1,149 +0,0 @@
|
|
1 |
-
import { newClap } from "./newClap"
|
2 |
-
import { newSegment } from "./newSegment"
|
3 |
-
import { ClapProject } from "./types"
|
4 |
-
|
5 |
-
let defaultSegmentDurationInMs = 2500 // 2584
|
6 |
-
|
7 |
-
const fishDemoStory = [
|
8 |
-
"Siamese fighting fish, bokeh, underwater, coral, lively, bubbles, translucency, perfect",
|
9 |
-
|
10 |
-
// this one is magnificient!
|
11 |
-
"princess parrot fish, bokeh, underwater, coral, lively, bubbles, translucency, perfect",
|
12 |
-
|
13 |
-
"pacific ocean perch, bokeh, underwater, coral, lively, bubbles, translucency, perfect",
|
14 |
-
|
15 |
-
"Queen angelfish, bokeh, underwater, coral, lively, bubbles, translucency, perfect",
|
16 |
-
|
17 |
-
"sea turtle, bokeh, underwater, coral, lively, bubbles, translucency, perfect",
|
18 |
-
|
19 |
-
"hippocampus, bokeh, underwater, coral, lively, bubbles, translucency, perfect",
|
20 |
-
]
|
21 |
-
|
22 |
-
let demoStory = [
|
23 |
-
...fishDemoStory,
|
24 |
-
|
25 |
-
// "portrait of one man news anchor, 60yo, thin, fit, american, mustache, beard, wearing a suit, medium-shot, central park, outside, serious, bokeh, perfect",
|
26 |
-
|
27 |
-
// "screenshot from Call of Duty, FPS game, nextgen, videogame screenshot, unreal engine, raytracing, perfect",
|
28 |
-
|
29 |
-
// "screenshot from a flight simulator, nextgen, videogame screenshot, unreal engine, raytracing, perfect",
|
30 |
-
// "screenshot from fallout3, fallout4, western, wasteland, 3rd person RPG, nextgen, videogame screenshot, unreal engine, raytracing, perfect",
|
31 |
-
// "portrait of single influencer woman, 30yo, thin, fit, american, wearing a red tshirt, medium-shot, central park, outside, serious, bokeh, perfect",
|
32 |
-
]
|
33 |
-
|
34 |
-
|
35 |
-
export function generateClapFromSimpleStory({
|
36 |
-
story = demoStory,
|
37 |
-
showIntroPoweredByEngine = false,
|
38 |
-
showIntroDisclaimerAboutAI = false,
|
39 |
-
}: {
|
40 |
-
story?: string[]
|
41 |
-
showIntroPoweredByEngine?: boolean
|
42 |
-
showIntroDisclaimerAboutAI?: boolean
|
43 |
-
} = {
|
44 |
-
story: demoStory,
|
45 |
-
showIntroPoweredByEngine: false,
|
46 |
-
showIntroDisclaimerAboutAI: false,
|
47 |
-
}): ClapProject {
|
48 |
-
|
49 |
-
const clap = newClap({
|
50 |
-
meta: {
|
51 |
-
title: "Interactive Demo",
|
52 |
-
isInteractive: true,
|
53 |
-
isLoop: true,
|
54 |
-
}
|
55 |
-
})
|
56 |
-
|
57 |
-
let currentElapsedTimeInMs = 0
|
58 |
-
let currentSegmentDurationInMs = defaultSegmentDurationInMs
|
59 |
-
|
60 |
-
if (showIntroPoweredByEngine) {
|
61 |
-
clap.segments.push(newSegment({
|
62 |
-
startTimeInMs: currentElapsedTimeInMs,
|
63 |
-
endTimeInMs: currentSegmentDurationInMs,
|
64 |
-
category: "interface",
|
65 |
-
prompt: "<BUILTIN:POWERED_BY_ENGINE>",
|
66 |
-
label: "disclaimer",
|
67 |
-
outputType: "interface",
|
68 |
-
}))
|
69 |
-
currentElapsedTimeInMs += currentSegmentDurationInMs
|
70 |
-
}
|
71 |
-
|
72 |
-
if (showIntroDisclaimerAboutAI) {
|
73 |
-
clap.segments.push(newSegment({
|
74 |
-
startTimeInMs: currentElapsedTimeInMs,
|
75 |
-
endTimeInMs: currentSegmentDurationInMs,
|
76 |
-
category: "interface",
|
77 |
-
prompt: "<BUILTIN:DISCLAIMER_ABOUT_AI>",
|
78 |
-
label: "disclaimer",
|
79 |
-
outputType: "interface",
|
80 |
-
}))
|
81 |
-
currentElapsedTimeInMs += currentSegmentDurationInMs
|
82 |
-
}
|
83 |
-
|
84 |
-
/*
|
85 |
-
clap.segments.push(
|
86 |
-
newSegment({
|
87 |
-
// id: string
|
88 |
-
// track: number
|
89 |
-
startTimeInMs: currentElapsedTimeInMs,
|
90 |
-
endTimeInMs: currentSegmentDurationInMs,
|
91 |
-
category: "interface",
|
92 |
-
// modelId: string
|
93 |
-
// sceneId: string
|
94 |
-
prompt: "a hello world",
|
95 |
-
label: "hello world",
|
96 |
-
outputType: "interface"
|
97 |
-
// renderId: string
|
98 |
-
// status: ClapSegmentStatus
|
99 |
-
// assetUrl: string
|
100 |
-
// assetDurationInMs: number
|
101 |
-
// createdBy: ClapAuthor
|
102 |
-
// editedBy: ClapAuthor
|
103 |
-
// outputGain: number
|
104 |
-
// seed: number
|
105 |
-
})
|
106 |
-
)
|
107 |
-
|
108 |
-
currentElapsedTimeInMs += currentSegmentDurationInMs
|
109 |
-
*/
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
for (let prompt of story) {
|
114 |
-
|
115 |
-
clap.segments.push(newSegment({
|
116 |
-
track: 0,
|
117 |
-
startTimeInMs: currentElapsedTimeInMs,
|
118 |
-
endTimeInMs: currentSegmentDurationInMs,
|
119 |
-
category: "video",
|
120 |
-
prompt: "",
|
121 |
-
label: "video",
|
122 |
-
outputType: "video",
|
123 |
-
}))
|
124 |
-
clap.segments.push(newSegment({
|
125 |
-
track: 1,
|
126 |
-
startTimeInMs: currentElapsedTimeInMs,
|
127 |
-
endTimeInMs: currentSegmentDurationInMs,
|
128 |
-
category: "generic",
|
129 |
-
prompt,
|
130 |
-
label: prompt,
|
131 |
-
outputType: "text",
|
132 |
-
}))
|
133 |
-
clap.segments.push(newSegment({
|
134 |
-
track: 2,
|
135 |
-
startTimeInMs: currentElapsedTimeInMs,
|
136 |
-
endTimeInMs: currentSegmentDurationInMs,
|
137 |
-
category: "camera",
|
138 |
-
prompt: "medium-shot",
|
139 |
-
label: "medium-shot",
|
140 |
-
outputType: "text",
|
141 |
-
}))
|
142 |
-
|
143 |
-
currentElapsedTimeInMs += currentSegmentDurationInMs
|
144 |
-
}
|
145 |
-
|
146 |
-
clap.meta.durationInMs = currentElapsedTimeInMs
|
147 |
-
|
148 |
-
return clap
|
149 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/clap/getClapAssetSource.ts
DELETED
@@ -1,25 +0,0 @@
|
|
1 |
-
import { ClapAssetSource } from "./types"
|
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/lib/clap/newClap.ts
DELETED
@@ -1,37 +0,0 @@
|
|
1 |
-
|
2 |
-
import { v4 as uuidv4 } from "uuid"
|
3 |
-
|
4 |
-
import { ClapMeta, ClapModel, ClapProject, ClapScene, ClapSegment } from "./types"
|
5 |
-
import { getValidNumber } from "@/lib/utils/getValidNumber"
|
6 |
-
|
7 |
-
// generate an empty clap file, or copy one from a source
|
8 |
-
export function newClap(clap: {
|
9 |
-
meta?: Partial<ClapMeta>
|
10 |
-
models?: ClapModel[]
|
11 |
-
scenes?: ClapScene[]
|
12 |
-
segments?: ClapSegment[]
|
13 |
-
} = {}): ClapProject {
|
14 |
-
|
15 |
-
const meta: ClapMeta = {
|
16 |
-
id: clap?.meta?.id === "string" ? clap.meta.id : uuidv4(),
|
17 |
-
title: clap?.meta?.title === "string" ? clap.meta.title : "",
|
18 |
-
description: typeof clap?.meta?.description === "string" ? clap.meta.description : "",
|
19 |
-
synopsis: typeof clap?.meta?.synopsis === "string" ? clap.meta.synopsis : "",
|
20 |
-
licence: typeof clap?.meta?.licence === "string" ? clap.meta.licence : "",
|
21 |
-
orientation: clap?.meta?.orientation === "portrait" ? "portrait" : clap?.meta?.orientation === "square" ? "square" : "landscape",
|
22 |
-
durationInMs: getValidNumber(clap?.meta?.durationInMs, 1000, Number.MAX_SAFE_INTEGER, 4000),
|
23 |
-
width: getValidNumber(clap?.meta?.width, 256, 8192, 1024),
|
24 |
-
height: getValidNumber(clap?.meta?.height, 256, 8192, 576),
|
25 |
-
defaultVideoModel: typeof clap?.meta?.defaultVideoModel === "string" ? clap.meta.defaultVideoModel : "SVD",
|
26 |
-
extraPositivePrompt: Array.isArray(clap?.meta?.extraPositivePrompt) ? clap.meta.extraPositivePrompt : [],
|
27 |
-
screenplay: typeof clap?.meta?.screenplay === "string" ? clap.meta.screenplay : "",
|
28 |
-
isLoop: typeof clap?.meta?.isLoop === "boolean" ? clap.meta.isLoop : false,
|
29 |
-
isInteractive: typeof clap?.meta?.isInteractive === "boolean" ? clap.meta.isInteractive : false,
|
30 |
-
}
|
31 |
-
|
32 |
-
const models: ClapModel[] = clap?.models && Array.isArray(clap.models) ? clap.models : []
|
33 |
-
const scenes: ClapScene[] = clap?.scenes && Array.isArray(clap.scenes) ? clap.scenes : []
|
34 |
-
const segments: ClapSegment[] = clap?.segments && Array.isArray(clap.segments) ? clap.segments : []
|
35 |
-
|
36 |
-
return { meta, models, scenes, segments }
|
37 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/clap/newSegment.ts
DELETED
@@ -1,46 +0,0 @@
|
|
1 |
-
import { v4 as uuidv4 } from "uuid"
|
2 |
-
|
3 |
-
import { generateSeed } from "../utils/generateSeed"
|
4 |
-
import { ClapSegment } from "./types"
|
5 |
-
import { isValidNumber } from "../utils/isValidNumber"
|
6 |
-
|
7 |
-
export function newSegment(maybeSegment?: Partial<ClapSegment>) {
|
8 |
-
|
9 |
-
const startTimeInMs =
|
10 |
-
isValidNumber(maybeSegment?.startTimeInMs)
|
11 |
-
? (maybeSegment?.startTimeInMs || 0)
|
12 |
-
: 0
|
13 |
-
|
14 |
-
const assetDurationInMs =
|
15 |
-
isValidNumber(maybeSegment?.assetDurationInMs)
|
16 |
-
? (maybeSegment?.assetDurationInMs || 0)
|
17 |
-
: 1000
|
18 |
-
|
19 |
-
const endTimeInMs =
|
20 |
-
isValidNumber(maybeSegment?.endTimeInMs)
|
21 |
-
? (maybeSegment?.endTimeInMs || 0)
|
22 |
-
: (startTimeInMs + assetDurationInMs)
|
23 |
-
|
24 |
-
const segment: ClapSegment = {
|
25 |
-
id: typeof maybeSegment?.id === "string" ? maybeSegment.id : uuidv4(),
|
26 |
-
track: isValidNumber(maybeSegment?.track) ? (maybeSegment?.track || 0) : 0,
|
27 |
-
startTimeInMs,
|
28 |
-
endTimeInMs,
|
29 |
-
category: typeof maybeSegment?.category === "string" ? maybeSegment.category : "generic",
|
30 |
-
modelId: typeof maybeSegment?.modelId === "string" ? maybeSegment.modelId : "",
|
31 |
-
sceneId: typeof maybeSegment?.sceneId === "string" ? maybeSegment.sceneId : "",
|
32 |
-
prompt: typeof maybeSegment?.prompt === "string" ? maybeSegment.prompt : "",
|
33 |
-
label: typeof maybeSegment?.label === "string" ? maybeSegment.label : "",
|
34 |
-
outputType: typeof maybeSegment?.outputType === "string" ? maybeSegment.outputType : "text",
|
35 |
-
renderId: typeof maybeSegment?.renderId === "string" ? maybeSegment.renderId : "",
|
36 |
-
status: typeof maybeSegment?.status === "string" ? maybeSegment.status : "to_generate",
|
37 |
-
assetUrl: typeof maybeSegment?.assetUrl === "string" ? maybeSegment.assetUrl : "",
|
38 |
-
assetDurationInMs,
|
39 |
-
createdBy: typeof maybeSegment?.createdBy === "string" ? maybeSegment.createdBy : "ai",
|
40 |
-
editedBy: typeof maybeSegment?.editedBy === "string" ? maybeSegment.editedBy : "ai",
|
41 |
-
outputGain: isValidNumber(maybeSegment?.outputGain) ? (maybeSegment?.outputGain || 0) : 0,
|
42 |
-
seed: isValidNumber(maybeSegment?.seed) ? (maybeSegment?.seed || 0) : generateSeed()
|
43 |
-
}
|
44 |
-
|
45 |
-
return segment
|
46 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/clap/parseClap.ts
DELETED
@@ -1,319 +0,0 @@
|
|
1 |
-
import YAML from "yaml"
|
2 |
-
import { v4 as uuidv4 } from "uuid"
|
3 |
-
|
4 |
-
import { ClapHeader, ClapMeta, ClapModel, ClapProject, ClapScene, ClapSegment } from "./types"
|
5 |
-
import { getValidNumber } from "@/lib/utils/getValidNumber"
|
6 |
-
import { dataUriToBlob } from "@/app/api/utils/dataUriToBlob"
|
7 |
-
|
8 |
-
type StringOrBlob = string | Blob
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Import a clap file from various data sources into an ClapProject
|
12 |
-
*
|
13 |
-
* Inputs can be:
|
14 |
-
* - a Clap project (which is an object)
|
15 |
-
* - an URL to a remote .clap file
|
16 |
-
* - a string containing a YAML array
|
17 |
-
* - a data uri containing a gzipped YAML array
|
18 |
-
* - a Blob containing a gzipped YAML array
|
19 |
-
*
|
20 |
-
* note: it is not really async, because for some reason YAML.parse is a blocking call like for JSON,
|
21 |
-
* there is no async version although we are now in the 20s not 90s
|
22 |
-
*/
|
23 |
-
export async function parseClap(src?: ClapProject | string | Blob, debug = false): Promise<ClapProject> {
|
24 |
-
|
25 |
-
try {
|
26 |
-
if (
|
27 |
-
typeof src === "object" &&
|
28 |
-
Array.isArray( (src as any)?.scenes) &&
|
29 |
-
Array.isArray((src as any)?.models)
|
30 |
-
) {
|
31 |
-
if (debug) {
|
32 |
-
console.log("parseClap: input is already a Clap file, nothing to do:", src)
|
33 |
-
}
|
34 |
-
// we can skip verification
|
35 |
-
return src as ClapProject
|
36 |
-
}
|
37 |
-
} catch (err) {
|
38 |
-
// well, this is not a clap project
|
39 |
-
}
|
40 |
-
|
41 |
-
let stringOrBlob = (src || "") as StringOrBlob
|
42 |
-
|
43 |
-
// both should work
|
44 |
-
const dataUriHeader1 = "data:application/x-gzip;base64,"
|
45 |
-
const dataUriHeader2 = "data:application/octet-stream;base64,"
|
46 |
-
|
47 |
-
const inputIsString = typeof stringOrBlob === "string"
|
48 |
-
const inputIsDataUri = typeof stringOrBlob === "string" ? stringOrBlob.startsWith(dataUriHeader1) || stringOrBlob.startsWith(dataUriHeader2) : false
|
49 |
-
const inputIsRemoteFile = typeof stringOrBlob === "string" ? (stringOrBlob.startsWith("http://") || stringOrBlob.startsWith("https://")) : false
|
50 |
-
|
51 |
-
let inputIsBlob = typeof stringOrBlob !== "string"
|
52 |
-
|
53 |
-
let inputYamlArrayString = ""
|
54 |
-
|
55 |
-
if (debug) {
|
56 |
-
console.log(`parseClap: pre-analysis: ${JSON.stringify({
|
57 |
-
inputIsString,
|
58 |
-
inputIsBlob,
|
59 |
-
inputIsDataUri,
|
60 |
-
inputIsRemoteFile
|
61 |
-
}, null, 2)}`)
|
62 |
-
}
|
63 |
-
|
64 |
-
if (typeof stringOrBlob === "string") {
|
65 |
-
if (debug) {
|
66 |
-
console.log("parseClap: input is a string ", stringOrBlob.slice(0, 120))
|
67 |
-
}
|
68 |
-
if (inputIsDataUri) {
|
69 |
-
if (debug) {
|
70 |
-
console.log(`parseClap: input is a data uri archive`)
|
71 |
-
}
|
72 |
-
stringOrBlob = dataUriToBlob(stringOrBlob, "application/x-gzip")
|
73 |
-
if (debug) {
|
74 |
-
console.log(`parseClap: inputBlob = `, stringOrBlob)
|
75 |
-
}
|
76 |
-
inputIsBlob = true
|
77 |
-
} else if (inputIsRemoteFile) {
|
78 |
-
try {
|
79 |
-
if (debug) {
|
80 |
-
console.log(`parseClap: input is a remote .clap file`)
|
81 |
-
}
|
82 |
-
const res = await fetch(stringOrBlob)
|
83 |
-
stringOrBlob = await res.blob()
|
84 |
-
if (!stringOrBlob) { throw new Error("blob is empty") }
|
85 |
-
inputIsBlob = true
|
86 |
-
} catch (err) {
|
87 |
-
// url seems invalid
|
88 |
-
throw new Error(`failed to download the .clap file (${err})`)
|
89 |
-
}
|
90 |
-
} else {
|
91 |
-
if (debug) {
|
92 |
-
console.log("parseClap: input is a text string containing a YAML array")
|
93 |
-
}
|
94 |
-
inputYamlArrayString = stringOrBlob
|
95 |
-
inputIsBlob = false
|
96 |
-
}
|
97 |
-
}
|
98 |
-
|
99 |
-
if (typeof stringOrBlob !== "string" && stringOrBlob) {
|
100 |
-
if (debug) {
|
101 |
-
console.log("parseClap: decompressing the blob..")
|
102 |
-
}
|
103 |
-
// Decompress the input blob using gzip
|
104 |
-
const decompressedStream = stringOrBlob.stream().pipeThrough(new DecompressionStream('gzip'))
|
105 |
-
|
106 |
-
try {
|
107 |
-
// Convert the stream to text using a Response object
|
108 |
-
const decompressedOutput = new Response(decompressedStream)
|
109 |
-
// decompressedOutput.headers.set("Content-Type", "application/x-gzip")
|
110 |
-
if (debug) {
|
111 |
-
console.log("parseClap: decompressedOutput: ", decompressedOutput)
|
112 |
-
}
|
113 |
-
// const blobAgain = await decompressedOutput.blob()
|
114 |
-
inputYamlArrayString = await decompressedOutput.text()
|
115 |
-
|
116 |
-
if (debug && inputYamlArrayString) {
|
117 |
-
console.log("parseClap: successfully decompressed the blob!")
|
118 |
-
}
|
119 |
-
} catch (err) {
|
120 |
-
const message = `parseClap: failed to decompress (${err})`
|
121 |
-
console.error(message)
|
122 |
-
throw new Error(message)
|
123 |
-
}
|
124 |
-
}
|
125 |
-
|
126 |
-
// we don't need this anymore I think
|
127 |
-
// new Blob([inputStringOrBlob], { type: "application/x-yaml" })
|
128 |
-
|
129 |
-
let maybeArray: any = {}
|
130 |
-
try {
|
131 |
-
if (debug) {
|
132 |
-
console.log("parseClap: parsing the YAML array..")
|
133 |
-
}
|
134 |
-
// Parse YAML string to raw data
|
135 |
-
maybeArray = YAML.parse(inputYamlArrayString)
|
136 |
-
} catch (err) {
|
137 |
-
throw new Error("invalid clap file (input string is not YAML)")
|
138 |
-
}
|
139 |
-
|
140 |
-
if (!Array.isArray(maybeArray) || maybeArray.length < 2) {
|
141 |
-
throw new Error("invalid clap file (need a clap format header block and project metadata block)")
|
142 |
-
}
|
143 |
-
|
144 |
-
if (debug) {
|
145 |
-
console.log("parseClap: the YAML seems okay, continuing decoding..")
|
146 |
-
}
|
147 |
-
|
148 |
-
const maybeClapHeader = maybeArray[0] as ClapHeader
|
149 |
-
|
150 |
-
if (maybeClapHeader.format !== "clap-0") {
|
151 |
-
throw new Error("invalid clap file (sorry, but you can't make up version numbers like that)")
|
152 |
-
}
|
153 |
-
|
154 |
-
|
155 |
-
const maybeClapMeta = maybeArray[1] as ClapMeta
|
156 |
-
|
157 |
-
const clapMeta: ClapMeta = {
|
158 |
-
id: typeof maybeClapMeta.title === "string" ? maybeClapMeta.id : uuidv4(),
|
159 |
-
title: typeof maybeClapMeta.title === "string" ? maybeClapMeta.title : "",
|
160 |
-
description: typeof maybeClapMeta.description === "string" ? maybeClapMeta.description : "",
|
161 |
-
synopsis: typeof maybeClapMeta.synopsis === "string" ? maybeClapMeta.synopsis : "",
|
162 |
-
licence: typeof maybeClapMeta.licence === "string" ? maybeClapMeta.licence : "",
|
163 |
-
orientation: maybeClapMeta.orientation === "portrait" ? "portrait" : maybeClapMeta.orientation === "square" ? "square" : "landscape",
|
164 |
-
durationInMs: getValidNumber(maybeClapMeta.durationInMs, 1000, Number.MAX_SAFE_INTEGER, 4000),
|
165 |
-
width: getValidNumber(maybeClapMeta.width, 128, 8192, 1024),
|
166 |
-
height: getValidNumber(maybeClapMeta.height, 128, 8192, 576),
|
167 |
-
defaultVideoModel: typeof maybeClapMeta.defaultVideoModel === "string" ? maybeClapMeta.defaultVideoModel : "SVD",
|
168 |
-
extraPositivePrompt: Array.isArray(maybeClapMeta.extraPositivePrompt) ? maybeClapMeta.extraPositivePrompt : [],
|
169 |
-
screenplay: typeof maybeClapMeta.screenplay === "string" ? maybeClapMeta.screenplay : "",
|
170 |
-
isLoop: typeof maybeClapMeta.isLoop === "boolean" ? maybeClapMeta.isLoop : false,
|
171 |
-
isInteractive: typeof maybeClapMeta.isInteractive === "boolean" ? maybeClapMeta.isInteractive : false,
|
172 |
-
}
|
173 |
-
|
174 |
-
/*
|
175 |
-
in case we want to support streaming (mix of models and segments etc), we could do it this way:
|
176 |
-
|
177 |
-
const maybeModelsOrSegments = rawData.slice(2)
|
178 |
-
maybeModelsOrSegments.forEach((unknownElement: any) => {
|
179 |
-
if (isValidNumber(unknownElement?.track)) {
|
180 |
-
maybeSegments.push(unknownElement as ClapSegment)
|
181 |
-
} else {
|
182 |
-
maybeModels.push(unknownElement as ClapModel)
|
183 |
-
}
|
184 |
-
})
|
185 |
-
*/
|
186 |
-
|
187 |
-
|
188 |
-
const expectedNumberOfModels = maybeClapHeader.numberOfModels || 0
|
189 |
-
const expectedNumberOfScenes = maybeClapHeader.numberOfScenes || 0
|
190 |
-
const expectedNumberOfSegments = maybeClapHeader.numberOfSegments || 0
|
191 |
-
|
192 |
-
// note: we assume the order is strictly enforced!
|
193 |
-
// if you implement streaming (mix of models and segments) you will have to rewrite this!
|
194 |
-
|
195 |
-
const afterTheHeaders = 2
|
196 |
-
const afterTheModels = afterTheHeaders + expectedNumberOfModels
|
197 |
-
|
198 |
-
const afterTheScenes = afterTheModels + expectedNumberOfScenes
|
199 |
-
|
200 |
-
// note: if there are no expected models, maybeModels will be empty
|
201 |
-
const maybeModels = maybeArray.slice(afterTheHeaders, afterTheModels) as ClapModel[]
|
202 |
-
|
203 |
-
// note: if there are no expected scenes, maybeScenes will be empty
|
204 |
-
const maybeScenes = maybeArray.slice(afterTheModels, afterTheScenes) as ClapScene[]
|
205 |
-
|
206 |
-
const maybeSegments = maybeArray.slice(afterTheScenes) as ClapSegment[]
|
207 |
-
|
208 |
-
const clapModels: ClapModel[] = maybeModels.map(({
|
209 |
-
id,
|
210 |
-
category,
|
211 |
-
triggerName,
|
212 |
-
label,
|
213 |
-
description,
|
214 |
-
author,
|
215 |
-
thumbnailUrl,
|
216 |
-
seed,
|
217 |
-
assetSourceType,
|
218 |
-
assetUrl,
|
219 |
-
age,
|
220 |
-
gender,
|
221 |
-
region,
|
222 |
-
appearance,
|
223 |
-
voiceVendor,
|
224 |
-
voiceId,
|
225 |
-
}) => ({
|
226 |
-
// TODO: we should verify each of those, probably
|
227 |
-
id,
|
228 |
-
category,
|
229 |
-
triggerName,
|
230 |
-
label,
|
231 |
-
description,
|
232 |
-
author,
|
233 |
-
thumbnailUrl,
|
234 |
-
seed,
|
235 |
-
assetSourceType,
|
236 |
-
assetUrl,
|
237 |
-
age,
|
238 |
-
gender,
|
239 |
-
region,
|
240 |
-
appearance,
|
241 |
-
voiceVendor,
|
242 |
-
voiceId,
|
243 |
-
}))
|
244 |
-
|
245 |
-
const clapScenes: ClapScene[] = maybeScenes.map(({
|
246 |
-
id,
|
247 |
-
scene,
|
248 |
-
line,
|
249 |
-
rawLine,
|
250 |
-
sequenceFullText,
|
251 |
-
sequenceStartAtLine,
|
252 |
-
sequenceEndAtLine,
|
253 |
-
startAtLine,
|
254 |
-
endAtLine,
|
255 |
-
events,
|
256 |
-
}) => ({
|
257 |
-
id,
|
258 |
-
scene,
|
259 |
-
line,
|
260 |
-
rawLine,
|
261 |
-
sequenceFullText,
|
262 |
-
sequenceStartAtLine,
|
263 |
-
sequenceEndAtLine,
|
264 |
-
startAtLine,
|
265 |
-
endAtLine,
|
266 |
-
events: events.map(e => e)
|
267 |
-
}))
|
268 |
-
|
269 |
-
const clapSegments: ClapSegment[] = maybeSegments.map(({
|
270 |
-
id,
|
271 |
-
track,
|
272 |
-
startTimeInMs,
|
273 |
-
endTimeInMs,
|
274 |
-
category,
|
275 |
-
modelId,
|
276 |
-
sceneId,
|
277 |
-
prompt,
|
278 |
-
label,
|
279 |
-
outputType,
|
280 |
-
renderId,
|
281 |
-
status,
|
282 |
-
assetUrl,
|
283 |
-
assetDurationInMs,
|
284 |
-
createdBy,
|
285 |
-
editedBy,
|
286 |
-
outputGain,
|
287 |
-
seed,
|
288 |
-
}) => ({
|
289 |
-
// TODO: we should verify each of those, probably
|
290 |
-
id,
|
291 |
-
track,
|
292 |
-
startTimeInMs,
|
293 |
-
endTimeInMs,
|
294 |
-
category,
|
295 |
-
modelId,
|
296 |
-
sceneId,
|
297 |
-
prompt,
|
298 |
-
label,
|
299 |
-
outputType,
|
300 |
-
renderId,
|
301 |
-
status,
|
302 |
-
assetUrl,
|
303 |
-
assetDurationInMs,
|
304 |
-
createdBy,
|
305 |
-
editedBy,
|
306 |
-
outputGain,
|
307 |
-
seed,
|
308 |
-
}))
|
309 |
-
|
310 |
-
if (debug) {
|
311 |
-
console.log(`parseClap: successfully parsed ${clapModels.length} models, ${clapScenes.length} scenes and ${clapSegments.length} segments`)
|
312 |
-
}
|
313 |
-
return {
|
314 |
-
meta: clapMeta,
|
315 |
-
models: clapModels,
|
316 |
-
scenes: clapScenes,
|
317 |
-
segments: clapSegments
|
318 |
-
}
|
319 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/clap/serializeClap.ts
DELETED
@@ -1,169 +0,0 @@
|
|
1 |
-
import YAML from "yaml"
|
2 |
-
import { v4 as uuidv4 } from "uuid"
|
3 |
-
|
4 |
-
import { getValidNumber } from "@/lib/utils/getValidNumber"
|
5 |
-
|
6 |
-
import { ClapHeader, ClapMeta, ClapModel, ClapProject, ClapScene, ClapSegment } from "./types"
|
7 |
-
|
8 |
-
export async function serializeClap({
|
9 |
-
meta, // ClapMeta
|
10 |
-
models, // ClapModel[]
|
11 |
-
scenes, // ClapScene[]
|
12 |
-
segments, // ClapSegment[]
|
13 |
-
}: ClapProject): Promise<Blob> {
|
14 |
-
|
15 |
-
// we play it safe, and we verify the structure of the parameters,
|
16 |
-
// to make sure we generate a valid clap file
|
17 |
-
const clapModels: ClapModel[] = models.map(({
|
18 |
-
id,
|
19 |
-
category,
|
20 |
-
triggerName,
|
21 |
-
label,
|
22 |
-
description,
|
23 |
-
author,
|
24 |
-
thumbnailUrl,
|
25 |
-
seed,
|
26 |
-
assetSourceType,
|
27 |
-
assetUrl,
|
28 |
-
age,
|
29 |
-
gender,
|
30 |
-
region,
|
31 |
-
appearance,
|
32 |
-
voiceVendor,
|
33 |
-
voiceId,
|
34 |
-
}) => ({
|
35 |
-
id,
|
36 |
-
category,
|
37 |
-
triggerName,
|
38 |
-
label,
|
39 |
-
description,
|
40 |
-
author,
|
41 |
-
thumbnailUrl,
|
42 |
-
seed,
|
43 |
-
assetSourceType,
|
44 |
-
assetUrl,
|
45 |
-
age,
|
46 |
-
gender,
|
47 |
-
region,
|
48 |
-
appearance,
|
49 |
-
voiceVendor,
|
50 |
-
voiceId,
|
51 |
-
}))
|
52 |
-
|
53 |
-
const clapScenes: ClapScene[] = scenes.map(({
|
54 |
-
id,
|
55 |
-
scene,
|
56 |
-
line,
|
57 |
-
rawLine,
|
58 |
-
sequenceFullText,
|
59 |
-
sequenceStartAtLine,
|
60 |
-
sequenceEndAtLine,
|
61 |
-
startAtLine,
|
62 |
-
endAtLine,
|
63 |
-
events,
|
64 |
-
}) => ({
|
65 |
-
id,
|
66 |
-
scene,
|
67 |
-
line,
|
68 |
-
rawLine,
|
69 |
-
sequenceFullText,
|
70 |
-
sequenceStartAtLine,
|
71 |
-
sequenceEndAtLine,
|
72 |
-
startAtLine,
|
73 |
-
endAtLine,
|
74 |
-
events: events.map(e => e)
|
75 |
-
}))
|
76 |
-
|
77 |
-
const clapSegments: ClapSegment[] = segments.map(({
|
78 |
-
id,
|
79 |
-
track,
|
80 |
-
startTimeInMs,
|
81 |
-
endTimeInMs,
|
82 |
-
category,
|
83 |
-
modelId,
|
84 |
-
sceneId,
|
85 |
-
prompt,
|
86 |
-
label,
|
87 |
-
outputType,
|
88 |
-
renderId,
|
89 |
-
status,
|
90 |
-
assetUrl,
|
91 |
-
assetDurationInMs,
|
92 |
-
createdBy,
|
93 |
-
editedBy,
|
94 |
-
outputGain,
|
95 |
-
seed,
|
96 |
-
}) => ({
|
97 |
-
id,
|
98 |
-
track,
|
99 |
-
startTimeInMs,
|
100 |
-
endTimeInMs,
|
101 |
-
category,
|
102 |
-
modelId,
|
103 |
-
sceneId,
|
104 |
-
prompt,
|
105 |
-
label,
|
106 |
-
outputType,
|
107 |
-
renderId,
|
108 |
-
status,
|
109 |
-
assetUrl,
|
110 |
-
assetDurationInMs,
|
111 |
-
createdBy,
|
112 |
-
editedBy,
|
113 |
-
outputGain,
|
114 |
-
seed,
|
115 |
-
}))
|
116 |
-
|
117 |
-
const clapHeader: ClapHeader = {
|
118 |
-
format: "clap-0",
|
119 |
-
numberOfModels: clapModels.length,
|
120 |
-
numberOfScenes: clapScenes.length,
|
121 |
-
numberOfSegments: clapSegments.length,
|
122 |
-
}
|
123 |
-
|
124 |
-
const clapMeta: ClapMeta = {
|
125 |
-
id: meta.id || uuidv4(),
|
126 |
-
title: typeof meta.title === "string" ? meta.title : "Untitled",
|
127 |
-
description: typeof meta.description === "string" ? meta.description : "",
|
128 |
-
synopsis: typeof meta.synopsis === "string" ? meta.synopsis : "",
|
129 |
-
licence: typeof meta.licence === "string" ? meta.licence : "",
|
130 |
-
orientation: meta.orientation === "portrait" ? "portrait" : meta.orientation === "square" ? "square" : "landscape",
|
131 |
-
durationInMs: getValidNumber(meta.durationInMs, 1000, Number.MAX_SAFE_INTEGER, 4000),
|
132 |
-
width: getValidNumber(meta.width, 256, 8192, 1024),
|
133 |
-
height: getValidNumber(meta.height, 256, 8192, 576),
|
134 |
-
defaultVideoModel: typeof meta.defaultVideoModel === "string" ? meta.defaultVideoModel : "SVD",
|
135 |
-
extraPositivePrompt: Array.isArray(meta.extraPositivePrompt) ? meta.extraPositivePrompt : [],
|
136 |
-
screenplay: typeof meta.screenplay === "string" ? meta.screenplay : "",
|
137 |
-
isLoop: typeof meta.screenplay === "boolean" ? meta.screenplay : false,
|
138 |
-
isInteractive: typeof meta.isInteractive === "boolean" ? meta.isInteractive : false,
|
139 |
-
}
|
140 |
-
|
141 |
-
const entries = [
|
142 |
-
clapHeader,
|
143 |
-
clapMeta,
|
144 |
-
...clapModels,
|
145 |
-
...clapScenes,
|
146 |
-
...clapSegments
|
147 |
-
]
|
148 |
-
|
149 |
-
const strigifiedResult = YAML.stringify(entries)
|
150 |
-
|
151 |
-
// Convert the string to a Blob
|
152 |
-
const blobResult = new Blob([strigifiedResult], { type: "application/x-yaml" })
|
153 |
-
|
154 |
-
// Create a stream for the blob
|
155 |
-
const readableStream = blobResult.stream()
|
156 |
-
|
157 |
-
// Compress the stream using gzip
|
158 |
-
const compressionStream = new CompressionStream('gzip')
|
159 |
-
const compressedStream = readableStream.pipeThrough(compressionStream)
|
160 |
-
|
161 |
-
// Create a new blob from the compressed stream
|
162 |
-
const response = new Response(compressedStream)
|
163 |
-
|
164 |
-
response.headers.set("Content-Type", "application/x-gzip")
|
165 |
-
|
166 |
-
const compressedBlob = await response.blob()
|
167 |
-
|
168 |
-
return compressedBlob
|
169 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/clap/types.ts
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 // usually track 0 is the video, track 1 is the storyboard, track 2 is the camera
|
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/lib/prompts/generateSeed.ts
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
export function generateSeed() {
|
2 |
-
return Math.floor(Math.random() * Math.pow(2, 31));
|
3 |
-
}
|
|
|
|
|
|
|
|
src/lib/utils/generateSeed.ts
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
export function generateSeed() {
|
2 |
-
return Math.floor(Math.random() * Math.pow(2, 31));
|
3 |
-
}
|
|
|
|
|
|
|
|
src/lib/utils/startOfSegment1IsWithinSegment2.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
import { ClapSegment } from "
|
2 |
|
3 |
export function startOfSegment1IsWithinSegment2(s1: ClapSegment, s2: ClapSegment) {
|
4 |
const startOfSegment1 = s1.startTimeInMs
|
|
|
1 |
+
import { ClapSegment } from "@aitube/clap"
|
2 |
|
3 |
export function startOfSegment1IsWithinSegment2(s1: ClapSegment, s2: ClapSegment) {
|
4 |
const startOfSegment1 = s1.startTimeInMs
|