jbilcke-hf HF staff commited on
Commit
0d218b1
1 Parent(s): 83defd6

let's use @aitube/clap inside AiTube

Browse files
Files changed (50) hide show
  1. .env +2 -0
  2. next.config.js +3 -0
  3. package-lock.json +96 -75
  4. package.json +3 -2
  5. src/app/api/actions/ai-tube-hf/downloadClapProject.ts +3 -3
  6. src/app/api/generate/models/generateAudioID.ts +12 -0
  7. src/app/api/generate/models/generateImageID.ts +68 -0
  8. src/app/api/generate/models/route.ts +75 -0
  9. src/app/api/generate/models/systemPrompt.ts +3 -0
  10. src/app/api/generate/story/route.ts +4 -7
  11. src/app/api/generate/storyboards/generateStoryboard.ts +1 -2
  12. src/app/api/generate/storyboards/route.ts +13 -14
  13. src/app/api/generate/video/route.ts +2 -1
  14. src/app/api/generators/clap/addLatentScenesToClap.ts +1 -5
  15. src/app/api/generators/clap/continueClap.ts +2 -5
  16. src/app/api/generators/clap/generateClap.ts +4 -6
  17. src/app/api/generators/search/unknownObjectToLatentSearchResults.ts +2 -1
  18. src/app/api/resolvers/clap/route.ts +1 -0
  19. src/app/api/resolvers/image/route.ts +1 -1
  20. src/app/api/resolvers/video/route.ts +2 -1
  21. src/app/dream/spoiler.tsx +1 -2
  22. src/components/interface/latent-engine/core/engine.tsx +3 -4
  23. src/components/interface/latent-engine/core/generators/fetchLatentClap.ts +1 -2
  24. src/components/interface/latent-engine/core/prompts/getCharacterPrompt.ts +1 -1
  25. src/components/interface/latent-engine/core/prompts/getVideoPrompt.ts +1 -1
  26. src/components/interface/latent-engine/core/types.ts +1 -1
  27. src/components/interface/latent-engine/core/useLatentEngine.ts +4 -8
  28. src/components/interface/latent-engine/resolvers/deprecated.txt +1 -1
  29. src/components/interface/latent-engine/resolvers/generic/index.tsx +1 -1
  30. src/components/interface/latent-engine/resolvers/image/index.tsx +1 -1
  31. src/components/interface/latent-engine/resolvers/interface/index.tsx +1 -1
  32. src/components/interface/latent-engine/resolvers/resolveSegment.ts +1 -1
  33. src/components/interface/latent-engine/resolvers/resolveSegments.ts +1 -1
  34. src/components/interface/latent-engine/resolvers/video/index.tsx +1 -1
  35. src/components/interface/latent-engine/resolvers/video/index_legacy.tsx +1 -1
  36. src/components/interface/latent-engine/resolvers/video/index_notSoGood.tsx +1 -1
  37. src/lib/business/getClapAssetSourceType.ts +1 -1
  38. src/lib/clap/clap-specification-draft.md +0 -162
  39. src/lib/clap/clapToDataUri.ts +0 -10
  40. src/lib/clap/emptyClap.ts +0 -18
  41. src/lib/clap/generateClapFromSimpleStory.ts +0 -149
  42. src/lib/clap/getClapAssetSource.ts +0 -25
  43. src/lib/clap/newClap.ts +0 -37
  44. src/lib/clap/newSegment.ts +0 -46
  45. src/lib/clap/parseClap.ts +0 -319
  46. src/lib/clap/serializeClap.ts +0 -169
  47. src/lib/clap/types.ts +0 -203
  48. src/lib/prompts/generateSeed.ts +0 -3
  49. src/lib/utils/generateSeed.ts +0 -3
  50. 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.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.20240422",
1498
- "resolved": "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.13-rc.20240422.tgz",
1499
- "integrity": "sha512-yKUS+Qidsw0pttv8Bx/EOdGkcWLH0b1tO4D0HfM6PaBjBAFUr7l5OmRfToFh4k8/XPto6d3X8Ujvm37Da0n2nw=="
1500
  },
1501
  "node_modules/@next/env": {
1502
- "version": "14.2.2",
1503
- "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.2.tgz",
1504
- "integrity": "sha512-sk72qRfM1Q90XZWYRoJKu/UWlTgihrASiYw/scb15u+tyzcze3bOuJ/UV6TBOQEeUaxOkRqGeuGUdiiuxc5oqw=="
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.2",
1516
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.2.tgz",
1517
- "integrity": "sha512-3iPgMhzbalizGwHNFUcGnDhFPSgVBHQ8aqSTAMxB5BvJG0oYrDf1WOJZlbXBgunOEj/8KMVbejEur/FpvFsgFQ==",
1518
  "cpu": [
1519
  "arm64"
1520
  ],
@@ -1527,9 +1540,9 @@
1527
  }
1528
  },
1529
  "node_modules/@next/swc-darwin-x64": {
1530
- "version": "14.2.2",
1531
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.2.tgz",
1532
- "integrity": "sha512-x7Afi/jt0ZBRUZHTi49yyej4o8znfIMHO4RvThuoc0P+uli8Jd99y5GKjxoYunPKsXL09xBXEM1+OQy2xEL0Ag==",
1533
  "cpu": [
1534
  "x64"
1535
  ],
@@ -1542,9 +1555,9 @@
1542
  }
1543
  },
1544
  "node_modules/@next/swc-linux-arm64-gnu": {
1545
- "version": "14.2.2",
1546
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.2.tgz",
1547
- "integrity": "sha512-zbfPtkk7L41ODMJwSp5VbmPozPmMMQrzAc0HAUomVeVIIwlDGs/UCqLJvLNDt4jpWgc21SjjyIn762lNGrMaUA==",
1548
  "cpu": [
1549
  "arm64"
1550
  ],
@@ -1557,9 +1570,9 @@
1557
  }
1558
  },
1559
  "node_modules/@next/swc-linux-arm64-musl": {
1560
- "version": "14.2.2",
1561
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.2.tgz",
1562
- "integrity": "sha512-wPbS3pI/JU16rm3XdLvvTmlsmm1nd+sBa2ohXgBZcShX4TgOjD4R+RqHKlI1cjo/jDZKXt6OxmcU0Iys0OC/yg==",
1563
  "cpu": [
1564
  "arm64"
1565
  ],
@@ -1572,9 +1585,9 @@
1572
  }
1573
  },
1574
  "node_modules/@next/swc-linux-x64-gnu": {
1575
- "version": "14.2.2",
1576
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.2.tgz",
1577
- "integrity": "sha512-NqWOHqqq8iC9tuHvZxjQ2tX+jWy2X9y8NX2mcB4sj2bIccuCxbIZrU/ThFPZZPauygajZuVQ6zediejQHwZHwQ==",
1578
  "cpu": [
1579
  "x64"
1580
  ],
@@ -1587,9 +1600,9 @@
1587
  }
1588
  },
1589
  "node_modules/@next/swc-linux-x64-musl": {
1590
- "version": "14.2.2",
1591
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.2.tgz",
1592
- "integrity": "sha512-lGepHhwb9sGhCcU7999+iK1ZZT+6rrIoVg40MP7DZski9GIZP80wORSbt5kJzh9v2x2ev2lxC6VgwMQT0PcgTA==",
1593
  "cpu": [
1594
  "x64"
1595
  ],
@@ -1602,9 +1615,9 @@
1602
  }
1603
  },
1604
  "node_modules/@next/swc-win32-arm64-msvc": {
1605
- "version": "14.2.2",
1606
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.2.tgz",
1607
- "integrity": "sha512-TZSh/48SfcLEQ4rD25VVn2kdIgUWmMflRX3OiyPwGNXn3NiyPqhqei/BaqCYXViIQ+6QsG9R0C8LftMqy8JPMA==",
1608
  "cpu": [
1609
  "arm64"
1610
  ],
@@ -1617,9 +1630,9 @@
1617
  }
1618
  },
1619
  "node_modules/@next/swc-win32-ia32-msvc": {
1620
- "version": "14.2.2",
1621
- "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.2.tgz",
1622
- "integrity": "sha512-M0tBVNMEBJN2ZNQWlcekMn6pvLria7Sa2Fai5znm7CCJz4pP3lrvlSxhKdkCerk0D9E0bqx5yAo3o2Q7RrD4gA==",
1623
  "cpu": [
1624
  "ia32"
1625
  ],
@@ -1632,9 +1645,9 @@
1632
  }
1633
  },
1634
  "node_modules/@next/swc-win32-x64-msvc": {
1635
- "version": "14.2.2",
1636
- "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.2.tgz",
1637
- "integrity": "sha512-a/20E/wtTJZ3Ykv3f/8F0l7TtgQa2LWHU2oNB9bsu0VjqGuGGHmm/q6waoUNQYTVPYrrlxxaHjJcDV6aiSTt/w==",
1638
  "cpu": [
1639
  "x64"
1640
  ],
@@ -3792,9 +3805,9 @@
3792
  "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
3793
  },
3794
  "node_modules/clsx": {
3795
- "version": "2.1.0",
3796
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
3797
- "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==",
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.746",
4278
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.746.tgz",
4279
- "integrity": "sha512-jeWaIta2rIG2FzHaYIhSuVWqC6KJYo7oSBX4Jv7g+aVujKztfvdpf+n6MGwZdC5hQXbax4nntykLH2juIQrfPg=="
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.18",
4408
- "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz",
4409
- "integrity": "sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==",
4410
  "dependencies": {
4411
  "call-bind": "^1.0.7",
4412
  "define-properties": "^1.2.1",
4413
- "es-abstract": "^1.23.0",
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.2",
6339
- "resolved": "https://registry.npmjs.org/next/-/next-14.2.2.tgz",
6340
- "integrity": "sha512-oGwUaa2bCs47FbuxWMpOoXtBMPYpvTPgdZr3UAo+pu7Ns00z9otmYpoeV1HEiYL06AlRQQIA/ypK526KjJfaxg==",
6341
  "dependencies": {
6342
- "@next/env": "14.2.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.2",
6358
- "@next/swc-darwin-x64": "14.2.2",
6359
- "@next/swc-linux-arm64-gnu": "14.2.2",
6360
- "@next/swc-linux-arm64-musl": "14.2.2",
6361
- "@next/swc-linux-x64-gnu": "14.2.2",
6362
- "@next/swc-linux-x64-musl": "14.2.2",
6363
- "@next/swc-win32-arm64-msvc": "14.2.2",
6364
- "@next/swc-win32-ia32-msvc": "14.2.2",
6365
- "@next/swc-win32-x64-msvc": "14.2.2"
6366
  },
6367
  "peerDependencies": {
6368
  "@opentelemetry/api": "^1.1.0",
@@ -6616,9 +6629,9 @@
6616
  }
6617
  },
6618
  "node_modules/openai": {
6619
- "version": "4.38.3",
6620
- "resolved": "https://registry.npmjs.org/openai/-/openai-4.38.3.tgz",
6621
- "integrity": "sha512-mIL9WtrFNOanpx98mJ+X/wkoepcxdqqu0noWFoNQHl/yODQ47YM7NEYda7qp8JfjqpLFVxY9mQhshoS/Fqac0A==",
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.0",
6750
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
6751
- "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
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.0",
7437
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
7438
- "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
7439
  "dependencies": {
7440
  "loose-envify": "^1.1.0"
7441
  }
@@ -8097,9 +8118,9 @@
8097
  }
8098
  },
8099
  "node_modules/three": {
8100
- "version": "0.163.0",
8101
- "resolved": "https://registry.npmjs.org/three/-/three-0.163.0.tgz",
8102
- "integrity": "sha512-HlMgCb2TF/dTLRtknBnjUTsR8FsDqBY43itYop2+Zg822I+Kd0Ua2vs8CvfBVefXkBdNDrLMoRTGCIIpfCuDew==",
8103
  "peer": true
8104
  },
8105
  "node_modules/to-regex-range": {
@@ -8227,9 +8248,9 @@
8227
  }
8228
  },
8229
  "node_modules/type-fest": {
8230
- "version": "4.16.0",
8231
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.16.0.tgz",
8232
- "integrity": "sha512-z7Rf5PXxIhbI6eJBTwdqe5bO02nUUmctq4WqviFSstBAWV0YNtEQRhEnZw73WJ8sZOqgFG6Jdl8gYZu7NBJZnA==",
8233
  "engines": {
8234
  "node": ">=16"
8235
  },
@@ -8315,9 +8336,9 @@
8315
  }
8316
  },
8317
  "node_modules/typescript": {
8318
- "version": "5.4.4",
8319
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz",
8320
- "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==",
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": "ai-tube",
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.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 "@/lib/clap/types"
 
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
- import { newSegment } from "@/lib/clap/newSegment"
 
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 "@/lib/clap/serializeClap"
4
- import { parseClap } from "@/lib/clap/parseClap"
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
- import { generateSeed } from "@/lib/utils/generateSeed"
 
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.prompt) {
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.assetUrl.slice(0, 50)}...`)
92
  } else {
93
- console.log(`[api/generate/storyboards] there is already a storyboard image: ${shotStoryboardSegment.assetUrl.slice(0, 50)}...`)
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
- NextResponse.redirect("https://jbilcke-hf-ai-tube-clap-exporter.hf.space")
 
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 { newClap } from "@/lib/clap/newClap"
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 "@/lib/utils/generateSeed"
 
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 "@/lib/clap/parseClap"
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 "@/lib/clap/types"
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 "@/lib/clap/types"
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 "@/lib/clap/types"
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 "@/lib/clap/types"
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
- import { dataUriToBlob } from "@/app/api/utils/dataUriToBlob"
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 "@/lib/clap/types";
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 "@/lib/clap/types"
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 "@/lib/clap/types"
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 "@/lib/clap/types"
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 "@/lib/clap/types"
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 "@/lib/clap/types"
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 "@/lib/clap/types"
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 "@/lib/clap/types"
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 "@/lib/clap/types"
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 "@/lib/clap/types"
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 "../clap/types"
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