jbilcke-hf HF staff commited on
Commit
0de2197
1 Parent(s): 74c9d0e

upgrade to openclap 0.1.1

Browse files
Files changed (30) hide show
  1. package-lock.json +1268 -312
  2. package.json +9 -6
  3. playwright.config.ts +4 -0
  4. src/components/monitor/index.tsx +1 -1
  5. src/components/toolbars/bottom-bar/index.tsx +1 -1
  6. src/components/toolbars/bottom-bar/metrics/index.tsx +1 -7
  7. src/components/toolbars/editors-menu/EditorsSideMenuItem.tsx +3 -3
  8. src/components/toolbars/top-menu/index.tsx +33 -2
  9. src/components/tree-browsers/stores/useEntityLibrary.ts +3 -3
  10. src/components/tree-browsers/stores/useProjectLibrary.ts +3 -3
  11. src/experiments/grading/README.md +3 -0
  12. src/experiments/grading/applyColorGrading.ts +225 -0
  13. src/experiments/grading/applyColorGradingDemo.ts +121 -0
  14. src/experiments/grading/filters/DEPRECATED_analogFilm.ts +171 -0
  15. src/experiments/grading/filters/analogLens.ts +228 -0
  16. src/experiments/grading/filters/cinematic.ts +98 -0
  17. src/experiments/grading/filters/colorMapping.ts +53 -0
  18. src/experiments/grading/filters/colorTemperature.ts +103 -0
  19. src/experiments/grading/filters/crossProcessing.ts +126 -0
  20. src/experiments/grading/filters/filmDegradation.ts +104 -0
  21. src/experiments/grading/filters/infrared.ts +87 -0
  22. src/experiments/grading/filters/lomography.ts +143 -0
  23. src/experiments/grading/filters/splitToning.ts +143 -0
  24. src/experiments/grading/filters/toneMapping.ts +148 -0
  25. src/experiments/grading/filters/vintageFilm.ts +299 -0
  26. src/experiments/grading/types.ts +22 -0
  27. src/lib/utils/formatSegmentForExport.test.ts +9 -4
  28. src/lib/utils/getTypeAndExtension.test.ts +4 -3
  29. src/services/ui/theme.ts +8 -2
  30. tsconfig.json +2 -1
package-lock.json CHANGED
@@ -9,11 +9,11 @@
9
  "version": "0.0.5",
10
  "license": "GPL-3.0-only",
11
  "dependencies": {
12
- "@aitube/broadway": "0.0.22",
13
- "@aitube/clap": "0.0.30",
14
- "@aitube/clapper-services": "0.0.35",
15
- "@aitube/engine": "0.0.26",
16
- "@aitube/timeline": "0.0.45",
17
  "@fal-ai/serverless-client": "^0.13.0",
18
  "@ffmpeg/ffmpeg": "^0.12.10",
19
  "@ffmpeg/util": "^0.12.1",
@@ -58,6 +58,7 @@
58
  "@types/dom-speech-recognition": "^0.0.4",
59
  "@xenova/transformers": "github:xenova/transformers.js#v3",
60
  "autoprefixer": "10.4.19",
 
61
  "class-variance-authority": "^0.7.0",
62
  "clsx": "^2.1.1",
63
  "cmdk": "^0.2.1",
@@ -120,6 +121,7 @@
120
  "@types/react-dom": "^18",
121
  "@types/uuid": "^9.0.8",
122
  "@vitejs/plugin-react": "^4.3.1",
 
123
  "electron": "^31.2.1",
124
  "eslint": "^8",
125
  "eslint-config-next": "14.2.5",
@@ -136,37 +138,37 @@
136
  }
137
  },
138
  "node_modules/@aitube/broadway": {
139
- "version": "0.0.22",
140
- "resolved": "https://registry.npmjs.org/@aitube/broadway/-/broadway-0.0.22.tgz",
141
- "integrity": "sha512-Koliw6Hg8QWx+iHqbaSdqpPmS21/AMzI7Bw5ecrNvRoURPEzJaBHjKo+q5Xk8AESHBU2ChNg+DLfjkgV1yHgyA==",
142
  "dependencies": {
143
  "@datagica/parse-entities": "^0.3.0",
144
  "@datagica/parse-names": "^0.0.8",
145
  "indexeddb-fs": "^2.1.5"
146
  },
147
  "peerDependencies": {
148
- "@aitube/clap": "0.0.30",
149
- "@aitube/colors": "0.0.9"
150
  }
151
  },
152
  "node_modules/@aitube/clap": {
153
- "version": "0.0.30",
154
- "resolved": "https://registry.npmjs.org/@aitube/clap/-/clap-0.0.30.tgz",
155
- "integrity": "sha512-vBIN8+heIVHYBTY0+Rzdx6SSAiALXlzrkn02SiBCCxDdWV3qPoiQPoY78OcIkVamNZenEZ5HRK/GpuA7fdoLEQ==",
156
  "dependencies": {
157
  "pure-uuid": "^1.8.1"
158
  },
159
  "peerDependencies": {
160
- "yaml": "^2.4.5"
161
  }
162
  },
163
  "node_modules/@aitube/clapper-services": {
164
- "version": "0.0.35",
165
- "resolved": "https://registry.npmjs.org/@aitube/clapper-services/-/clapper-services-0.0.35.tgz",
166
- "integrity": "sha512-qI0qj+8tKgv6vbhBvy+RKItITSIHsjdVq6NAuxjNwXYFhxgMFuZpj34gB0AcGH9ZShl7ZEGlqptU3B9pOpqa1A==",
167
  "peerDependencies": {
168
- "@aitube/clap": "0.0.30",
169
- "@aitube/timeline": "0.0.45",
170
  "@monaco-editor/react": "4.6.0",
171
  "monaco-editor": "0.50.0",
172
  "react": "*",
@@ -175,32 +177,32 @@
175
  }
176
  },
177
  "node_modules/@aitube/colors": {
178
- "version": "0.0.9",
179
- "resolved": "https://registry.npmjs.org/@aitube/colors/-/colors-0.0.9.tgz",
180
- "integrity": "sha512-Svu7nI7sVfoWrvEIdG8c0c2irhRPXphsTIh9rnesqcEJGtz/VIOqQBrYBKI+htTfGX5EeM5Q/rr7zUYrfK+pfQ==",
181
  "peer": true,
182
  "peerDependencies": {
183
- "@aitube/clap": "0.0.30"
184
  }
185
  },
186
  "node_modules/@aitube/engine": {
187
- "version": "0.0.26",
188
- "resolved": "https://registry.npmjs.org/@aitube/engine/-/engine-0.0.26.tgz",
189
- "integrity": "sha512-Wk5kfMo5T0Gr3XjQiJGJozmtQdPdq2U6Bl0SDYyeUyLBSM5eAmiLNf+mwsy8MqDpsIdGXIeJ8IJKlChEu0Uzkw==",
190
  "peerDependencies": {
191
- "@aitube/clap": "0.0.30"
192
  }
193
  },
194
  "node_modules/@aitube/timeline": {
195
- "version": "0.0.45",
196
- "resolved": "https://registry.npmjs.org/@aitube/timeline/-/timeline-0.0.45.tgz",
197
- "integrity": "sha512-5nDn4O7z72WvZeXVAzGn+HjRhKvTpZb4OAnOMmHCpQ5bwaublaVYN1JV8wurgh+KN/N1IQgUbTe2NSQuF9EWkQ==",
198
  "dependencies": {
199
  "date-fns": "^3.6.0",
200
  "react-virtualized-auto-sizer": "^1.0.24"
201
  },
202
  "peerDependencies": {
203
- "@aitube/clap": "0.0.30",
204
  "@radix-ui/react-slider": "^1.1.2",
205
  "@react-spring/three": "^9.7.3",
206
  "@react-spring/types": "^9.7.3",
@@ -209,8 +211,8 @@
209
  "clsx": "^2.1.1",
210
  "react": "*",
211
  "react-dom": "*",
212
- "tailwind-merge": "^2.3.0",
213
- "tailwindcss": "^3.4.3",
214
  "three": "^0.164.1",
215
  "zustand": "4.5.2"
216
  }
@@ -254,9 +256,9 @@
254
  }
255
  },
256
  "node_modules/@anthropic-ai/sdk/node_modules/@types/node": {
257
- "version": "18.19.41",
258
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.41.tgz",
259
- "integrity": "sha512-LX84pRJ+evD2e2nrgYCHObGWkiQJ1mL+meAgbvnwk/US6vmMY7S2ygBTGV2Jw91s9vUsLSXeDEkUHZIJGLrhsg==",
260
  "dependencies": {
261
  "undici-types": "~5.26.4"
262
  }
@@ -837,9 +839,9 @@
837
  }
838
  },
839
  "node_modules/@aws-sdk/credential-providers": {
840
- "version": "3.616.0",
841
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.616.0.tgz",
842
- "integrity": "sha512-uyscpYV21lr24FNFu8ZkIKzOCD/xoysRci9HmShtKBY/FixwZRlLv7aUpqH7xcLd7sgsQwa2UD/7s9PKj/DXSg==",
843
  "dependencies": {
844
  "@aws-sdk/client-cognito-identity": "3.616.0",
845
  "@aws-sdk/client-sso": "3.616.0",
@@ -1618,6 +1620,15 @@
1618
  "statuses": "^2.0.1"
1619
  }
1620
  },
 
 
 
 
 
 
 
 
 
1621
  "node_modules/@cspotcode/source-map-support": {
1622
  "version": "0.8.1",
1623
  "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
@@ -2823,6 +2834,15 @@
2823
  "node": ">=14.14"
2824
  }
2825
  },
 
 
 
 
 
 
 
 
 
2826
  "node_modules/@emotion/is-prop-valid": {
2827
  "version": "1.3.0",
2828
  "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.0.tgz",
@@ -2846,294 +2866,1034 @@
2846
  "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
2847
  "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
2848
  },
2849
- "node_modules/@esbuild/darwin-arm64": {
2850
  "version": "0.21.5",
2851
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
2852
- "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
2853
  "cpu": [
2854
- "arm64"
2855
  ],
2856
  "dev": true,
2857
  "optional": true,
2858
  "os": [
2859
- "darwin"
2860
  ],
2861
  "engines": {
2862
  "node": ">=12"
2863
  }
2864
  },
2865
- "node_modules/@eslint-community/eslint-utils": {
2866
- "version": "4.4.0",
2867
- "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
2868
- "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
 
 
 
2869
  "dev": true,
2870
- "dependencies": {
2871
- "eslint-visitor-keys": "^3.3.0"
2872
- },
 
2873
  "engines": {
2874
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
2875
- },
2876
- "peerDependencies": {
2877
- "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
2878
  }
2879
  },
2880
- "node_modules/@eslint-community/regexpp": {
2881
- "version": "4.11.0",
2882
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz",
2883
- "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==",
 
 
 
2884
  "dev": true,
 
 
 
 
2885
  "engines": {
2886
- "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
2887
  }
2888
  },
2889
- "node_modules/@eslint/eslintrc": {
2890
- "version": "2.1.4",
2891
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
2892
- "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
 
 
 
2893
  "dev": true,
2894
- "dependencies": {
2895
- "ajv": "^6.12.4",
2896
- "debug": "^4.3.2",
2897
- "espree": "^9.6.0",
2898
- "globals": "^13.19.0",
2899
- "ignore": "^5.2.0",
2900
- "import-fresh": "^3.2.1",
2901
- "js-yaml": "^4.1.0",
2902
- "minimatch": "^3.1.2",
2903
- "strip-json-comments": "^3.1.1"
2904
- },
2905
  "engines": {
2906
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
2907
- },
2908
- "funding": {
2909
- "url": "https://opencollective.com/eslint"
2910
  }
2911
  },
2912
- "node_modules/@eslint/eslintrc/node_modules/globals": {
2913
- "version": "13.24.0",
2914
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
2915
- "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
 
 
 
2916
  "dev": true,
2917
- "dependencies": {
2918
- "type-fest": "^0.20.2"
2919
- },
 
2920
  "engines": {
2921
- "node": ">=8"
2922
- },
2923
- "funding": {
2924
- "url": "https://github.com/sponsors/sindresorhus"
2925
  }
2926
  },
2927
- "node_modules/@eslint/eslintrc/node_modules/type-fest": {
2928
- "version": "0.20.2",
2929
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
2930
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
 
 
 
2931
  "dev": true,
 
 
 
 
2932
  "engines": {
2933
- "node": ">=10"
2934
- },
2935
- "funding": {
2936
- "url": "https://github.com/sponsors/sindresorhus"
2937
  }
2938
  },
2939
- "node_modules/@eslint/js": {
2940
- "version": "8.57.0",
2941
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
2942
- "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
 
 
 
2943
  "dev": true,
 
 
 
 
2944
  "engines": {
2945
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
2946
  }
2947
  },
2948
- "node_modules/@fal-ai/serverless-client": {
2949
- "version": "0.13.0",
2950
- "resolved": "https://registry.npmjs.org/@fal-ai/serverless-client/-/serverless-client-0.13.0.tgz",
2951
- "integrity": "sha512-Nkb/5YXJIPQHzM79+fRb1LZ1zQLSSvNhDVL2l62sN6/H4XqAWueIOqAAvPF8ds39uSGn8nF1WQV1mt7raVMlWw==",
2952
- "dependencies": {
2953
- "@msgpack/msgpack": "^3.0.0-beta2",
2954
- "eventsource-parser": "^1.1.2",
2955
- "robot3": "^0.4.1",
2956
- "uuid-random": "^1.3.2"
2957
- },
 
 
2958
  "engines": {
2959
- "node": ">=18.0.0"
2960
  }
2961
  },
2962
- "node_modules/@ffmpeg/ffmpeg": {
2963
- "version": "0.12.10",
2964
- "resolved": "https://registry.npmjs.org/@ffmpeg/ffmpeg/-/ffmpeg-0.12.10.tgz",
2965
- "integrity": "sha512-lVtk8PW8e+NUzGZhPTWj2P1J4/NyuCrbDD3O9IGpSeLYtUZKBqZO8CNj1WYGghep/MXoM8e1qVY1GztTkf8YYQ==",
2966
- "dependencies": {
2967
- "@ffmpeg/types": "^0.12.2"
2968
- },
 
 
 
 
 
2969
  "engines": {
2970
- "node": ">=18.x"
2971
  }
2972
  },
2973
- "node_modules/@ffmpeg/types": {
2974
- "version": "0.12.2",
2975
- "resolved": "https://registry.npmjs.org/@ffmpeg/types/-/types-0.12.2.tgz",
2976
- "integrity": "sha512-NJtxwPoLb60/z1Klv0ueshguWQ/7mNm106qdHkB4HL49LXszjhjCCiL+ldHJGQ9ai2Igx0s4F24ghigy//ERdA==",
 
 
 
 
 
 
 
 
2977
  "engines": {
2978
- "node": ">=16.x"
2979
  }
2980
  },
2981
- "node_modules/@ffmpeg/util": {
2982
- "version": "0.12.1",
2983
- "resolved": "https://registry.npmjs.org/@ffmpeg/util/-/util-0.12.1.tgz",
2984
- "integrity": "sha512-10jjfAKWaDyb8+nAkijcsi9wgz/y26LOc1NKJradNMyCIl6usQcBbhkjX5qhALrSBcOy6TOeksunTYa+a03qNQ==",
 
 
 
 
 
 
 
 
2985
  "engines": {
2986
- "node": ">=18.x"
2987
  }
2988
  },
2989
- "node_modules/@floating-ui/core": {
2990
- "version": "1.6.5",
2991
- "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.5.tgz",
2992
- "integrity": "sha512-8GrTWmoFhm5BsMZOTHeGD2/0FLKLQQHvO/ZmQga4tKempYRLz8aqJGqXVuQgisnMObq2YZ2SgkwctN1LOOxcqA==",
2993
- "dependencies": {
2994
- "@floating-ui/utils": "^0.2.5"
 
 
 
 
 
 
 
 
2995
  }
2996
  },
2997
- "node_modules/@floating-ui/dom": {
2998
- "version": "1.6.8",
2999
- "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.8.tgz",
3000
- "integrity": "sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q==",
3001
- "dependencies": {
3002
- "@floating-ui/core": "^1.6.0",
3003
- "@floating-ui/utils": "^0.2.5"
 
 
 
 
 
 
 
3004
  }
3005
  },
3006
- "node_modules/@floating-ui/react-dom": {
3007
- "version": "2.1.1",
3008
- "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz",
3009
- "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==",
3010
- "dependencies": {
3011
- "@floating-ui/dom": "^1.0.0"
3012
- },
3013
- "peerDependencies": {
3014
- "react": ">=16.8.0",
3015
- "react-dom": ">=16.8.0"
 
 
 
 
3016
  }
3017
  },
3018
- "node_modules/@floating-ui/utils": {
3019
- "version": "0.2.5",
3020
- "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.5.tgz",
3021
- "integrity": "sha512-sTcG+QZ6fdEUObICavU+aB3Mp8HY4n14wYHdxK4fXjPmv3PXZZeY5RaguJmGyeH/CJQhX3fqKUtS4qc1LoHwhQ=="
 
 
 
 
 
 
 
 
 
 
 
3022
  },
3023
- "node_modules/@gar/promisify": {
3024
- "version": "1.1.3",
3025
- "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
3026
- "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
3027
- "dev": true
 
 
 
 
 
 
 
 
 
 
3028
  },
3029
- "node_modules/@gradio/client": {
3030
- "version": "1.3.0",
3031
- "resolved": "https://registry.npmjs.org/@gradio/client/-/client-1.3.0.tgz",
3032
- "integrity": "sha512-hy7brBNQGmJLUQ69gOMrcp4LGHAPknFy5Jl30EF0+VEBSjv8e3f7hPAq15QPJWY9SDDie7Mmg+epx7H+V1a8og==",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3033
  "dependencies": {
3034
- "@types/eventsource": "^1.1.15",
3035
- "bufferutil": "^4.0.7",
3036
- "eventsource": "^2.0.2",
3037
- "fetch-event-stream": "^0.1.5",
3038
- "msw": "^2.2.1",
3039
- "semiver": "^1.1.0",
3040
- "textlinestream": "^1.1.1",
3041
- "typescript": "^5.0.0",
3042
- "ws": "^8.13.0"
3043
  },
3044
  "engines": {
3045
- "node": ">=18.0.0"
 
 
 
3046
  }
3047
  },
3048
- "node_modules/@huggingface/hub": {
3049
- "version": "0.15.1",
3050
- "resolved": "https://registry.npmjs.org/@huggingface/hub/-/hub-0.15.1.tgz",
3051
- "integrity": "sha512-uHb4aFkJDoGfLeRHfFTjkI36Z8IV6Z1c+KzhMDqUSC56opyr7Mn1Nsx7Rri/C7KDwROhQfBp/fOOqqjTzn6Cgg==",
 
 
 
 
 
 
 
 
 
 
3052
  "dependencies": {
3053
- "@huggingface/tasks": "^0.10.6",
3054
- "hash-wasm": "^4.9.0"
 
 
 
 
 
 
 
3055
  },
3056
  "engines": {
3057
- "node": ">=18"
 
 
 
3058
  }
3059
  },
3060
- "node_modules/@huggingface/inference": {
3061
- "version": "2.8.0",
3062
- "resolved": "https://registry.npmjs.org/@huggingface/inference/-/inference-2.8.0.tgz",
3063
- "integrity": "sha512-Ti681P1qckcCAqgzmL53jBnluPuZGelmMIuXNjgAwC5+RIjF4S0SDQu6oy44ZTwekwNp2ETaZ2sXsOk+45aC4w==",
 
3064
  "dependencies": {
3065
- "@huggingface/tasks": "^0.11.2"
3066
  },
3067
  "engines": {
3068
- "node": ">=18"
 
 
 
3069
  }
3070
  },
3071
- "node_modules/@huggingface/inference/node_modules/@huggingface/tasks": {
3072
- "version": "0.11.3",
3073
- "resolved": "https://registry.npmjs.org/@huggingface/tasks/-/tasks-0.11.3.tgz",
3074
- "integrity": "sha512-IYq4OdlySdscjkFwm6iIqP1ZgKl4OGhvQFJWI7Yxpq2V8RmXcgIjiqk/65S6Ap7i+eyCdlOC4qweVy/ICNE0JA=="
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3075
  },
3076
- "node_modules/@huggingface/jinja": {
3077
- "version": "0.2.2",
3078
- "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.2.2.tgz",
3079
- "integrity": "sha512-/KPde26khDUIPkTGU82jdtTW9UAuvUTumCAbFs/7giR0SxsvZC4hru51PBvpijH6BVkHcROcvZM/lpy5h1jRRA==",
 
 
 
 
 
 
 
3080
  "engines": {
3081
- "node": ">=18"
 
 
 
 
 
 
 
 
 
 
3082
  }
3083
  },
3084
- "node_modules/@huggingface/tasks": {
3085
- "version": "0.10.22",
3086
- "resolved": "https://registry.npmjs.org/@huggingface/tasks/-/tasks-0.10.22.tgz",
3087
- "integrity": "sha512-sCtp+A6sq6NXoUU7NXuXWoVNNjKddk1GTQIh3cJ6illF8S4zmFoerCVRvFf19BdgICGvF+RVZiv9sGGK9KRDTg=="
3088
- },
3089
- "node_modules/@humanwhocodes/config-array": {
3090
- "version": "0.11.14",
3091
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
3092
- "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
3093
- "deprecated": "Use @eslint/config-array instead",
3094
- "dev": true,
3095
  "dependencies": {
3096
- "@humanwhocodes/object-schema": "^2.0.2",
3097
- "debug": "^4.3.1",
3098
- "minimatch": "^3.0.5"
3099
  },
3100
  "engines": {
3101
- "node": ">=10.10.0"
3102
- }
3103
- },
3104
- "node_modules/@humanwhocodes/module-importer": {
3105
- "version": "1.0.1",
3106
- "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
3107
- "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
3108
- "dev": true,
3109
- "engines": {
3110
- "node": ">=12.22"
3111
  },
3112
  "funding": {
3113
- "type": "github",
3114
- "url": "https://github.com/sponsors/nzakas"
3115
  }
3116
  },
3117
- "node_modules/@humanwhocodes/object-schema": {
3118
- "version": "2.0.3",
3119
- "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
3120
- "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
3121
- "deprecated": "Use @eslint/object-schema instead",
3122
- "dev": true
3123
- },
3124
- "node_modules/@img/sharp-darwin-arm64": {
3125
  "version": "0.33.4",
3126
- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.4.tgz",
3127
- "integrity": "sha512-p0suNqXufJs9t3RqLBO6vvrgr5OhgbWp76s5gTRvdmxmuv9E1rcaqGUsl3l4mKVmXPkTkTErXediAui4x+8PSA==",
3128
  "cpu": [
3129
- "arm64"
3130
  ],
3131
  "optional": true,
3132
  "os": [
3133
- "darwin"
3134
  ],
3135
  "engines": {
3136
- "glibc": ">=2.26",
3137
  "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
3138
  "npm": ">=9.6.5",
3139
  "pnpm": ">=7.1.0",
@@ -3141,24 +3901,21 @@
3141
  },
3142
  "funding": {
3143
  "url": "https://opencollective.com/libvips"
3144
- },
3145
- "optionalDependencies": {
3146
- "@img/sharp-libvips-darwin-arm64": "1.0.2"
3147
  }
3148
  },
3149
- "node_modules/@img/sharp-libvips-darwin-arm64": {
3150
- "version": "1.0.2",
3151
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.2.tgz",
3152
- "integrity": "sha512-tcK/41Rq8IKlSaKRCCAuuY3lDJjQnYIW1UXU1kxcEKrfL8WR7N6+rzNoOxoQRJWTAECuKwgAHnPvqXGN8XfkHA==",
3153
  "cpu": [
3154
- "arm64"
3155
  ],
3156
  "optional": true,
3157
  "os": [
3158
- "darwin"
3159
  ],
3160
  "engines": {
3161
- "macos": ">=11",
3162
  "npm": ">=9.6.5",
3163
  "pnpm": ">=7.1.0",
3164
  "yarn": ">=3.2.0"
@@ -3418,9 +4175,9 @@
3418
  }
3419
  },
3420
  "node_modules/@langchain/anthropic": {
3421
- "version": "0.2.6",
3422
- "resolved": "https://registry.npmjs.org/@langchain/anthropic/-/anthropic-0.2.6.tgz",
3423
- "integrity": "sha512-mFBC944rKGy+oRKWOmCmABPj+pQ2S8FcvyFGavFgIqjWlnBk9PwMjWm8IEdWwaSEahJXuEL9xAV2StWazWdXvg==",
3424
  "dependencies": {
3425
  "@anthropic-ai/sdk": "^0.22.0",
3426
  "@langchain/core": ">=0.2.16 <0.3.0",
@@ -3678,14 +4435,6 @@
3678
  "node": ">= 14"
3679
  }
3680
  },
3681
- "node_modules/@mswjs/cookies": {
3682
- "version": "1.1.1",
3683
- "resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-1.1.1.tgz",
3684
- "integrity": "sha512-W68qOHEjx1iD+4VjQudlx26CPIoxmIAtK4ZCexU0/UJBG6jYhcuyzKJx+Iw8uhBIGd9eba64XgWVgo20it1qwA==",
3685
- "engines": {
3686
- "node": ">=18"
3687
- }
3688
- },
3689
  "node_modules/@mswjs/interceptors": {
3690
  "version": "0.29.1",
3691
  "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.29.1.tgz",
@@ -4173,12 +4922,12 @@
4173
  }
4174
  },
4175
  "node_modules/@playwright/test": {
4176
- "version": "1.45.2",
4177
- "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.2.tgz",
4178
- "integrity": "sha512-JxG9eq92ET75EbVi3s+4sYbcG7q72ECeZNbdBlaMkGcNbiDQ4cAi8U2QP5oKkOx+1gpaiL1LDStmzCaEM1Z6fQ==",
4179
  "devOptional": true,
4180
  "dependencies": {
4181
- "playwright": "1.45.2"
4182
  },
4183
  "bin": {
4184
  "playwright": "cli.js"
@@ -5395,9 +6144,9 @@
5395
  "integrity": "sha512-iQVztO09ZVfsletMiY+DpT/JRiBntdsdJ4uqk3UJFhrhS8mIC9ZOZbmfGSRs/kdbNPQkVyzucceDicQ/3Mlj9g=="
5396
  },
5397
  "node_modules/@react-three/drei": {
5398
- "version": "9.109.0",
5399
- "resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-9.109.0.tgz",
5400
- "integrity": "sha512-LlJ1k0DO5UvBdjuv6WuSP5jXb1mXsQY3VeQTfzivCsHJH9pUsbxutLL7mk84w9MI7cZytv2Qcx2nU2HBm0eNpQ==",
5401
  "dependencies": {
5402
  "@babel/runtime": "^7.11.2",
5403
  "@mediapipe/tasks-vision": "0.10.8",
@@ -5749,6 +6498,32 @@
5749
  "url": "https://github.com/chalk/strip-ansi?sponsor=1"
5750
  }
5751
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5752
  "node_modules/@rollup/rollup-darwin-arm64": {
5753
  "version": "4.19.0",
5754
  "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.0.tgz",
@@ -5762,6 +6537,175 @@
5762
  "darwin"
5763
  ]
5764
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5765
  "node_modules/@rushstack/eslint-patch": {
5766
  "version": "1.10.3",
5767
  "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz",
@@ -6620,9 +7564,9 @@
6620
  }
6621
  },
6622
  "node_modules/@types/node": {
6623
- "version": "20.14.11",
6624
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz",
6625
- "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==",
6626
  "dependencies": {
6627
  "undici-types": "~5.26.4"
6628
  }
@@ -6709,6 +7653,11 @@
6709
  "meshoptimizer": "~0.18.1"
6710
  }
6711
  },
 
 
 
 
 
6712
  "node_modules/@types/uuid": {
6713
  "version": "9.0.8",
6714
  "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
@@ -6983,6 +7932,12 @@
6983
  "url": "https://opencollective.com/vitest"
6984
  }
6985
  },
 
 
 
 
 
 
6986
  "node_modules/@xenova/transformers": {
6987
  "version": "3.0.0-alpha.0",
6988
  "resolved": "git+ssh://git@github.com/xenova/transformers.js.git#c6aeb4be1bc1cdfa72e9d050f77b97dc9c8af362",
@@ -7613,6 +8568,14 @@
7613
  "to-data-view": "^1.1.0"
7614
  }
7615
  },
 
 
 
 
 
 
 
 
7616
  "node_modules/base64-js": {
7617
  "version": "1.5.1",
7618
  "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@@ -9934,14 +10897,14 @@
9934
  }
9935
  },
9936
  "node_modules/electron-to-chromium": {
9937
- "version": "1.4.832",
9938
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.832.tgz",
9939
- "integrity": "sha512-cTen3SB0H2SGU7x467NRe1eVcQgcuS6jckKfWJHia2eo0cHIGOqHoAxevIYZD4eRHcWjkvFzo93bi3vJ9W+1lA=="
9940
  },
9941
  "node_modules/electron-winstaller": {
9942
- "version": "5.3.1",
9943
- "resolved": "https://registry.npmjs.org/electron-winstaller/-/electron-winstaller-5.3.1.tgz",
9944
- "integrity": "sha512-oM8BW3a8NEqG0XW+Vx3xywhk0DyDV4T0jT0zZfWt0IczNT3jHAAvQWBorF8osQDplSsCyXXyxrsrQ8cY0Slb/A==",
9945
  "dev": true,
9946
  "hasInstallScript": true,
9947
  "optional": true,
@@ -10087,9 +11050,9 @@
10087
  }
10088
  },
10089
  "node_modules/enhanced-resolve": {
10090
- "version": "5.17.0",
10091
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz",
10092
- "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==",
10093
  "dev": true,
10094
  "dependencies": {
10095
  "graceful-fs": "^4.2.4",
@@ -12087,9 +13050,9 @@
12087
  }
12088
  },
12089
  "node_modules/groq-sdk/node_modules/@types/node": {
12090
- "version": "18.19.41",
12091
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.41.tgz",
12092
- "integrity": "sha512-LX84pRJ+evD2e2nrgYCHObGWkiQJ1mL+meAgbvnwk/US6vmMY7S2ygBTGV2Jw91s9vUsLSXeDEkUHZIJGLrhsg==",
12093
  "dependencies": {
12094
  "undici-types": "~5.26.4"
12095
  }
@@ -14079,15 +15042,15 @@
14079
  "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
14080
  },
14081
  "node_modules/msw": {
14082
- "version": "2.3.2",
14083
- "resolved": "https://registry.npmjs.org/msw/-/msw-2.3.2.tgz",
14084
- "integrity": "sha512-vDn6d6a50vxPE+HnaKQfpmZ4SVXlOjF97yD5FJcUT3v2/uZ65qvTYNL25yOmnrfCNWZ4wtAS7EbtXxygMug2Tw==",
14085
  "hasInstallScript": true,
14086
  "dependencies": {
14087
  "@bundled-es-modules/cookie": "^2.0.0",
14088
  "@bundled-es-modules/statuses": "^1.0.1",
 
14089
  "@inquirer/confirm": "^3.0.0",
14090
- "@mswjs/cookies": "^1.1.0",
14091
  "@mswjs/interceptors": "^0.29.0",
14092
  "@open-draft/until": "^2.1.0",
14093
  "@types/cookie": "^0.6.0",
@@ -14993,9 +15956,9 @@
14993
  }
14994
  },
14995
  "node_modules/openai/node_modules/@types/node": {
14996
- "version": "18.19.41",
14997
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.41.tgz",
14998
- "integrity": "sha512-LX84pRJ+evD2e2nrgYCHObGWkiQJ1mL+meAgbvnwk/US6vmMY7S2ygBTGV2Jw91s9vUsLSXeDEkUHZIJGLrhsg==",
14999
  "dependencies": {
15000
  "undici-types": "~5.26.4"
15001
  }
@@ -15476,12 +16439,12 @@
15476
  "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg=="
15477
  },
15478
  "node_modules/playwright": {
15479
- "version": "1.45.2",
15480
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.2.tgz",
15481
- "integrity": "sha512-ReywF2t/0teRvNBpfIgh5e4wnrI/8Su8ssdo5XsQKpjxJj+jspm00jSoz9BTg91TT0c9HRjXO7LBNVrgYj9X0g==",
15482
  "devOptional": true,
15483
  "dependencies": {
15484
- "playwright-core": "1.45.2"
15485
  },
15486
  "bin": {
15487
  "playwright": "cli.js"
@@ -15494,9 +16457,9 @@
15494
  }
15495
  },
15496
  "node_modules/playwright-core": {
15497
- "version": "1.45.2",
15498
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.2.tgz",
15499
- "integrity": "sha512-ha175tAWb0dTK0X4orvBIqi3jGEt701SMxMhyujxNrgd8K0Uy5wMSwwcQHtyB4om7INUkfndx02XnQ2p6dvLDw==",
15500
  "devOptional": true,
15501
  "bin": {
15502
  "playwright-core": "cli.js"
@@ -15953,8 +16916,7 @@
15953
  "node_modules/psl": {
15954
  "version": "1.9.0",
15955
  "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
15956
- "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==",
15957
- "dev": true
15958
  },
15959
  "node_modules/pump": {
15960
  "version": "3.0.0",
@@ -15970,7 +16932,6 @@
15970
  "version": "2.3.1",
15971
  "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
15972
  "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
15973
- "dev": true,
15974
  "engines": {
15975
  "node": ">=6"
15976
  }
@@ -16016,8 +16977,7 @@
16016
  "node_modules/querystringify": {
16017
  "version": "2.2.0",
16018
  "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
16019
- "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
16020
- "dev": true
16021
  },
16022
  "node_modules/queue-microtask": {
16023
  "version": "1.2.3",
@@ -16618,8 +17578,7 @@
16618
  "node_modules/requires-port": {
16619
  "version": "1.0.0",
16620
  "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
16621
- "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
16622
- "dev": true
16623
  },
16624
  "node_modules/resedit": {
16625
  "version": "2.0.2",
@@ -18232,7 +19191,6 @@
18232
  "version": "4.1.4",
18233
  "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
18234
  "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==",
18235
- "dev": true,
18236
  "dependencies": {
18237
  "psl": "^1.1.33",
18238
  "punycode": "^2.1.1",
@@ -18247,7 +19205,6 @@
18247
  "version": "0.2.0",
18248
  "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
18249
  "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
18250
- "dev": true,
18251
  "engines": {
18252
  "node": ">= 4.0.0"
18253
  }
@@ -18588,9 +19545,9 @@
18588
  }
18589
  },
18590
  "node_modules/typescript": {
18591
- "version": "5.5.3",
18592
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
18593
- "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==",
18594
  "bin": {
18595
  "tsc": "bin/tsc",
18596
  "tsserver": "bin/tsserver"
@@ -18714,7 +19671,6 @@
18714
  "version": "1.5.10",
18715
  "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
18716
  "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
18717
- "dev": true,
18718
  "dependencies": {
18719
  "querystringify": "^2.1.1",
18720
  "requires-port": "^1.0.0"
@@ -19587,9 +20543,9 @@
19587
  "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
19588
  },
19589
  "node_modules/yaml": {
19590
- "version": "2.4.5",
19591
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz",
19592
- "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==",
19593
  "bin": {
19594
  "yaml": "bin.mjs"
19595
  },
 
9
  "version": "0.0.5",
10
  "license": "GPL-3.0-only",
11
  "dependencies": {
12
+ "@aitube/broadway": "0.1.1",
13
+ "@aitube/clap": "0.1.1",
14
+ "@aitube/clapper-services": "0.1.1",
15
+ "@aitube/engine": "0.1.1",
16
+ "@aitube/timeline": "0.1.1",
17
  "@fal-ai/serverless-client": "^0.13.0",
18
  "@ffmpeg/ffmpeg": "^0.12.10",
19
  "@ffmpeg/util": "^0.12.1",
 
58
  "@types/dom-speech-recognition": "^0.0.4",
59
  "@xenova/transformers": "github:xenova/transformers.js#v3",
60
  "autoprefixer": "10.4.19",
61
+ "base64-arraybuffer": "^1.0.2",
62
  "class-variance-authority": "^0.7.0",
63
  "clsx": "^2.1.1",
64
  "cmdk": "^0.2.1",
 
121
  "@types/react-dom": "^18",
122
  "@types/uuid": "^9.0.8",
123
  "@vitejs/plugin-react": "^4.3.1",
124
+ "@webgpu/types": "^0.1.44",
125
  "electron": "^31.2.1",
126
  "eslint": "^8",
127
  "eslint-config-next": "14.2.5",
 
138
  }
139
  },
140
  "node_modules/@aitube/broadway": {
141
+ "version": "0.1.1",
142
+ "resolved": "https://registry.npmjs.org/@aitube/broadway/-/broadway-0.1.1.tgz",
143
+ "integrity": "sha512-OqWyAH48yp3XxmkC6n2r0V0bDGGIC4WD0stzZYrHneMmwI3D1TxSYj7yUCqhmYolwhAvnaYOWl43LhW6/rxrlA==",
144
  "dependencies": {
145
  "@datagica/parse-entities": "^0.3.0",
146
  "@datagica/parse-names": "^0.0.8",
147
  "indexeddb-fs": "^2.1.5"
148
  },
149
  "peerDependencies": {
150
+ "@aitube/clap": "0.1.1",
151
+ "@aitube/colors": "0.1.1"
152
  }
153
  },
154
  "node_modules/@aitube/clap": {
155
+ "version": "0.1.1",
156
+ "resolved": "https://registry.npmjs.org/@aitube/clap/-/clap-0.1.1.tgz",
157
+ "integrity": "sha512-zKo3HQTM2kIlTTsZS7Pj+nYt5hYv0hyTQnd+Zj3C4gsoHEY8ua2JdIQTsBULD8zi3s4tKueEFv03ZwtD8q2Z1w==",
158
  "dependencies": {
159
  "pure-uuid": "^1.8.1"
160
  },
161
  "peerDependencies": {
162
+ "yaml": "^2.5.0"
163
  }
164
  },
165
  "node_modules/@aitube/clapper-services": {
166
+ "version": "0.1.1",
167
+ "resolved": "https://registry.npmjs.org/@aitube/clapper-services/-/clapper-services-0.1.1.tgz",
168
+ "integrity": "sha512-61fEweTndBE5Smf/Z5MZcs1ikXVZXuYD3+vAK4I2nCed5zi1Os7vKkg+M/+2IJVaGKhO45NcAKY18iyOypNzIA==",
169
  "peerDependencies": {
170
+ "@aitube/clap": "0.1.1",
171
+ "@aitube/timeline": "0.1.1",
172
  "@monaco-editor/react": "4.6.0",
173
  "monaco-editor": "0.50.0",
174
  "react": "*",
 
177
  }
178
  },
179
  "node_modules/@aitube/colors": {
180
+ "version": "0.1.1",
181
+ "resolved": "https://registry.npmjs.org/@aitube/colors/-/colors-0.1.1.tgz",
182
+ "integrity": "sha512-nat4dbIzTpv4UmgTLRn9ulRXrazNDh6ClhLkkEV+tNMAlx22T3btMjyKCmhpZVjL/zMpvDE/rf8oJvWiuzOa5g==",
183
  "peer": true,
184
  "peerDependencies": {
185
+ "@aitube/clap": "0.1.1"
186
  }
187
  },
188
  "node_modules/@aitube/engine": {
189
+ "version": "0.1.1",
190
+ "resolved": "https://registry.npmjs.org/@aitube/engine/-/engine-0.1.1.tgz",
191
+ "integrity": "sha512-ZhmNwzuakkHWO/ZhyPXVKLXzZfFsSIvGS5awBjqqb5KKFb8gIWTi3t/wRfCeoQN2Ngdhut4jZWJhBuh5nChnSg==",
192
  "peerDependencies": {
193
+ "@aitube/clap": "0.1.1"
194
  }
195
  },
196
  "node_modules/@aitube/timeline": {
197
+ "version": "0.1.1",
198
+ "resolved": "https://registry.npmjs.org/@aitube/timeline/-/timeline-0.1.1.tgz",
199
+ "integrity": "sha512-cUxgIqkZ1r1M7yaqk+VpJKaeN1gpFxsFMz7REkC5XZlUyt4cHeHSQT/njMFsYp0kOvKAcCUDZpW8oEyiZp45nQ==",
200
  "dependencies": {
201
  "date-fns": "^3.6.0",
202
  "react-virtualized-auto-sizer": "^1.0.24"
203
  },
204
  "peerDependencies": {
205
+ "@aitube/clap": "0.1.1",
206
  "@radix-ui/react-slider": "^1.1.2",
207
  "@react-spring/three": "^9.7.3",
208
  "@react-spring/types": "^9.7.3",
 
211
  "clsx": "^2.1.1",
212
  "react": "*",
213
  "react-dom": "*",
214
+ "tailwind-merge": "^2.4.0",
215
+ "tailwindcss": "^3.4.6",
216
  "three": "^0.164.1",
217
  "zustand": "4.5.2"
218
  }
 
256
  }
257
  },
258
  "node_modules/@anthropic-ai/sdk/node_modules/@types/node": {
259
+ "version": "18.19.42",
260
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.42.tgz",
261
+ "integrity": "sha512-d2ZFc/3lnK2YCYhos8iaNIYu9Vfhr92nHiyJHRltXWjXUBjEE+A4I58Tdbnw4VhggSW+2j5y5gTrLs4biNnubg==",
262
  "dependencies": {
263
  "undici-types": "~5.26.4"
264
  }
 
839
  }
840
  },
841
  "node_modules/@aws-sdk/credential-providers": {
842
+ "version": "3.617.0",
843
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.617.0.tgz",
844
+ "integrity": "sha512-ZXzdnHI7Tfsk7Y2hezlhxFHlG2VM5tTWQPZ0qZ/cYCzZxyZfsmSFr/rMi6wJGB2J6ZDbbAohEoOWrEblHVq7Cw==",
845
  "dependencies": {
846
  "@aws-sdk/client-cognito-identity": "3.616.0",
847
  "@aws-sdk/client-sso": "3.616.0",
 
1620
  "statuses": "^2.0.1"
1621
  }
1622
  },
1623
+ "node_modules/@bundled-es-modules/tough-cookie": {
1624
+ "version": "0.1.6",
1625
+ "resolved": "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz",
1626
+ "integrity": "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==",
1627
+ "dependencies": {
1628
+ "@types/tough-cookie": "^4.0.5",
1629
+ "tough-cookie": "^4.1.4"
1630
+ }
1631
+ },
1632
  "node_modules/@cspotcode/source-map-support": {
1633
  "version": "0.8.1",
1634
  "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
 
2834
  "node": ">=14.14"
2835
  }
2836
  },
2837
+ "node_modules/@emnapi/runtime": {
2838
+ "version": "1.2.0",
2839
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz",
2840
+ "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==",
2841
+ "optional": true,
2842
+ "dependencies": {
2843
+ "tslib": "^2.4.0"
2844
+ }
2845
+ },
2846
  "node_modules/@emotion/is-prop-valid": {
2847
  "version": "1.3.0",
2848
  "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.0.tgz",
 
2866
  "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
2867
  "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
2868
  },
2869
+ "node_modules/@esbuild/aix-ppc64": {
2870
  "version": "0.21.5",
2871
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
2872
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
2873
  "cpu": [
2874
+ "ppc64"
2875
  ],
2876
  "dev": true,
2877
  "optional": true,
2878
  "os": [
2879
+ "aix"
2880
  ],
2881
  "engines": {
2882
  "node": ">=12"
2883
  }
2884
  },
2885
+ "node_modules/@esbuild/android-arm": {
2886
+ "version": "0.21.5",
2887
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
2888
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
2889
+ "cpu": [
2890
+ "arm"
2891
+ ],
2892
  "dev": true,
2893
+ "optional": true,
2894
+ "os": [
2895
+ "android"
2896
+ ],
2897
  "engines": {
2898
+ "node": ">=12"
 
 
 
2899
  }
2900
  },
2901
+ "node_modules/@esbuild/android-arm64": {
2902
+ "version": "0.21.5",
2903
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
2904
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
2905
+ "cpu": [
2906
+ "arm64"
2907
+ ],
2908
  "dev": true,
2909
+ "optional": true,
2910
+ "os": [
2911
+ "android"
2912
+ ],
2913
  "engines": {
2914
+ "node": ">=12"
2915
  }
2916
  },
2917
+ "node_modules/@esbuild/android-x64": {
2918
+ "version": "0.21.5",
2919
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
2920
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
2921
+ "cpu": [
2922
+ "x64"
2923
+ ],
2924
  "dev": true,
2925
+ "optional": true,
2926
+ "os": [
2927
+ "android"
2928
+ ],
 
 
 
 
 
 
 
2929
  "engines": {
2930
+ "node": ">=12"
 
 
 
2931
  }
2932
  },
2933
+ "node_modules/@esbuild/darwin-arm64": {
2934
+ "version": "0.21.5",
2935
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
2936
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
2937
+ "cpu": [
2938
+ "arm64"
2939
+ ],
2940
  "dev": true,
2941
+ "optional": true,
2942
+ "os": [
2943
+ "darwin"
2944
+ ],
2945
  "engines": {
2946
+ "node": ">=12"
 
 
 
2947
  }
2948
  },
2949
+ "node_modules/@esbuild/darwin-x64": {
2950
+ "version": "0.21.5",
2951
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
2952
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
2953
+ "cpu": [
2954
+ "x64"
2955
+ ],
2956
  "dev": true,
2957
+ "optional": true,
2958
+ "os": [
2959
+ "darwin"
2960
+ ],
2961
  "engines": {
2962
+ "node": ">=12"
 
 
 
2963
  }
2964
  },
2965
+ "node_modules/@esbuild/freebsd-arm64": {
2966
+ "version": "0.21.5",
2967
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
2968
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
2969
+ "cpu": [
2970
+ "arm64"
2971
+ ],
2972
  "dev": true,
2973
+ "optional": true,
2974
+ "os": [
2975
+ "freebsd"
2976
+ ],
2977
  "engines": {
2978
+ "node": ">=12"
2979
  }
2980
  },
2981
+ "node_modules/@esbuild/freebsd-x64": {
2982
+ "version": "0.21.5",
2983
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
2984
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
2985
+ "cpu": [
2986
+ "x64"
2987
+ ],
2988
+ "dev": true,
2989
+ "optional": true,
2990
+ "os": [
2991
+ "freebsd"
2992
+ ],
2993
  "engines": {
2994
+ "node": ">=12"
2995
  }
2996
  },
2997
+ "node_modules/@esbuild/linux-arm": {
2998
+ "version": "0.21.5",
2999
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
3000
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
3001
+ "cpu": [
3002
+ "arm"
3003
+ ],
3004
+ "dev": true,
3005
+ "optional": true,
3006
+ "os": [
3007
+ "linux"
3008
+ ],
3009
  "engines": {
3010
+ "node": ">=12"
3011
  }
3012
  },
3013
+ "node_modules/@esbuild/linux-arm64": {
3014
+ "version": "0.21.5",
3015
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
3016
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
3017
+ "cpu": [
3018
+ "arm64"
3019
+ ],
3020
+ "dev": true,
3021
+ "optional": true,
3022
+ "os": [
3023
+ "linux"
3024
+ ],
3025
  "engines": {
3026
+ "node": ">=12"
3027
  }
3028
  },
3029
+ "node_modules/@esbuild/linux-ia32": {
3030
+ "version": "0.21.5",
3031
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
3032
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
3033
+ "cpu": [
3034
+ "ia32"
3035
+ ],
3036
+ "dev": true,
3037
+ "optional": true,
3038
+ "os": [
3039
+ "linux"
3040
+ ],
3041
  "engines": {
3042
+ "node": ">=12"
3043
  }
3044
  },
3045
+ "node_modules/@esbuild/linux-loong64": {
3046
+ "version": "0.21.5",
3047
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
3048
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
3049
+ "cpu": [
3050
+ "loong64"
3051
+ ],
3052
+ "dev": true,
3053
+ "optional": true,
3054
+ "os": [
3055
+ "linux"
3056
+ ],
3057
+ "engines": {
3058
+ "node": ">=12"
3059
  }
3060
  },
3061
+ "node_modules/@esbuild/linux-mips64el": {
3062
+ "version": "0.21.5",
3063
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
3064
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
3065
+ "cpu": [
3066
+ "mips64el"
3067
+ ],
3068
+ "dev": true,
3069
+ "optional": true,
3070
+ "os": [
3071
+ "linux"
3072
+ ],
3073
+ "engines": {
3074
+ "node": ">=12"
3075
  }
3076
  },
3077
+ "node_modules/@esbuild/linux-ppc64": {
3078
+ "version": "0.21.5",
3079
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
3080
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
3081
+ "cpu": [
3082
+ "ppc64"
3083
+ ],
3084
+ "dev": true,
3085
+ "optional": true,
3086
+ "os": [
3087
+ "linux"
3088
+ ],
3089
+ "engines": {
3090
+ "node": ">=12"
3091
  }
3092
  },
3093
+ "node_modules/@esbuild/linux-riscv64": {
3094
+ "version": "0.21.5",
3095
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
3096
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
3097
+ "cpu": [
3098
+ "riscv64"
3099
+ ],
3100
+ "dev": true,
3101
+ "optional": true,
3102
+ "os": [
3103
+ "linux"
3104
+ ],
3105
+ "engines": {
3106
+ "node": ">=12"
3107
+ }
3108
  },
3109
+ "node_modules/@esbuild/linux-s390x": {
3110
+ "version": "0.21.5",
3111
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
3112
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
3113
+ "cpu": [
3114
+ "s390x"
3115
+ ],
3116
+ "dev": true,
3117
+ "optional": true,
3118
+ "os": [
3119
+ "linux"
3120
+ ],
3121
+ "engines": {
3122
+ "node": ">=12"
3123
+ }
3124
  },
3125
+ "node_modules/@esbuild/linux-x64": {
3126
+ "version": "0.21.5",
3127
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
3128
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
3129
+ "cpu": [
3130
+ "x64"
3131
+ ],
3132
+ "dev": true,
3133
+ "optional": true,
3134
+ "os": [
3135
+ "linux"
3136
+ ],
3137
+ "engines": {
3138
+ "node": ">=12"
3139
+ }
3140
+ },
3141
+ "node_modules/@esbuild/netbsd-x64": {
3142
+ "version": "0.21.5",
3143
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
3144
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
3145
+ "cpu": [
3146
+ "x64"
3147
+ ],
3148
+ "dev": true,
3149
+ "optional": true,
3150
+ "os": [
3151
+ "netbsd"
3152
+ ],
3153
+ "engines": {
3154
+ "node": ">=12"
3155
+ }
3156
+ },
3157
+ "node_modules/@esbuild/openbsd-x64": {
3158
+ "version": "0.21.5",
3159
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
3160
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
3161
+ "cpu": [
3162
+ "x64"
3163
+ ],
3164
+ "dev": true,
3165
+ "optional": true,
3166
+ "os": [
3167
+ "openbsd"
3168
+ ],
3169
+ "engines": {
3170
+ "node": ">=12"
3171
+ }
3172
+ },
3173
+ "node_modules/@esbuild/sunos-x64": {
3174
+ "version": "0.21.5",
3175
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
3176
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
3177
+ "cpu": [
3178
+ "x64"
3179
+ ],
3180
+ "dev": true,
3181
+ "optional": true,
3182
+ "os": [
3183
+ "sunos"
3184
+ ],
3185
+ "engines": {
3186
+ "node": ">=12"
3187
+ }
3188
+ },
3189
+ "node_modules/@esbuild/win32-arm64": {
3190
+ "version": "0.21.5",
3191
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
3192
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
3193
+ "cpu": [
3194
+ "arm64"
3195
+ ],
3196
+ "dev": true,
3197
+ "optional": true,
3198
+ "os": [
3199
+ "win32"
3200
+ ],
3201
+ "engines": {
3202
+ "node": ">=12"
3203
+ }
3204
+ },
3205
+ "node_modules/@esbuild/win32-ia32": {
3206
+ "version": "0.21.5",
3207
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
3208
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
3209
+ "cpu": [
3210
+ "ia32"
3211
+ ],
3212
+ "dev": true,
3213
+ "optional": true,
3214
+ "os": [
3215
+ "win32"
3216
+ ],
3217
+ "engines": {
3218
+ "node": ">=12"
3219
+ }
3220
+ },
3221
+ "node_modules/@esbuild/win32-x64": {
3222
+ "version": "0.21.5",
3223
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
3224
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
3225
+ "cpu": [
3226
+ "x64"
3227
+ ],
3228
+ "dev": true,
3229
+ "optional": true,
3230
+ "os": [
3231
+ "win32"
3232
+ ],
3233
+ "engines": {
3234
+ "node": ">=12"
3235
+ }
3236
+ },
3237
+ "node_modules/@eslint-community/eslint-utils": {
3238
+ "version": "4.4.0",
3239
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
3240
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
3241
+ "dev": true,
3242
  "dependencies": {
3243
+ "eslint-visitor-keys": "^3.3.0"
 
 
 
 
 
 
 
 
3244
  },
3245
  "engines": {
3246
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
3247
+ },
3248
+ "peerDependencies": {
3249
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
3250
  }
3251
  },
3252
+ "node_modules/@eslint-community/regexpp": {
3253
+ "version": "4.11.0",
3254
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz",
3255
+ "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==",
3256
+ "dev": true,
3257
+ "engines": {
3258
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
3259
+ }
3260
+ },
3261
+ "node_modules/@eslint/eslintrc": {
3262
+ "version": "2.1.4",
3263
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
3264
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
3265
+ "dev": true,
3266
  "dependencies": {
3267
+ "ajv": "^6.12.4",
3268
+ "debug": "^4.3.2",
3269
+ "espree": "^9.6.0",
3270
+ "globals": "^13.19.0",
3271
+ "ignore": "^5.2.0",
3272
+ "import-fresh": "^3.2.1",
3273
+ "js-yaml": "^4.1.0",
3274
+ "minimatch": "^3.1.2",
3275
+ "strip-json-comments": "^3.1.1"
3276
  },
3277
  "engines": {
3278
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
3279
+ },
3280
+ "funding": {
3281
+ "url": "https://opencollective.com/eslint"
3282
  }
3283
  },
3284
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
3285
+ "version": "13.24.0",
3286
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
3287
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
3288
+ "dev": true,
3289
  "dependencies": {
3290
+ "type-fest": "^0.20.2"
3291
  },
3292
  "engines": {
3293
+ "node": ">=8"
3294
+ },
3295
+ "funding": {
3296
+ "url": "https://github.com/sponsors/sindresorhus"
3297
  }
3298
  },
3299
+ "node_modules/@eslint/eslintrc/node_modules/type-fest": {
3300
+ "version": "0.20.2",
3301
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
3302
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
3303
+ "dev": true,
3304
+ "engines": {
3305
+ "node": ">=10"
3306
+ },
3307
+ "funding": {
3308
+ "url": "https://github.com/sponsors/sindresorhus"
3309
+ }
3310
+ },
3311
+ "node_modules/@eslint/js": {
3312
+ "version": "8.57.0",
3313
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
3314
+ "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
3315
+ "dev": true,
3316
+ "engines": {
3317
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
3318
+ }
3319
+ },
3320
+ "node_modules/@fal-ai/serverless-client": {
3321
+ "version": "0.13.0",
3322
+ "resolved": "https://registry.npmjs.org/@fal-ai/serverless-client/-/serverless-client-0.13.0.tgz",
3323
+ "integrity": "sha512-Nkb/5YXJIPQHzM79+fRb1LZ1zQLSSvNhDVL2l62sN6/H4XqAWueIOqAAvPF8ds39uSGn8nF1WQV1mt7raVMlWw==",
3324
+ "dependencies": {
3325
+ "@msgpack/msgpack": "^3.0.0-beta2",
3326
+ "eventsource-parser": "^1.1.2",
3327
+ "robot3": "^0.4.1",
3328
+ "uuid-random": "^1.3.2"
3329
+ },
3330
+ "engines": {
3331
+ "node": ">=18.0.0"
3332
+ }
3333
+ },
3334
+ "node_modules/@ffmpeg/ffmpeg": {
3335
+ "version": "0.12.10",
3336
+ "resolved": "https://registry.npmjs.org/@ffmpeg/ffmpeg/-/ffmpeg-0.12.10.tgz",
3337
+ "integrity": "sha512-lVtk8PW8e+NUzGZhPTWj2P1J4/NyuCrbDD3O9IGpSeLYtUZKBqZO8CNj1WYGghep/MXoM8e1qVY1GztTkf8YYQ==",
3338
+ "dependencies": {
3339
+ "@ffmpeg/types": "^0.12.2"
3340
+ },
3341
+ "engines": {
3342
+ "node": ">=18.x"
3343
+ }
3344
+ },
3345
+ "node_modules/@ffmpeg/types": {
3346
+ "version": "0.12.2",
3347
+ "resolved": "https://registry.npmjs.org/@ffmpeg/types/-/types-0.12.2.tgz",
3348
+ "integrity": "sha512-NJtxwPoLb60/z1Klv0ueshguWQ/7mNm106qdHkB4HL49LXszjhjCCiL+ldHJGQ9ai2Igx0s4F24ghigy//ERdA==",
3349
+ "engines": {
3350
+ "node": ">=16.x"
3351
+ }
3352
+ },
3353
+ "node_modules/@ffmpeg/util": {
3354
+ "version": "0.12.1",
3355
+ "resolved": "https://registry.npmjs.org/@ffmpeg/util/-/util-0.12.1.tgz",
3356
+ "integrity": "sha512-10jjfAKWaDyb8+nAkijcsi9wgz/y26LOc1NKJradNMyCIl6usQcBbhkjX5qhALrSBcOy6TOeksunTYa+a03qNQ==",
3357
+ "engines": {
3358
+ "node": ">=18.x"
3359
+ }
3360
+ },
3361
+ "node_modules/@floating-ui/core": {
3362
+ "version": "1.6.5",
3363
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.5.tgz",
3364
+ "integrity": "sha512-8GrTWmoFhm5BsMZOTHeGD2/0FLKLQQHvO/ZmQga4tKempYRLz8aqJGqXVuQgisnMObq2YZ2SgkwctN1LOOxcqA==",
3365
+ "dependencies": {
3366
+ "@floating-ui/utils": "^0.2.5"
3367
+ }
3368
+ },
3369
+ "node_modules/@floating-ui/dom": {
3370
+ "version": "1.6.8",
3371
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.8.tgz",
3372
+ "integrity": "sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q==",
3373
+ "dependencies": {
3374
+ "@floating-ui/core": "^1.6.0",
3375
+ "@floating-ui/utils": "^0.2.5"
3376
+ }
3377
+ },
3378
+ "node_modules/@floating-ui/react-dom": {
3379
+ "version": "2.1.1",
3380
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz",
3381
+ "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==",
3382
+ "dependencies": {
3383
+ "@floating-ui/dom": "^1.0.0"
3384
+ },
3385
+ "peerDependencies": {
3386
+ "react": ">=16.8.0",
3387
+ "react-dom": ">=16.8.0"
3388
+ }
3389
+ },
3390
+ "node_modules/@floating-ui/utils": {
3391
+ "version": "0.2.5",
3392
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.5.tgz",
3393
+ "integrity": "sha512-sTcG+QZ6fdEUObICavU+aB3Mp8HY4n14wYHdxK4fXjPmv3PXZZeY5RaguJmGyeH/CJQhX3fqKUtS4qc1LoHwhQ=="
3394
+ },
3395
+ "node_modules/@gar/promisify": {
3396
+ "version": "1.1.3",
3397
+ "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
3398
+ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
3399
+ "dev": true
3400
+ },
3401
+ "node_modules/@gradio/client": {
3402
+ "version": "1.4.0",
3403
+ "resolved": "https://registry.npmjs.org/@gradio/client/-/client-1.4.0.tgz",
3404
+ "integrity": "sha512-4QrJrUz0j75/2SpiHfhQmKmEuFcTbbuA8hpPFb+G0fvT1kd9fRPf1LhrwvsxFQaP3byZs+IeiV0dzCLveHgtfA==",
3405
+ "dependencies": {
3406
+ "@types/eventsource": "^1.1.15",
3407
+ "bufferutil": "^4.0.7",
3408
+ "eventsource": "^2.0.2",
3409
+ "fetch-event-stream": "^0.1.5",
3410
+ "msw": "^2.2.1",
3411
+ "semiver": "^1.1.0",
3412
+ "textlinestream": "^1.1.1",
3413
+ "typescript": "^5.0.0",
3414
+ "ws": "^8.13.0"
3415
+ },
3416
+ "engines": {
3417
+ "node": ">=18.0.0"
3418
+ }
3419
+ },
3420
+ "node_modules/@huggingface/hub": {
3421
+ "version": "0.15.1",
3422
+ "resolved": "https://registry.npmjs.org/@huggingface/hub/-/hub-0.15.1.tgz",
3423
+ "integrity": "sha512-uHb4aFkJDoGfLeRHfFTjkI36Z8IV6Z1c+KzhMDqUSC56opyr7Mn1Nsx7Rri/C7KDwROhQfBp/fOOqqjTzn6Cgg==",
3424
+ "dependencies": {
3425
+ "@huggingface/tasks": "^0.10.6",
3426
+ "hash-wasm": "^4.9.0"
3427
+ },
3428
+ "engines": {
3429
+ "node": ">=18"
3430
+ }
3431
+ },
3432
+ "node_modules/@huggingface/inference": {
3433
+ "version": "2.8.0",
3434
+ "resolved": "https://registry.npmjs.org/@huggingface/inference/-/inference-2.8.0.tgz",
3435
+ "integrity": "sha512-Ti681P1qckcCAqgzmL53jBnluPuZGelmMIuXNjgAwC5+RIjF4S0SDQu6oy44ZTwekwNp2ETaZ2sXsOk+45aC4w==",
3436
+ "dependencies": {
3437
+ "@huggingface/tasks": "^0.11.2"
3438
+ },
3439
+ "engines": {
3440
+ "node": ">=18"
3441
+ }
3442
+ },
3443
+ "node_modules/@huggingface/inference/node_modules/@huggingface/tasks": {
3444
+ "version": "0.11.3",
3445
+ "resolved": "https://registry.npmjs.org/@huggingface/tasks/-/tasks-0.11.3.tgz",
3446
+ "integrity": "sha512-IYq4OdlySdscjkFwm6iIqP1ZgKl4OGhvQFJWI7Yxpq2V8RmXcgIjiqk/65S6Ap7i+eyCdlOC4qweVy/ICNE0JA=="
3447
+ },
3448
+ "node_modules/@huggingface/jinja": {
3449
+ "version": "0.2.2",
3450
+ "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.2.2.tgz",
3451
+ "integrity": "sha512-/KPde26khDUIPkTGU82jdtTW9UAuvUTumCAbFs/7giR0SxsvZC4hru51PBvpijH6BVkHcROcvZM/lpy5h1jRRA==",
3452
+ "engines": {
3453
+ "node": ">=18"
3454
+ }
3455
+ },
3456
+ "node_modules/@huggingface/tasks": {
3457
+ "version": "0.10.22",
3458
+ "resolved": "https://registry.npmjs.org/@huggingface/tasks/-/tasks-0.10.22.tgz",
3459
+ "integrity": "sha512-sCtp+A6sq6NXoUU7NXuXWoVNNjKddk1GTQIh3cJ6illF8S4zmFoerCVRvFf19BdgICGvF+RVZiv9sGGK9KRDTg=="
3460
+ },
3461
+ "node_modules/@humanwhocodes/config-array": {
3462
+ "version": "0.11.14",
3463
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
3464
+ "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
3465
+ "deprecated": "Use @eslint/config-array instead",
3466
+ "dev": true,
3467
+ "dependencies": {
3468
+ "@humanwhocodes/object-schema": "^2.0.2",
3469
+ "debug": "^4.3.1",
3470
+ "minimatch": "^3.0.5"
3471
+ },
3472
+ "engines": {
3473
+ "node": ">=10.10.0"
3474
+ }
3475
+ },
3476
+ "node_modules/@humanwhocodes/module-importer": {
3477
+ "version": "1.0.1",
3478
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
3479
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
3480
+ "dev": true,
3481
+ "engines": {
3482
+ "node": ">=12.22"
3483
+ },
3484
+ "funding": {
3485
+ "type": "github",
3486
+ "url": "https://github.com/sponsors/nzakas"
3487
+ }
3488
+ },
3489
+ "node_modules/@humanwhocodes/object-schema": {
3490
+ "version": "2.0.3",
3491
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
3492
+ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
3493
+ "deprecated": "Use @eslint/object-schema instead",
3494
+ "dev": true
3495
+ },
3496
+ "node_modules/@img/sharp-darwin-arm64": {
3497
+ "version": "0.33.4",
3498
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.4.tgz",
3499
+ "integrity": "sha512-p0suNqXufJs9t3RqLBO6vvrgr5OhgbWp76s5gTRvdmxmuv9E1rcaqGUsl3l4mKVmXPkTkTErXediAui4x+8PSA==",
3500
+ "cpu": [
3501
+ "arm64"
3502
+ ],
3503
+ "optional": true,
3504
+ "os": [
3505
+ "darwin"
3506
+ ],
3507
+ "engines": {
3508
+ "glibc": ">=2.26",
3509
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
3510
+ "npm": ">=9.6.5",
3511
+ "pnpm": ">=7.1.0",
3512
+ "yarn": ">=3.2.0"
3513
+ },
3514
+ "funding": {
3515
+ "url": "https://opencollective.com/libvips"
3516
+ },
3517
+ "optionalDependencies": {
3518
+ "@img/sharp-libvips-darwin-arm64": "1.0.2"
3519
+ }
3520
+ },
3521
+ "node_modules/@img/sharp-darwin-x64": {
3522
+ "version": "0.33.4",
3523
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.4.tgz",
3524
+ "integrity": "sha512-0l7yRObwtTi82Z6ebVI2PnHT8EB2NxBgpK2MiKJZJ7cz32R4lxd001ecMhzzsZig3Yv9oclvqqdV93jo9hy+Dw==",
3525
+ "cpu": [
3526
+ "x64"
3527
+ ],
3528
+ "optional": true,
3529
+ "os": [
3530
+ "darwin"
3531
+ ],
3532
+ "engines": {
3533
+ "glibc": ">=2.26",
3534
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
3535
+ "npm": ">=9.6.5",
3536
+ "pnpm": ">=7.1.0",
3537
+ "yarn": ">=3.2.0"
3538
+ },
3539
+ "funding": {
3540
+ "url": "https://opencollective.com/libvips"
3541
+ },
3542
+ "optionalDependencies": {
3543
+ "@img/sharp-libvips-darwin-x64": "1.0.2"
3544
+ }
3545
+ },
3546
+ "node_modules/@img/sharp-libvips-darwin-arm64": {
3547
+ "version": "1.0.2",
3548
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.2.tgz",
3549
+ "integrity": "sha512-tcK/41Rq8IKlSaKRCCAuuY3lDJjQnYIW1UXU1kxcEKrfL8WR7N6+rzNoOxoQRJWTAECuKwgAHnPvqXGN8XfkHA==",
3550
+ "cpu": [
3551
+ "arm64"
3552
+ ],
3553
+ "optional": true,
3554
+ "os": [
3555
+ "darwin"
3556
+ ],
3557
+ "engines": {
3558
+ "macos": ">=11",
3559
+ "npm": ">=9.6.5",
3560
+ "pnpm": ">=7.1.0",
3561
+ "yarn": ">=3.2.0"
3562
+ },
3563
+ "funding": {
3564
+ "url": "https://opencollective.com/libvips"
3565
+ }
3566
+ },
3567
+ "node_modules/@img/sharp-libvips-darwin-x64": {
3568
+ "version": "1.0.2",
3569
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.2.tgz",
3570
+ "integrity": "sha512-Ofw+7oaWa0HiiMiKWqqaZbaYV3/UGL2wAPeLuJTx+9cXpCRdvQhCLG0IH8YGwM0yGWGLpsF4Su9vM1o6aer+Fw==",
3571
+ "cpu": [
3572
+ "x64"
3573
+ ],
3574
+ "optional": true,
3575
+ "os": [
3576
+ "darwin"
3577
+ ],
3578
+ "engines": {
3579
+ "macos": ">=10.13",
3580
+ "npm": ">=9.6.5",
3581
+ "pnpm": ">=7.1.0",
3582
+ "yarn": ">=3.2.0"
3583
+ },
3584
+ "funding": {
3585
+ "url": "https://opencollective.com/libvips"
3586
+ }
3587
+ },
3588
+ "node_modules/@img/sharp-libvips-linux-arm": {
3589
+ "version": "1.0.2",
3590
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.2.tgz",
3591
+ "integrity": "sha512-iLWCvrKgeFoglQxdEwzu1eQV04o8YeYGFXtfWU26Zr2wWT3q3MTzC+QTCO3ZQfWd3doKHT4Pm2kRmLbupT+sZw==",
3592
+ "cpu": [
3593
+ "arm"
3594
+ ],
3595
+ "optional": true,
3596
+ "os": [
3597
+ "linux"
3598
+ ],
3599
+ "engines": {
3600
+ "glibc": ">=2.28",
3601
+ "npm": ">=9.6.5",
3602
+ "pnpm": ">=7.1.0",
3603
+ "yarn": ">=3.2.0"
3604
+ },
3605
+ "funding": {
3606
+ "url": "https://opencollective.com/libvips"
3607
+ }
3608
+ },
3609
+ "node_modules/@img/sharp-libvips-linux-arm64": {
3610
+ "version": "1.0.2",
3611
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.2.tgz",
3612
+ "integrity": "sha512-x7kCt3N00ofFmmkkdshwj3vGPCnmiDh7Gwnd4nUwZln2YjqPxV1NlTyZOvoDWdKQVDL911487HOueBvrpflagw==",
3613
+ "cpu": [
3614
+ "arm64"
3615
+ ],
3616
+ "optional": true,
3617
+ "os": [
3618
+ "linux"
3619
+ ],
3620
+ "engines": {
3621
+ "glibc": ">=2.26",
3622
+ "npm": ">=9.6.5",
3623
+ "pnpm": ">=7.1.0",
3624
+ "yarn": ">=3.2.0"
3625
+ },
3626
+ "funding": {
3627
+ "url": "https://opencollective.com/libvips"
3628
+ }
3629
+ },
3630
+ "node_modules/@img/sharp-libvips-linux-s390x": {
3631
+ "version": "1.0.2",
3632
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.2.tgz",
3633
+ "integrity": "sha512-cmhQ1J4qVhfmS6szYW7RT+gLJq9dH2i4maq+qyXayUSn9/3iY2ZeWpbAgSpSVbV2E1JUL2Gg7pwnYQ1h8rQIog==",
3634
+ "cpu": [
3635
+ "s390x"
3636
+ ],
3637
+ "optional": true,
3638
+ "os": [
3639
+ "linux"
3640
+ ],
3641
+ "engines": {
3642
+ "glibc": ">=2.28",
3643
+ "npm": ">=9.6.5",
3644
+ "pnpm": ">=7.1.0",
3645
+ "yarn": ">=3.2.0"
3646
+ },
3647
+ "funding": {
3648
+ "url": "https://opencollective.com/libvips"
3649
+ }
3650
+ },
3651
+ "node_modules/@img/sharp-libvips-linux-x64": {
3652
+ "version": "1.0.2",
3653
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.2.tgz",
3654
+ "integrity": "sha512-E441q4Qdb+7yuyiADVi5J+44x8ctlrqn8XgkDTwr4qPJzWkaHwD489iZ4nGDgcuya4iMN3ULV6NwbhRZJ9Z7SQ==",
3655
+ "cpu": [
3656
+ "x64"
3657
+ ],
3658
+ "optional": true,
3659
+ "os": [
3660
+ "linux"
3661
+ ],
3662
+ "engines": {
3663
+ "glibc": ">=2.26",
3664
+ "npm": ">=9.6.5",
3665
+ "pnpm": ">=7.1.0",
3666
+ "yarn": ">=3.2.0"
3667
+ },
3668
+ "funding": {
3669
+ "url": "https://opencollective.com/libvips"
3670
+ }
3671
+ },
3672
+ "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
3673
+ "version": "1.0.2",
3674
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.2.tgz",
3675
+ "integrity": "sha512-3CAkndNpYUrlDqkCM5qhksfE+qSIREVpyoeHIU6jd48SJZViAmznoQQLAv4hVXF7xyUB9zf+G++e2v1ABjCbEQ==",
3676
+ "cpu": [
3677
+ "arm64"
3678
+ ],
3679
+ "optional": true,
3680
+ "os": [
3681
+ "linux"
3682
+ ],
3683
+ "engines": {
3684
+ "musl": ">=1.2.2",
3685
+ "npm": ">=9.6.5",
3686
+ "pnpm": ">=7.1.0",
3687
+ "yarn": ">=3.2.0"
3688
+ },
3689
+ "funding": {
3690
+ "url": "https://opencollective.com/libvips"
3691
+ }
3692
+ },
3693
+ "node_modules/@img/sharp-libvips-linuxmusl-x64": {
3694
+ "version": "1.0.2",
3695
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.2.tgz",
3696
+ "integrity": "sha512-VI94Q6khIHqHWNOh6LLdm9s2Ry4zdjWJwH56WoiJU7NTeDwyApdZZ8c+SADC8OH98KWNQXnE01UdJ9CSfZvwZw==",
3697
+ "cpu": [
3698
+ "x64"
3699
+ ],
3700
+ "optional": true,
3701
+ "os": [
3702
+ "linux"
3703
+ ],
3704
+ "engines": {
3705
+ "musl": ">=1.2.2",
3706
+ "npm": ">=9.6.5",
3707
+ "pnpm": ">=7.1.0",
3708
+ "yarn": ">=3.2.0"
3709
+ },
3710
+ "funding": {
3711
+ "url": "https://opencollective.com/libvips"
3712
+ }
3713
+ },
3714
+ "node_modules/@img/sharp-linux-arm": {
3715
+ "version": "0.33.4",
3716
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.4.tgz",
3717
+ "integrity": "sha512-RUgBD1c0+gCYZGCCe6mMdTiOFS0Zc/XrN0fYd6hISIKcDUbAW5NtSQW9g/powkrXYm6Vzwd6y+fqmExDuCdHNQ==",
3718
+ "cpu": [
3719
+ "arm"
3720
+ ],
3721
+ "optional": true,
3722
+ "os": [
3723
+ "linux"
3724
+ ],
3725
+ "engines": {
3726
+ "glibc": ">=2.28",
3727
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
3728
+ "npm": ">=9.6.5",
3729
+ "pnpm": ">=7.1.0",
3730
+ "yarn": ">=3.2.0"
3731
+ },
3732
+ "funding": {
3733
+ "url": "https://opencollective.com/libvips"
3734
+ },
3735
+ "optionalDependencies": {
3736
+ "@img/sharp-libvips-linux-arm": "1.0.2"
3737
+ }
3738
+ },
3739
+ "node_modules/@img/sharp-linux-arm64": {
3740
+ "version": "0.33.4",
3741
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.4.tgz",
3742
+ "integrity": "sha512-2800clwVg1ZQtxwSoTlHvtm9ObgAax7V6MTAB/hDT945Tfyy3hVkmiHpeLPCKYqYR1Gcmv1uDZ3a4OFwkdBL7Q==",
3743
+ "cpu": [
3744
+ "arm64"
3745
+ ],
3746
+ "optional": true,
3747
+ "os": [
3748
+ "linux"
3749
+ ],
3750
+ "engines": {
3751
+ "glibc": ">=2.26",
3752
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
3753
+ "npm": ">=9.6.5",
3754
+ "pnpm": ">=7.1.0",
3755
+ "yarn": ">=3.2.0"
3756
+ },
3757
+ "funding": {
3758
+ "url": "https://opencollective.com/libvips"
3759
+ },
3760
+ "optionalDependencies": {
3761
+ "@img/sharp-libvips-linux-arm64": "1.0.2"
3762
+ }
3763
+ },
3764
+ "node_modules/@img/sharp-linux-s390x": {
3765
+ "version": "0.33.4",
3766
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.4.tgz",
3767
+ "integrity": "sha512-h3RAL3siQoyzSoH36tUeS0PDmb5wINKGYzcLB5C6DIiAn2F3udeFAum+gj8IbA/82+8RGCTn7XW8WTFnqag4tQ==",
3768
+ "cpu": [
3769
+ "s390x"
3770
+ ],
3771
+ "optional": true,
3772
+ "os": [
3773
+ "linux"
3774
+ ],
3775
+ "engines": {
3776
+ "glibc": ">=2.31",
3777
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
3778
+ "npm": ">=9.6.5",
3779
+ "pnpm": ">=7.1.0",
3780
+ "yarn": ">=3.2.0"
3781
+ },
3782
+ "funding": {
3783
+ "url": "https://opencollective.com/libvips"
3784
+ },
3785
+ "optionalDependencies": {
3786
+ "@img/sharp-libvips-linux-s390x": "1.0.2"
3787
+ }
3788
+ },
3789
+ "node_modules/@img/sharp-linux-x64": {
3790
+ "version": "0.33.4",
3791
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.4.tgz",
3792
+ "integrity": "sha512-GoR++s0XW9DGVi8SUGQ/U4AeIzLdNjHka6jidVwapQ/JebGVQIpi52OdyxCNVRE++n1FCLzjDovJNozif7w/Aw==",
3793
+ "cpu": [
3794
+ "x64"
3795
+ ],
3796
+ "optional": true,
3797
+ "os": [
3798
+ "linux"
3799
+ ],
3800
+ "engines": {
3801
+ "glibc": ">=2.26",
3802
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
3803
+ "npm": ">=9.6.5",
3804
+ "pnpm": ">=7.1.0",
3805
+ "yarn": ">=3.2.0"
3806
+ },
3807
+ "funding": {
3808
+ "url": "https://opencollective.com/libvips"
3809
+ },
3810
+ "optionalDependencies": {
3811
+ "@img/sharp-libvips-linux-x64": "1.0.2"
3812
+ }
3813
+ },
3814
+ "node_modules/@img/sharp-linuxmusl-arm64": {
3815
+ "version": "0.33.4",
3816
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.4.tgz",
3817
+ "integrity": "sha512-nhr1yC3BlVrKDTl6cO12gTpXMl4ITBUZieehFvMntlCXFzH2bvKG76tBL2Y/OqhupZt81pR7R+Q5YhJxW0rGgQ==",
3818
+ "cpu": [
3819
+ "arm64"
3820
+ ],
3821
+ "optional": true,
3822
+ "os": [
3823
+ "linux"
3824
+ ],
3825
+ "engines": {
3826
+ "musl": ">=1.2.2",
3827
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
3828
+ "npm": ">=9.6.5",
3829
+ "pnpm": ">=7.1.0",
3830
+ "yarn": ">=3.2.0"
3831
+ },
3832
+ "funding": {
3833
+ "url": "https://opencollective.com/libvips"
3834
+ },
3835
+ "optionalDependencies": {
3836
+ "@img/sharp-libvips-linuxmusl-arm64": "1.0.2"
3837
+ }
3838
  },
3839
+ "node_modules/@img/sharp-linuxmusl-x64": {
3840
+ "version": "0.33.4",
3841
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.4.tgz",
3842
+ "integrity": "sha512-uCPTku0zwqDmZEOi4ILyGdmW76tH7dm8kKlOIV1XC5cLyJ71ENAAqarOHQh0RLfpIpbV5KOpXzdU6XkJtS0daw==",
3843
+ "cpu": [
3844
+ "x64"
3845
+ ],
3846
+ "optional": true,
3847
+ "os": [
3848
+ "linux"
3849
+ ],
3850
  "engines": {
3851
+ "musl": ">=1.2.2",
3852
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
3853
+ "npm": ">=9.6.5",
3854
+ "pnpm": ">=7.1.0",
3855
+ "yarn": ">=3.2.0"
3856
+ },
3857
+ "funding": {
3858
+ "url": "https://opencollective.com/libvips"
3859
+ },
3860
+ "optionalDependencies": {
3861
+ "@img/sharp-libvips-linuxmusl-x64": "1.0.2"
3862
  }
3863
  },
3864
+ "node_modules/@img/sharp-wasm32": {
3865
+ "version": "0.33.4",
3866
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.4.tgz",
3867
+ "integrity": "sha512-Bmmauh4sXUsUqkleQahpdNXKvo+wa1V9KhT2pDA4VJGKwnKMJXiSTGphn0gnJrlooda0QxCtXc6RX1XAU6hMnQ==",
3868
+ "cpu": [
3869
+ "wasm32"
3870
+ ],
3871
+ "optional": true,
 
 
 
3872
  "dependencies": {
3873
+ "@emnapi/runtime": "^1.1.1"
 
 
3874
  },
3875
  "engines": {
3876
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
3877
+ "npm": ">=9.6.5",
3878
+ "pnpm": ">=7.1.0",
3879
+ "yarn": ">=3.2.0"
 
 
 
 
 
 
3880
  },
3881
  "funding": {
3882
+ "url": "https://opencollective.com/libvips"
 
3883
  }
3884
  },
3885
+ "node_modules/@img/sharp-win32-ia32": {
 
 
 
 
 
 
 
3886
  "version": "0.33.4",
3887
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.4.tgz",
3888
+ "integrity": "sha512-99SJ91XzUhYHbx7uhK3+9Lf7+LjwMGQZMDlO/E/YVJ7Nc3lyDFZPGhjwiYdctoH2BOzW9+TnfqcaMKt0jHLdqw==",
3889
  "cpu": [
3890
+ "ia32"
3891
  ],
3892
  "optional": true,
3893
  "os": [
3894
+ "win32"
3895
  ],
3896
  "engines": {
 
3897
  "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
3898
  "npm": ">=9.6.5",
3899
  "pnpm": ">=7.1.0",
 
3901
  },
3902
  "funding": {
3903
  "url": "https://opencollective.com/libvips"
 
 
 
3904
  }
3905
  },
3906
+ "node_modules/@img/sharp-win32-x64": {
3907
+ "version": "0.33.4",
3908
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.4.tgz",
3909
+ "integrity": "sha512-3QLocdTRVIrFNye5YocZl+KKpYKP+fksi1QhmOArgx7GyhIbQp/WrJRu176jm8IxromS7RIkzMiMINVdBtC8Aw==",
3910
  "cpu": [
3911
+ "x64"
3912
  ],
3913
  "optional": true,
3914
  "os": [
3915
+ "win32"
3916
  ],
3917
  "engines": {
3918
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
3919
  "npm": ">=9.6.5",
3920
  "pnpm": ">=7.1.0",
3921
  "yarn": ">=3.2.0"
 
4175
  }
4176
  },
4177
  "node_modules/@langchain/anthropic": {
4178
+ "version": "0.2.8",
4179
+ "resolved": "https://registry.npmjs.org/@langchain/anthropic/-/anthropic-0.2.8.tgz",
4180
+ "integrity": "sha512-d2aFPdFDFApLmaCzluTH/FvFi+xPhDDRW4gYIjE4DIoTuubAYKZEkvIlrratQuzXzg5LhDPPHBctvR7nst0D6Q==",
4181
  "dependencies": {
4182
  "@anthropic-ai/sdk": "^0.22.0",
4183
  "@langchain/core": ">=0.2.16 <0.3.0",
 
4435
  "node": ">= 14"
4436
  }
4437
  },
 
 
 
 
 
 
 
 
4438
  "node_modules/@mswjs/interceptors": {
4439
  "version": "0.29.1",
4440
  "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.29.1.tgz",
 
4922
  }
4923
  },
4924
  "node_modules/@playwright/test": {
4925
+ "version": "1.45.3",
4926
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.3.tgz",
4927
+ "integrity": "sha512-UKF4XsBfy+u3MFWEH44hva1Q8Da28G6RFtR2+5saw+jgAFQV5yYnB1fu68Mz7fO+5GJF3wgwAIs0UelU8TxFrA==",
4928
  "devOptional": true,
4929
  "dependencies": {
4930
+ "playwright": "1.45.3"
4931
  },
4932
  "bin": {
4933
  "playwright": "cli.js"
 
6144
  "integrity": "sha512-iQVztO09ZVfsletMiY+DpT/JRiBntdsdJ4uqk3UJFhrhS8mIC9ZOZbmfGSRs/kdbNPQkVyzucceDicQ/3Mlj9g=="
6145
  },
6146
  "node_modules/@react-three/drei": {
6147
+ "version": "9.109.2",
6148
+ "resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-9.109.2.tgz",
6149
+ "integrity": "sha512-oUbfjiyPQeQch4Mi3jZvFKigMlc97/xvazxyjPBCGa8RP8cHZJl187eZI9Ha1WwkVaX80DfgN7bYAWXS4ywxmw==",
6150
  "dependencies": {
6151
  "@babel/runtime": "^7.11.2",
6152
  "@mediapipe/tasks-vision": "0.10.8",
 
6498
  "url": "https://github.com/chalk/strip-ansi?sponsor=1"
6499
  }
6500
  },
6501
+ "node_modules/@rollup/rollup-android-arm-eabi": {
6502
+ "version": "4.19.0",
6503
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.0.tgz",
6504
+ "integrity": "sha512-JlPfZ/C7yn5S5p0yKk7uhHTTnFlvTgLetl2VxqE518QgyM7C9bSfFTYvB/Q/ftkq0RIPY4ySxTz+/wKJ/dXC0w==",
6505
+ "cpu": [
6506
+ "arm"
6507
+ ],
6508
+ "dev": true,
6509
+ "optional": true,
6510
+ "os": [
6511
+ "android"
6512
+ ]
6513
+ },
6514
+ "node_modules/@rollup/rollup-android-arm64": {
6515
+ "version": "4.19.0",
6516
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.0.tgz",
6517
+ "integrity": "sha512-RDxUSY8D1tWYfn00DDi5myxKgOk6RvWPxhmWexcICt/MEC6yEMr4HNCu1sXXYLw8iAsg0D44NuU+qNq7zVWCrw==",
6518
+ "cpu": [
6519
+ "arm64"
6520
+ ],
6521
+ "dev": true,
6522
+ "optional": true,
6523
+ "os": [
6524
+ "android"
6525
+ ]
6526
+ },
6527
  "node_modules/@rollup/rollup-darwin-arm64": {
6528
  "version": "4.19.0",
6529
  "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.0.tgz",
 
6537
  "darwin"
6538
  ]
6539
  },
6540
+ "node_modules/@rollup/rollup-darwin-x64": {
6541
+ "version": "4.19.0",
6542
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.0.tgz",
6543
+ "integrity": "sha512-fO28cWA1dC57qCd+D0rfLC4VPbh6EOJXrreBmFLWPGI9dpMlER2YwSPZzSGfq11XgcEpPukPTfEVFtw2q2nYJg==",
6544
+ "cpu": [
6545
+ "x64"
6546
+ ],
6547
+ "dev": true,
6548
+ "optional": true,
6549
+ "os": [
6550
+ "darwin"
6551
+ ]
6552
+ },
6553
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
6554
+ "version": "4.19.0",
6555
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.0.tgz",
6556
+ "integrity": "sha512-2Rn36Ubxdv32NUcfm0wB1tgKqkQuft00PtM23VqLuCUR4N5jcNWDoV5iBC9jeGdgS38WK66ElncprqgMUOyomw==",
6557
+ "cpu": [
6558
+ "arm"
6559
+ ],
6560
+ "dev": true,
6561
+ "optional": true,
6562
+ "os": [
6563
+ "linux"
6564
+ ]
6565
+ },
6566
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
6567
+ "version": "4.19.0",
6568
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.0.tgz",
6569
+ "integrity": "sha512-gJuzIVdq/X1ZA2bHeCGCISe0VWqCoNT8BvkQ+BfsixXwTOndhtLUpOg0A1Fcx/+eA6ei6rMBzlOz4JzmiDw7JQ==",
6570
+ "cpu": [
6571
+ "arm"
6572
+ ],
6573
+ "dev": true,
6574
+ "optional": true,
6575
+ "os": [
6576
+ "linux"
6577
+ ]
6578
+ },
6579
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
6580
+ "version": "4.19.0",
6581
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.0.tgz",
6582
+ "integrity": "sha512-0EkX2HYPkSADo9cfeGFoQ7R0/wTKb7q6DdwI4Yn/ULFE1wuRRCHybxpl2goQrx4c/yzK3I8OlgtBu4xvted0ug==",
6583
+ "cpu": [
6584
+ "arm64"
6585
+ ],
6586
+ "dev": true,
6587
+ "optional": true,
6588
+ "os": [
6589
+ "linux"
6590
+ ]
6591
+ },
6592
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
6593
+ "version": "4.19.0",
6594
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.0.tgz",
6595
+ "integrity": "sha512-GlIQRj9px52ISomIOEUq/IojLZqzkvRpdP3cLgIE1wUWaiU5Takwlzpz002q0Nxxr1y2ZgxC2obWxjr13lvxNQ==",
6596
+ "cpu": [
6597
+ "arm64"
6598
+ ],
6599
+ "dev": true,
6600
+ "optional": true,
6601
+ "os": [
6602
+ "linux"
6603
+ ]
6604
+ },
6605
+ "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
6606
+ "version": "4.19.0",
6607
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.0.tgz",
6608
+ "integrity": "sha512-N6cFJzssruDLUOKfEKeovCKiHcdwVYOT1Hs6dovDQ61+Y9n3Ek4zXvtghPPelt6U0AH4aDGnDLb83uiJMkWYzQ==",
6609
+ "cpu": [
6610
+ "ppc64"
6611
+ ],
6612
+ "dev": true,
6613
+ "optional": true,
6614
+ "os": [
6615
+ "linux"
6616
+ ]
6617
+ },
6618
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
6619
+ "version": "4.19.0",
6620
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.0.tgz",
6621
+ "integrity": "sha512-2DnD3mkS2uuam/alF+I7M84koGwvn3ZVD7uG+LEWpyzo/bq8+kKnus2EVCkcvh6PlNB8QPNFOz6fWd5N8o1CYg==",
6622
+ "cpu": [
6623
+ "riscv64"
6624
+ ],
6625
+ "dev": true,
6626
+ "optional": true,
6627
+ "os": [
6628
+ "linux"
6629
+ ]
6630
+ },
6631
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
6632
+ "version": "4.19.0",
6633
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.0.tgz",
6634
+ "integrity": "sha512-D6pkaF7OpE7lzlTOFCB2m3Ngzu2ykw40Nka9WmKGUOTS3xcIieHe82slQlNq69sVB04ch73thKYIWz/Ian8DUA==",
6635
+ "cpu": [
6636
+ "s390x"
6637
+ ],
6638
+ "dev": true,
6639
+ "optional": true,
6640
+ "os": [
6641
+ "linux"
6642
+ ]
6643
+ },
6644
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
6645
+ "version": "4.19.0",
6646
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.0.tgz",
6647
+ "integrity": "sha512-HBndjQLP8OsdJNSxpNIN0einbDmRFg9+UQeZV1eiYupIRuZsDEoeGU43NQsS34Pp166DtwQOnpcbV/zQxM+rWA==",
6648
+ "cpu": [
6649
+ "x64"
6650
+ ],
6651
+ "dev": true,
6652
+ "optional": true,
6653
+ "os": [
6654
+ "linux"
6655
+ ]
6656
+ },
6657
+ "node_modules/@rollup/rollup-linux-x64-musl": {
6658
+ "version": "4.19.0",
6659
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.0.tgz",
6660
+ "integrity": "sha512-HxfbvfCKJe/RMYJJn0a12eiOI9OOtAUF4G6ozrFUK95BNyoJaSiBjIOHjZskTUffUrB84IPKkFG9H9nEvJGW6A==",
6661
+ "cpu": [
6662
+ "x64"
6663
+ ],
6664
+ "dev": true,
6665
+ "optional": true,
6666
+ "os": [
6667
+ "linux"
6668
+ ]
6669
+ },
6670
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
6671
+ "version": "4.19.0",
6672
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.0.tgz",
6673
+ "integrity": "sha512-HxDMKIhmcguGTiP5TsLNolwBUK3nGGUEoV/BO9ldUBoMLBssvh4J0X8pf11i1fTV7WShWItB1bKAKjX4RQeYmg==",
6674
+ "cpu": [
6675
+ "arm64"
6676
+ ],
6677
+ "dev": true,
6678
+ "optional": true,
6679
+ "os": [
6680
+ "win32"
6681
+ ]
6682
+ },
6683
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
6684
+ "version": "4.19.0",
6685
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.0.tgz",
6686
+ "integrity": "sha512-xItlIAZZaiG/u0wooGzRsx11rokP4qyc/79LkAOdznGRAbOFc+SfEdfUOszG1odsHNgwippUJavag/+W/Etc6Q==",
6687
+ "cpu": [
6688
+ "ia32"
6689
+ ],
6690
+ "dev": true,
6691
+ "optional": true,
6692
+ "os": [
6693
+ "win32"
6694
+ ]
6695
+ },
6696
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
6697
+ "version": "4.19.0",
6698
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.0.tgz",
6699
+ "integrity": "sha512-xNo5fV5ycvCCKqiZcpB65VMR11NJB+StnxHz20jdqRAktfdfzhgjTiJ2doTDQE/7dqGaV5I7ZGqKpgph6lCIag==",
6700
+ "cpu": [
6701
+ "x64"
6702
+ ],
6703
+ "dev": true,
6704
+ "optional": true,
6705
+ "os": [
6706
+ "win32"
6707
+ ]
6708
+ },
6709
  "node_modules/@rushstack/eslint-patch": {
6710
  "version": "1.10.3",
6711
  "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz",
 
7564
  }
7565
  },
7566
  "node_modules/@types/node": {
7567
+ "version": "20.14.12",
7568
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz",
7569
+ "integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==",
7570
  "dependencies": {
7571
  "undici-types": "~5.26.4"
7572
  }
 
7653
  "meshoptimizer": "~0.18.1"
7654
  }
7655
  },
7656
+ "node_modules/@types/tough-cookie": {
7657
+ "version": "4.0.5",
7658
+ "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
7659
+ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA=="
7660
+ },
7661
  "node_modules/@types/uuid": {
7662
  "version": "9.0.8",
7663
  "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
 
7932
  "url": "https://opencollective.com/vitest"
7933
  }
7934
  },
7935
+ "node_modules/@webgpu/types": {
7936
+ "version": "0.1.44",
7937
+ "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.44.tgz",
7938
+ "integrity": "sha512-JDpYJN5E/asw84LTYhKyvPpxGnD+bAKPtpW9Ilurf7cZpxaTbxkQcGwOd7jgB9BPBrTYQ+32ufo4HiuomTjHNQ==",
7939
+ "dev": true
7940
+ },
7941
  "node_modules/@xenova/transformers": {
7942
  "version": "3.0.0-alpha.0",
7943
  "resolved": "git+ssh://git@github.com/xenova/transformers.js.git#c6aeb4be1bc1cdfa72e9d050f77b97dc9c8af362",
 
8568
  "to-data-view": "^1.1.0"
8569
  }
8570
  },
8571
+ "node_modules/base64-arraybuffer": {
8572
+ "version": "1.0.2",
8573
+ "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
8574
+ "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
8575
+ "engines": {
8576
+ "node": ">= 0.6.0"
8577
+ }
8578
+ },
8579
  "node_modules/base64-js": {
8580
  "version": "1.5.1",
8581
  "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
 
10897
  }
10898
  },
10899
  "node_modules/electron-to-chromium": {
10900
+ "version": "1.5.0",
10901
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.0.tgz",
10902
+ "integrity": "sha512-Vb3xHHYnLseK8vlMJQKJYXJ++t4u1/qJ3vykuVrVjvdiOEhYyT1AuP4x03G8EnPmYvYOhe9T+dADTmthjRQMkA=="
10903
  },
10904
  "node_modules/electron-winstaller": {
10905
+ "version": "5.4.0",
10906
+ "resolved": "https://registry.npmjs.org/electron-winstaller/-/electron-winstaller-5.4.0.tgz",
10907
+ "integrity": "sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==",
10908
  "dev": true,
10909
  "hasInstallScript": true,
10910
  "optional": true,
 
11050
  }
11051
  },
11052
  "node_modules/enhanced-resolve": {
11053
+ "version": "5.17.1",
11054
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
11055
+ "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
11056
  "dev": true,
11057
  "dependencies": {
11058
  "graceful-fs": "^4.2.4",
 
13050
  }
13051
  },
13052
  "node_modules/groq-sdk/node_modules/@types/node": {
13053
+ "version": "18.19.42",
13054
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.42.tgz",
13055
+ "integrity": "sha512-d2ZFc/3lnK2YCYhos8iaNIYu9Vfhr92nHiyJHRltXWjXUBjEE+A4I58Tdbnw4VhggSW+2j5y5gTrLs4biNnubg==",
13056
  "dependencies": {
13057
  "undici-types": "~5.26.4"
13058
  }
 
15042
  "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
15043
  },
15044
  "node_modules/msw": {
15045
+ "version": "2.3.4",
15046
+ "resolved": "https://registry.npmjs.org/msw/-/msw-2.3.4.tgz",
15047
+ "integrity": "sha512-sHMlwrajgmZSA2l1o7qRSe+azm/I+x9lvVVcOxAzi4vCtH8uVPJk1K5BQYDkzGl+tt0RvM9huEXXdeGrgcc79g==",
15048
  "hasInstallScript": true,
15049
  "dependencies": {
15050
  "@bundled-es-modules/cookie": "^2.0.0",
15051
  "@bundled-es-modules/statuses": "^1.0.1",
15052
+ "@bundled-es-modules/tough-cookie": "^0.1.6",
15053
  "@inquirer/confirm": "^3.0.0",
 
15054
  "@mswjs/interceptors": "^0.29.0",
15055
  "@open-draft/until": "^2.1.0",
15056
  "@types/cookie": "^0.6.0",
 
15956
  }
15957
  },
15958
  "node_modules/openai/node_modules/@types/node": {
15959
+ "version": "18.19.42",
15960
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.42.tgz",
15961
+ "integrity": "sha512-d2ZFc/3lnK2YCYhos8iaNIYu9Vfhr92nHiyJHRltXWjXUBjEE+A4I58Tdbnw4VhggSW+2j5y5gTrLs4biNnubg==",
15962
  "dependencies": {
15963
  "undici-types": "~5.26.4"
15964
  }
 
16439
  "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg=="
16440
  },
16441
  "node_modules/playwright": {
16442
+ "version": "1.45.3",
16443
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.3.tgz",
16444
+ "integrity": "sha512-QhVaS+lpluxCaioejDZ95l4Y4jSFCsBvl2UZkpeXlzxmqS+aABr5c82YmfMHrL6x27nvrvykJAFpkzT2eWdJww==",
16445
  "devOptional": true,
16446
  "dependencies": {
16447
+ "playwright-core": "1.45.3"
16448
  },
16449
  "bin": {
16450
  "playwright": "cli.js"
 
16457
  }
16458
  },
16459
  "node_modules/playwright-core": {
16460
+ "version": "1.45.3",
16461
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.3.tgz",
16462
+ "integrity": "sha512-+ym0jNbcjikaOwwSZycFbwkWgfruWvYlJfThKYAlImbxUgdWFO2oW70ojPm4OpE4t6TAo2FY/smM+hpVTtkhDA==",
16463
  "devOptional": true,
16464
  "bin": {
16465
  "playwright-core": "cli.js"
 
16916
  "node_modules/psl": {
16917
  "version": "1.9.0",
16918
  "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
16919
+ "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
 
16920
  },
16921
  "node_modules/pump": {
16922
  "version": "3.0.0",
 
16932
  "version": "2.3.1",
16933
  "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
16934
  "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
 
16935
  "engines": {
16936
  "node": ">=6"
16937
  }
 
16977
  "node_modules/querystringify": {
16978
  "version": "2.2.0",
16979
  "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
16980
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
 
16981
  },
16982
  "node_modules/queue-microtask": {
16983
  "version": "1.2.3",
 
17578
  "node_modules/requires-port": {
17579
  "version": "1.0.0",
17580
  "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
17581
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
 
17582
  },
17583
  "node_modules/resedit": {
17584
  "version": "2.0.2",
 
19191
  "version": "4.1.4",
19192
  "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
19193
  "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==",
 
19194
  "dependencies": {
19195
  "psl": "^1.1.33",
19196
  "punycode": "^2.1.1",
 
19205
  "version": "0.2.0",
19206
  "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
19207
  "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
 
19208
  "engines": {
19209
  "node": ">= 4.0.0"
19210
  }
 
19545
  }
19546
  },
19547
  "node_modules/typescript": {
19548
+ "version": "5.5.4",
19549
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz",
19550
+ "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==",
19551
  "bin": {
19552
  "tsc": "bin/tsc",
19553
  "tsserver": "bin/tsserver"
 
19671
  "version": "1.5.10",
19672
  "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
19673
  "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
 
19674
  "dependencies": {
19675
  "querystringify": "^2.1.1",
19676
  "requires-port": "^1.0.0"
 
20543
  "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
20544
  },
20545
  "node_modules/yaml": {
20546
+ "version": "2.5.0",
20547
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz",
20548
+ "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==",
20549
  "bin": {
20550
  "yaml": "bin.mjs"
20551
  },
package.json CHANGED
@@ -25,7 +25,8 @@
25
  "format:fix": "prettier --write --ignore-path .gitignore ./src/",
26
  "lint": "next lint",
27
  "lint:fix": "next lint --fix",
28
- "test": "npm run build && npm run test:unit:ci && npm run test:e2e",
 
29
  "test:unit:ci": "vitest run",
30
  "test:unit:watch": "vitest",
31
  "test:e2e": "npx playwright test",
@@ -35,11 +36,11 @@
35
  "electron:make": "npm run build && electron-forge make"
36
  },
37
  "dependencies": {
38
- "@aitube/broadway": "0.0.22",
39
- "@aitube/clap": "0.0.30",
40
- "@aitube/clapper-services": "0.0.35",
41
- "@aitube/engine": "0.0.26",
42
- "@aitube/timeline": "0.0.45",
43
  "@fal-ai/serverless-client": "^0.13.0",
44
  "@ffmpeg/ffmpeg": "^0.12.10",
45
  "@ffmpeg/util": "^0.12.1",
@@ -84,6 +85,7 @@
84
  "@types/dom-speech-recognition": "^0.0.4",
85
  "@xenova/transformers": "github:xenova/transformers.js#v3",
86
  "autoprefixer": "10.4.19",
 
87
  "class-variance-authority": "^0.7.0",
88
  "clsx": "^2.1.1",
89
  "cmdk": "^0.2.1",
@@ -146,6 +148,7 @@
146
  "@types/react-dom": "^18",
147
  "@types/uuid": "^9.0.8",
148
  "@vitejs/plugin-react": "^4.3.1",
 
149
  "electron": "^31.2.1",
150
  "eslint": "^8",
151
  "eslint-config-next": "14.2.5",
 
25
  "format:fix": "prettier --write --ignore-path .gitignore ./src/",
26
  "lint": "next lint",
27
  "lint:fix": "next lint --fix",
28
+ "test": "npm run build && npm run test:unit:ci",
29
+ "test_TEMPORARY_DISABLED": "npm run build && npm run test:unit:ci && npm run test:e2e",
30
  "test:unit:ci": "vitest run",
31
  "test:unit:watch": "vitest",
32
  "test:e2e": "npx playwright test",
 
36
  "electron:make": "npm run build && electron-forge make"
37
  },
38
  "dependencies": {
39
+ "@aitube/broadway": "0.1.1",
40
+ "@aitube/clap": "0.1.1",
41
+ "@aitube/clapper-services": "0.1.1",
42
+ "@aitube/engine": "0.1.1",
43
+ "@aitube/timeline": "0.1.1",
44
  "@fal-ai/serverless-client": "^0.13.0",
45
  "@ffmpeg/ffmpeg": "^0.12.10",
46
  "@ffmpeg/util": "^0.12.1",
 
85
  "@types/dom-speech-recognition": "^0.0.4",
86
  "@xenova/transformers": "github:xenova/transformers.js#v3",
87
  "autoprefixer": "10.4.19",
88
+ "base64-arraybuffer": "^1.0.2",
89
  "class-variance-authority": "^0.7.0",
90
  "clsx": "^2.1.1",
91
  "cmdk": "^0.2.1",
 
148
  "@types/react-dom": "^18",
149
  "@types/uuid": "^9.0.8",
150
  "@vitejs/plugin-react": "^4.3.1",
151
+ "@webgpu/types": "^0.1.44",
152
  "electron": "^31.2.1",
153
  "eslint": "^8",
154
  "eslint-config-next": "14.2.5",
playwright.config.ts CHANGED
@@ -31,6 +31,10 @@ export default defineConfig({
31
  trace: 'on-first-retry',
32
  },
33
 
 
 
 
 
34
  /* Configure projects for major browsers */
35
  projects: [
36
  {
 
31
  trace: 'on-first-retry',
32
  },
33
 
34
+ expect: {
35
+ timeout: 10000,
36
+ },
37
+
38
  /* Configure projects for major browsers */
39
  projects: [
40
  {
src/components/monitor/index.tsx CHANGED
@@ -24,7 +24,7 @@ export function Monitor() {
24
  >
25
  <UniversalPlayer />
26
  <PlayerControls />
27
- <div className="absolute right-0 top-8 z-20">
28
  <div
29
  onClick={() => setFullscreen()}
30
  className={cn(
 
24
  >
25
  <UniversalPlayer />
26
  <PlayerControls />
27
+ <div className="absolute right-0 top-0 z-20">
28
  <div
29
  onClick={() => setFullscreen()}
30
  className={cn(
src/components/toolbars/bottom-bar/index.tsx CHANGED
@@ -31,7 +31,7 @@ export function BottomToolbar() {
31
  <span className="text-stone-300/70">{APP_REVISION}</span>
32
  </div>
33
 
34
- <Metrics />
35
  </div>
36
  <div className="flex flex-row space-x-6">
37
  <Tasks />
 
31
  <span className="text-stone-300/70">{APP_REVISION}</span>
32
  </div>
33
 
34
+ {/* <Metrics /> */}
35
  </div>
36
  <div className="flex flex-row space-x-6">
37
  <Tasks />
src/components/toolbars/bottom-bar/metrics/index.tsx CHANGED
@@ -4,14 +4,8 @@ import { cn } from '@/lib/utils'
4
  export function Metrics() {
5
  const { isAvailable, isMeasuring, bytes, humanReadableString } =
6
  usePerformanceMeter({
7
- delayBetweenMeasures: 20,
8
  })
9
- console.log('debug:', {
10
- isAvailable,
11
- isMeasuring,
12
- bytes,
13
- humanReadableString,
14
- })
15
 
16
  if (!isAvailable) {
17
  return null
 
4
  export function Metrics() {
5
  const { isAvailable, isMeasuring, bytes, humanReadableString } =
6
  usePerformanceMeter({
7
+ delayBetweenMeasures: 40,
8
  })
 
 
 
 
 
 
9
 
10
  if (!isAvailable) {
11
  return null
src/components/toolbars/editors-menu/EditorsSideMenuItem.tsx CHANGED
@@ -61,17 +61,17 @@ export function EditorsSideMenuItem({
61
  `transition-all duration-200 ease-out`,
62
  `items-center justify-center`,
63
  unmanaged || isActive ? '' : `cursor-pointer`,
64
- `border-l-[3px]`,
65
  isActive
66
  ? 'fill-gray-50 text-gray-50 hover:fill-gray-50 hover:text-gray-50'
67
- : 'hover:tefillxt-gray-200 fill-gray-400 text-gray-400 hover:text-gray-200',
68
  `group`
69
  )}
70
  style={{
71
  // background: theme.editorMenuBgColor || theme.defaultBgColor || "#eeeeee",
72
  borderColor: isActive
73
  ? theme.defaultPrimaryColor || '#ffffff'
74
- : '#111827',
75
  }}
76
  onClick={handleClick}
77
  >
 
61
  `transition-all duration-200 ease-out`,
62
  `items-center justify-center`,
63
  unmanaged || isActive ? '' : `cursor-pointer`,
64
+ `border-l-[2px]`,
65
  isActive
66
  ? 'fill-gray-50 text-gray-50 hover:fill-gray-50 hover:text-gray-50'
67
+ : 'fill-gray-400 text-gray-400 hover:fill-gray-200 hover:text-gray-200',
68
  `group`
69
  )}
70
  style={{
71
  // background: theme.editorMenuBgColor || theme.defaultBgColor || "#eeeeee",
72
  borderColor: isActive
73
  ? theme.defaultPrimaryColor || '#ffffff'
74
+ : 'rgba(0,0,0,0)',
75
  }}
76
  onClick={handleClick}
77
  >
src/components/toolbars/top-menu/index.tsx CHANGED
@@ -1,7 +1,8 @@
1
  import { cn } from '@aitube/timeline'
 
 
2
 
3
  import { Menubar } from '@/components/ui/menubar'
4
- import { APP_REVISION } from '@/lib/core/constants'
5
  import { useUI, useResolver } from '@/services'
6
 
7
  import { TopMenuFile } from './file'
@@ -15,6 +16,11 @@ import { TopMenuAssistant } from './assistant'
15
  import { TopMenuView } from './view'
16
  import { TopMenuLogo } from './TopMenuLogo'
17
  import { TopMenuPlugins } from './plugins'
 
 
 
 
 
18
 
19
  export function TopMenu() {
20
  const isBusyResolving = useResolver((s) => s.isBusyResolving)
@@ -43,12 +49,37 @@ export function TopMenu() {
43
  <TopMenuView />
44
  <div
45
  className={cn(
46
- `pointer-events-none flex flex-grow flex-row items-center justify-end px-2 text-xs text-stone-300`
47
  )}
48
  >
49
  {
50
  // clap?.meta?.title || "Untitled"
51
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  </div>
53
  </Menubar>
54
  )
 
1
  import { cn } from '@aitube/timeline'
2
+ import { TbBrandDiscord } from 'react-icons/tb'
3
+ import { FaGithubAlt } from 'react-icons/fa'
4
 
5
  import { Menubar } from '@/components/ui/menubar'
 
6
  import { useUI, useResolver } from '@/services'
7
 
8
  import { TopMenuFile } from './file'
 
16
  import { TopMenuView } from './view'
17
  import { TopMenuLogo } from './TopMenuLogo'
18
  import { TopMenuPlugins } from './plugins'
19
+ import {
20
+ Tooltip,
21
+ TooltipContent,
22
+ TooltipTrigger,
23
+ } from '@/components/ui/tooltip'
24
 
25
  export function TopMenu() {
26
  const isBusyResolving = useResolver((s) => s.isBusyResolving)
 
49
  <TopMenuView />
50
  <div
51
  className={cn(
52
+ `flex flex-grow flex-row items-center justify-end space-x-3 px-2 text-xs`
53
  )}
54
  >
55
  {
56
  // clap?.meta?.title || "Untitled"
57
  }
58
+ <Tooltip>
59
+ <TooltipTrigger className="">
60
+ <div className="scale-100 cursor-pointer text-stone-300/70 transition-all duration-200 ease-in-out hover:scale-110 hover:text-stone-100/90">
61
+ <a href="https://discord.gg/AEruz9B92B" target='"_blank'>
62
+ <TbBrandDiscord className="h-4 w-4" />
63
+ </a>
64
+ </div>
65
+ </TooltipTrigger>
66
+ <TooltipContent className="mr-4 mt-2 text-xs font-light">
67
+ Community
68
+ </TooltipContent>
69
+ </Tooltip>
70
+
71
+ <Tooltip>
72
+ <TooltipTrigger className="">
73
+ <div className="scale-100 cursor-pointer text-stone-300/70 transition-all duration-200 ease-in-out hover:scale-110 hover:text-stone-100/90">
74
+ <a href="https://discord.gg/AEruz9B92B" target='"_blank'>
75
+ <FaGithubAlt className="h-4 w-4" />
76
+ </a>
77
+ </div>
78
+ </TooltipTrigger>
79
+ <TooltipContent className="mr-4 mt-2 text-xs font-light">
80
+ Code
81
+ </TooltipContent>
82
+ </Tooltip>
83
  </div>
84
  </Menubar>
85
  )
src/components/tree-browsers/stores/useEntityLibrary.ts CHANGED
@@ -1,7 +1,7 @@
1
  'use client'
2
 
3
  import { create } from 'zustand'
4
- import { ClapEntity, UUID } from '@aitube/clap'
5
  import {
6
  CivitaiCollection,
7
  LibraryNodeItem,
@@ -191,10 +191,10 @@ export const useEntityLibrary = create<{
191
  icon: icons.misc,
192
  className: itemClassName,
193
  }
194
- if (entity.category === 'character') {
195
  node.icon = icons.character
196
  characters.children!.push(node)
197
- } else if (entity.category === 'location') {
198
  node.icon = icons.location
199
  locations.children!.push(node)
200
  } else {
 
1
  'use client'
2
 
3
  import { create } from 'zustand'
4
+ import { ClapEntity, ClapSegmentCategory, UUID } from '@aitube/clap'
5
  import {
6
  CivitaiCollection,
7
  LibraryNodeItem,
 
191
  icon: icons.misc,
192
  className: itemClassName,
193
  }
194
+ if (entity.category === ClapSegmentCategory.CHARACTER) {
195
  node.icon = icons.character
196
  characters.children!.push(node)
197
+ } else if (entity.category === ClapSegmentCategory.LOCATION) {
198
  node.icon = icons.location
199
  locations.children!.push(node)
200
  } else {
src/components/tree-browsers/stores/useProjectLibrary.ts CHANGED
@@ -1,7 +1,7 @@
1
  'use client'
2
 
3
  import { create } from 'zustand'
4
- import { ClapEntity, UUID } from '@aitube/clap'
5
 
6
  import { icons } from '@/components/icons'
7
 
@@ -85,11 +85,11 @@ export const useProjectLibrary = create<{
85
  icon: icons.misc,
86
  className: collectionClassName,
87
  }
88
- if (entity.category === 'character') {
89
  node.icon = icons.character
90
  node.nodeType = 'LIB_NODE_PROJECT_ENTITY_CHARACTER'
91
  characters.children!.push(node)
92
- } else if (entity.category === 'location') {
93
  node.icon = icons.location
94
  node.nodeType = 'LIB_NODE_PROJECT_ENTITY_LOCATION'
95
  locations.children!.push(node)
 
1
  'use client'
2
 
3
  import { create } from 'zustand'
4
+ import { ClapEntity, ClapSegmentCategory, UUID } from '@aitube/clap'
5
 
6
  import { icons } from '@/components/icons'
7
 
 
85
  icon: icons.misc,
86
  className: collectionClassName,
87
  }
88
+ if (entity.category === ClapSegmentCategory.CHARACTER) {
89
  node.icon = icons.character
90
  node.nodeType = 'LIB_NODE_PROJECT_ENTITY_CHARACTER'
91
  characters.children!.push(node)
92
+ } else if (entity.category === ClapSegmentCategory.LOCATION) {
93
  node.icon = icons.location
94
  node.nodeType = 'LIB_NODE_PROJECT_ENTITY_LOCATION'
95
  locations.children!.push(node)
src/experiments/grading/README.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ Utilities to apply color grading to an image.
2
+
3
+ The purpose is to be able to unify / homogeneize
src/experiments/grading/applyColorGrading.ts ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { decode, encode } from 'base64-arraybuffer'
2
+
3
+ import { ColorGradingFilter } from './types'
4
+
5
+ export async function applyColorGrading({
6
+ images,
7
+ filters,
8
+ }: {
9
+ images: Array<{ image: string; depthMap?: string }>
10
+ filters: Array<{
11
+ filter: ColorGradingFilter
12
+ parameters?: Record<string, string | number>
13
+ }>
14
+ }): Promise<string[]> {
15
+ if (!navigator.gpu) {
16
+ throw new Error('WebGPU is not supported in this browser.')
17
+ }
18
+
19
+ const adapter = await navigator.gpu.requestAdapter()
20
+ if (!adapter) {
21
+ throw new Error('Failed to get GPU adapter.')
22
+ }
23
+
24
+ const device = await adapter.requestDevice()
25
+ if (!device) {
26
+ throw new Error('Failed to get GPU device.')
27
+ }
28
+
29
+ const processedImages: string[] = []
30
+
31
+ for (const { image, depthMap } of images) {
32
+ const imgData = await loadImage(image)
33
+ let texture = device.createTexture({
34
+ size: [imgData.width, imgData.height, 1],
35
+ format: 'rgba8unorm',
36
+ usage:
37
+ GPUTextureUsage.TEXTURE_BINDING |
38
+ GPUTextureUsage.COPY_DST |
39
+ GPUTextureUsage.STORAGE_BINDING,
40
+ })
41
+
42
+ device.queue.writeTexture(
43
+ { texture },
44
+ imgData.data,
45
+ { bytesPerRow: imgData.width * 4 },
46
+ { width: imgData.width, height: imgData.height }
47
+ )
48
+
49
+ let depthTexture: GPUTexture | null = null
50
+ if (depthMap) {
51
+ const depthImgData = await loadImage(depthMap)
52
+ depthTexture = device.createTexture({
53
+ size: [depthImgData.width, depthImgData.height, 1],
54
+ format: 'r8unorm',
55
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
56
+ })
57
+
58
+ device.queue.writeTexture(
59
+ { texture: depthTexture },
60
+ depthImgData.data,
61
+ { bytesPerRow: depthImgData.width },
62
+ { width: depthImgData.width, height: depthImgData.height }
63
+ )
64
+ }
65
+
66
+ for (const { filter, parameters } of filters) {
67
+ texture = await applyFilter(
68
+ device,
69
+ texture,
70
+ depthTexture,
71
+ filter,
72
+ parameters
73
+ )
74
+ }
75
+
76
+ const resultBuffer = await readTextureToBuffer(device, texture)
77
+ const base64 = encode(resultBuffer)
78
+ processedImages.push(`data:image/png;base64,${base64}`)
79
+ }
80
+
81
+ return processedImages
82
+ }
83
+
84
+ async function loadImage(dataUri: string): Promise<ImageData> {
85
+ return new Promise((resolve, reject) => {
86
+ const img = new Image()
87
+ img.onload = () => {
88
+ const canvas = document.createElement('canvas')
89
+ canvas.width = img.width
90
+ canvas.height = img.height
91
+ const ctx = canvas.getContext('2d')
92
+ if (!ctx) {
93
+ reject(new Error('Failed to get 2D context'))
94
+ return
95
+ }
96
+ ctx.drawImage(img, 0, 0)
97
+ resolve(ctx.getImageData(0, 0, img.width, img.height))
98
+ }
99
+ img.onerror = reject
100
+ img.src = dataUri
101
+ })
102
+ }
103
+
104
+ async function applyFilter(
105
+ device: GPUDevice,
106
+ inputTexture: GPUTexture,
107
+ depthTexture: GPUTexture | null,
108
+ filter: ColorGradingFilter,
109
+ parameters?: Record<string, string | number>
110
+ ): Promise<GPUTexture> {
111
+ const shader = createShaderModule(device, filter.shader)
112
+ const pipeline = device.createComputePipeline({
113
+ layout: 'auto',
114
+ compute: { module: shader, entryPoint: 'main' },
115
+ })
116
+
117
+ const outputTexture = device.createTexture({
118
+ size: [inputTexture.width, inputTexture.height, 1],
119
+ format: 'rgba8unorm',
120
+ usage: GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_SRC,
121
+ })
122
+
123
+ // Automatically calculate uniform buffer size and create typed array
124
+ const uniformData: number[] = []
125
+ filter.parameters.forEach((param) => {
126
+ if (param.type === 'number') {
127
+ uniformData.push(
128
+ (parameters?.[param.name] as number) ?? param.defaultValue
129
+ )
130
+ } else if (param.type === 'string') {
131
+ // For string parameters, we'll use the index of the value in allowedValues
132
+ const value = (parameters?.[param.name] as string) ?? param.defaultValue
133
+ const index = param.allowedValues.indexOf(value)
134
+ uniformData.push(index)
135
+ }
136
+ })
137
+
138
+ const uniformTypedArray = new Float32Array(uniformData)
139
+ const uniformBufferSize = uniformTypedArray.byteLength
140
+ const uniformBuffer = device.createBuffer({
141
+ size: uniformBufferSize,
142
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
143
+ })
144
+
145
+ device.queue.writeBuffer(uniformBuffer, 0, uniformTypedArray)
146
+
147
+ const sampler = device.createSampler({
148
+ magFilter: 'linear',
149
+ minFilter: 'linear',
150
+ })
151
+
152
+ const bindGroupEntries: GPUBindGroupEntry[] = [
153
+ { binding: 0, resource: inputTexture.createView() },
154
+ { binding: 1, resource: outputTexture.createView() },
155
+ { binding: 2, resource: { buffer: uniformBuffer } },
156
+ { binding: 4, resource: sampler },
157
+ ]
158
+
159
+ if (depthTexture) {
160
+ bindGroupEntries.push({ binding: 3, resource: depthTexture.createView() })
161
+ } else {
162
+ // Create a dummy 1x1 depth texture if no depth texture is provided
163
+ const dummyDepthTexture = device.createTexture({
164
+ size: [1, 1],
165
+ format: 'r32float',
166
+ usage: GPUTextureUsage.TEXTURE_BINDING,
167
+ })
168
+ bindGroupEntries.push({
169
+ binding: 3,
170
+ resource: dummyDepthTexture.createView(),
171
+ })
172
+ }
173
+
174
+ const bindGroup = device.createBindGroup({
175
+ layout: pipeline.getBindGroupLayout(0),
176
+ entries: bindGroupEntries,
177
+ })
178
+
179
+ const commandEncoder = device.createCommandEncoder()
180
+ const passEncoder = commandEncoder.beginComputePass()
181
+ passEncoder.setPipeline(pipeline)
182
+ passEncoder.setBindGroup(0, bindGroup)
183
+ passEncoder.dispatchWorkgroups(
184
+ Math.ceil(inputTexture.width / 8),
185
+ Math.ceil(inputTexture.height / 8)
186
+ )
187
+ passEncoder.end()
188
+
189
+ device.queue.submit([commandEncoder.finish()])
190
+
191
+ return outputTexture
192
+ }
193
+
194
+ function createShaderModule(
195
+ device: GPUDevice,
196
+ shaderCode: string
197
+ ): GPUShaderModule {
198
+ return device.createShaderModule({ code: shaderCode })
199
+ }
200
+
201
+ async function readTextureToBuffer(
202
+ device: GPUDevice,
203
+ texture: GPUTexture
204
+ ): Promise<ArrayBuffer> {
205
+ const bufferSize = texture.width * texture.height * 4
206
+ const resultBuffer = device.createBuffer({
207
+ size: bufferSize,
208
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
209
+ })
210
+
211
+ const commandEncoder = device.createCommandEncoder()
212
+ commandEncoder.copyTextureToBuffer(
213
+ { texture },
214
+ { buffer: resultBuffer, bytesPerRow: texture.width * 4 },
215
+ { width: texture.width, height: texture.height }
216
+ )
217
+
218
+ device.queue.submit([commandEncoder.finish()])
219
+
220
+ await resultBuffer.mapAsync(GPUMapMode.READ)
221
+ const arrayBuffer = resultBuffer.getMappedRange().slice(0)
222
+ resultBuffer.unmap()
223
+
224
+ return arrayBuffer
225
+ }
src/experiments/grading/applyColorGradingDemo.ts ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { applyColorGrading } from './applyColorGrading'
2
+
3
+ import { analogLensSimulator } from './filters/analogLens'
4
+ import { cinematic } from './filters/cinematic'
5
+ import { colorTemperature } from './filters/colorTemperature'
6
+ import { crossProcessing } from './filters/crossProcessing'
7
+ import { filmDegradation } from './filters/filmDegradation'
8
+ import { infraredBlackAndWhite } from './filters/infrared'
9
+ import { lomography } from './filters/lomography'
10
+ import { splitToning } from './filters/splitToning'
11
+ import { hdrToneMapping } from './filters/toneMapping'
12
+ import { vintageFilm } from './filters/vintageFilm'
13
+
14
+ export async function demo() {
15
+ const base64DataUriImages = await applyColorGrading({
16
+ images: [
17
+ {
18
+ image: 'data:image/png....',
19
+ // depthMap: "data:image/png...." // optional depth map
20
+ },
21
+ ],
22
+ filters: [
23
+ {
24
+ filter: analogLensSimulator,
25
+ parameters: {
26
+ chromaticAberration: 0.003,
27
+ vignetteStrength: 0.4,
28
+ vignetteRadius: 0.8,
29
+ distortion: 0.15,
30
+ bloomStrength: 0.2,
31
+ bloomRadius: 4,
32
+ dofFocusDistance: 0.6,
33
+ dofFocusRange: 0.1,
34
+ dofBlurStrength: 3,
35
+ },
36
+ },
37
+
38
+ {
39
+ filter: infraredBlackAndWhite,
40
+ parameters: {
41
+ contrast: 1.3,
42
+ grain: 0.25,
43
+ glow: 0.4,
44
+ },
45
+ },
46
+ {
47
+ filter: filmDegradation,
48
+ parameters: {
49
+ scratchesIntensity: 0.35,
50
+ dustIntensity: 0.25,
51
+ colorFading: 0.4,
52
+ lightLeakIntensity: 0.3,
53
+ },
54
+ },
55
+ {
56
+ filter: crossProcessing,
57
+ parameters: {
58
+ intensity: 0.6,
59
+ contrastBoost: 0.4,
60
+ colorShift: 'Cool',
61
+ },
62
+ },
63
+ {
64
+ filter: lomography,
65
+ parameters: {
66
+ saturation: 1.4,
67
+ contrast: 1.3,
68
+ vignetteIntensity: 0.6,
69
+ lightLeakIntensity: 0.4,
70
+ },
71
+ },
72
+ {
73
+ filter: cinematic,
74
+ parameters: {
75
+ preset: 'Blade Runner',
76
+ intensity: 0.6,
77
+ contrast: 1.3,
78
+ },
79
+ },
80
+ {
81
+ filter: splitToning,
82
+ parameters: {
83
+ highlightColor: 'Yellow',
84
+ shadowColor: 'Blue',
85
+ balance: 0.1,
86
+ intensity: 0.5,
87
+ },
88
+ },
89
+
90
+ {
91
+ filter: hdrToneMapping,
92
+ parameters: {
93
+ exposure: 0.5,
94
+ contrast: 1.2,
95
+ saturation: 1.1,
96
+ highlights: -0.2,
97
+ shadows: 0.3,
98
+ },
99
+ },
100
+ {
101
+ filter: colorTemperature,
102
+ parameters: {
103
+ temperature: 5500,
104
+ tint: 10,
105
+ },
106
+ },
107
+ {
108
+ filter: vintageFilm,
109
+ parameters: {
110
+ preset: 'Kodachrome 64',
111
+ intensity: 0.8,
112
+ grain: 0.3,
113
+ ageEffect: 0.2,
114
+ colorShift: 0.05,
115
+ contrast: 1.1,
116
+ saturation: 1.2,
117
+ },
118
+ },
119
+ ],
120
+ })
121
+ }
src/experiments/grading/filters/DEPRECATED_analogFilm.ts ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ColorGradingFilter } from '../types'
2
+
3
+ export const analogFilmSimulator: ColorGradingFilter = {
4
+ name: 'Analog Film Simulator',
5
+ parameters: [
6
+ {
7
+ name: 'preset',
8
+ description: 'Film preset',
9
+ type: 'string',
10
+ allowedValues: [
11
+ 'Konica Centuria 200',
12
+ 'Kodak Portra 400',
13
+ 'Fujifilm Superia 1600',
14
+ ],
15
+ defaultValue: 'Konica Centuria 200',
16
+ },
17
+ {
18
+ name: 'saturation',
19
+ description: 'Color saturation',
20
+ type: 'number',
21
+ minValue: 0,
22
+ maxValue: 2,
23
+ defaultValue: 1,
24
+ },
25
+ {
26
+ name: 'noise',
27
+ description: 'Film grain intensity',
28
+ type: 'number',
29
+ minValue: 0,
30
+ maxValue: 1,
31
+ defaultValue: 0.2,
32
+ },
33
+ ],
34
+ shader: `
35
+ struct Params {
36
+ preset: u32,
37
+ saturation: f32,
38
+ noise: f32,
39
+ }
40
+
41
+ @group(0) @binding(0) var input_texture: texture_2d<f32>;
42
+ @group(0) @binding(1) var output_texture: texture_storage_2d<rgba8unorm, write>;
43
+ @group(0) @binding(2) var<uniform> params: Params;
44
+ @group(0) @binding(3) var depth_texture: texture_2d<f32>;
45
+
46
+ // Film preset color matrices
47
+ const konica_centuria_200 = mat3x3<f32>(
48
+ 1.0, 0.0, 0.0,
49
+ -0.1, 1.1, 0.0,
50
+ 0.0, 0.1, 0.9
51
+ );
52
+
53
+ const kodak_portra_400 = mat3x3<f32>(
54
+ 1.1, -0.1, 0.0,
55
+ 0.0, 1.0, 0.0,
56
+ -0.1, 0.1, 1.0
57
+ );
58
+
59
+ const fujifilm_superia_1600 = mat3x3<f32>(
60
+ 1.2, -0.1, -0.1,
61
+ -0.1, 1.1, 0.0,
62
+ 0.0, 0.0, 1.0
63
+ );
64
+
65
+ // Helper functions
66
+ fn rgb_to_hsv(rgb: vec3<f32>) -> vec3<f32> {
67
+ let v = max(max(rgb.r, rgb.g), rgb.b);
68
+ let c = v - min(min(rgb.r, rgb.g), rgb.b);
69
+ let s = select(0.0, c / v, v != 0.0);
70
+
71
+ var h: f32;
72
+ if (c == 0.0) {
73
+ h = 0.0;
74
+ } else if (v == rgb.r) {
75
+ h = (rgb.g - rgb.b) / c;
76
+ } else if (v == rgb.g) {
77
+ h = 2.0 + (rgb.b - rgb.r) / c;
78
+ } else {
79
+ h = 4.0 + (rgb.r - rgb.g) / c;
80
+ }
81
+ h = fract(h / 6.0);
82
+
83
+ return vec3<f32>(h, s, v);
84
+ }
85
+
86
+ fn hsv_to_rgb(hsv: vec3<f32>) -> vec3<f32> {
87
+ let h = hsv.x * 6.0;
88
+ let s = hsv.y;
89
+ let v = hsv.z;
90
+
91
+ let c = v * s;
92
+ let x = c * (1.0 - abs(fract(h / 2.0) * 2.0 - 1.0));
93
+ let m = v - c;
94
+
95
+ var rgb: vec3<f32>;
96
+ if (h < 1.0) {
97
+ rgb = vec3<f32>(c, x, 0.0);
98
+ } else if (h < 2.0) {
99
+ rgb = vec3<f32>(x, c, 0.0);
100
+ } else if (h < 3.0) {
101
+ rgb = vec3<f32>(0.0, c, x);
102
+ } else if (h < 4.0) {
103
+ rgb = vec3<f32>(0.0, x, c);
104
+ } else if (h < 5.0) {
105
+ rgb = vec3<f32>(x, 0.0, c);
106
+ } else {
107
+ rgb = vec3<f32>(c, 0.0, x);
108
+ }
109
+
110
+ return rgb + vec3<f32>(m);
111
+ }
112
+
113
+ fn apply_film_preset(color: vec3<f32>, preset: u32) -> vec3<f32> {
114
+ switch preset {
115
+ case 0u: { return konica_centuria_200 * color; }
116
+ case 1u: { return kodak_portra_400 * color; }
117
+ case 2u: { return fujifilm_superia_1600 * color; }
118
+ default: { return color; }
119
+ }
120
+ }
121
+
122
+ fn apply_saturation(color: vec3<f32>, saturation: f32) -> vec3<f32> {
123
+ let luminance = dot(color, vec3<f32>(0.299, 0.587, 0.114));
124
+ return mix(vec3<f32>(luminance), color, saturation);
125
+ }
126
+
127
+ fn apply_contrast(color: vec3<f32>, contrast: f32) -> vec3<f32> {
128
+ return (color - 0.5) * contrast + 0.5;
129
+ }
130
+
131
+ fn rand(co: vec2<f32>) -> f32 {
132
+ return fract(sin(dot(co, vec2<f32>(12.9898, 78.233))) * 43758.5453);
133
+ }
134
+
135
+ fn apply_film_grain(color: vec3<f32>, coord: vec2<f32>, amount: f32) -> vec3<f32> {
136
+ let noise = rand(coord) - 0.5;
137
+ return color + noise * amount;
138
+ }
139
+
140
+ @compute @workgroup_size(8, 8)
141
+ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
142
+ let dimensions = textureDimensions(input_texture);
143
+ let coord = vec2<i32>(global_id.xy);
144
+
145
+ if (coord.x >= dimensions.x || coord.y >= dimensions.y) {
146
+ return;
147
+ }
148
+
149
+ var color = textureLoad(input_texture, coord, 0).rgb;
150
+
151
+ // Apply film preset
152
+ color = apply_film_preset(color, params.preset);
153
+
154
+ // Convert to HSV for saturation adjustment
155
+ var hsv = rgb_to_hsv(color);
156
+ hsv.y *= params.saturation;
157
+ color = hsv_to_rgb(hsv);
158
+
159
+ // Apply contrast
160
+ color = apply_contrast(color, 1.1); // Slight increase in contrast
161
+
162
+ // Apply film grain
163
+ color = apply_film_grain(color, vec2<f32>(coord), params.noise);
164
+
165
+ // Ensure color values are within [0, 1] range
166
+ color = clamp(color, vec3<f32>(0.0), vec3<f32>(1.0));
167
+
168
+ textureStore(output_texture, coord, vec4<f32>(color, 1.0));
169
+ }
170
+ `,
171
+ }
src/experiments/grading/filters/analogLens.ts ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ColorGradingFilter } from '../types'
2
+
3
+ export const analogLensSimulator: ColorGradingFilter = {
4
+ name: 'Analog Lens Simulator',
5
+ parameters: [
6
+ {
7
+ name: 'chromaticAberration',
8
+ description: 'Chromatic aberration strength',
9
+ type: 'number',
10
+ minValue: 0,
11
+ maxValue: 0.05,
12
+ defaultValue: 0.002,
13
+ },
14
+ {
15
+ name: 'vignetteStrength',
16
+ description: 'Vignette strength',
17
+ type: 'number',
18
+ minValue: 0,
19
+ maxValue: 1,
20
+ defaultValue: 0.3,
21
+ },
22
+ {
23
+ name: 'vignetteRadius',
24
+ description: 'Vignette radius',
25
+ type: 'number',
26
+ minValue: 0,
27
+ maxValue: 1,
28
+ defaultValue: 0.75,
29
+ },
30
+ {
31
+ name: 'distortion',
32
+ description: 'Lens distortion',
33
+ type: 'number',
34
+ minValue: -1,
35
+ maxValue: 1,
36
+ defaultValue: 0.1,
37
+ },
38
+ {
39
+ name: 'bloomStrength',
40
+ description: 'Bloom strength',
41
+ type: 'number',
42
+ minValue: 0,
43
+ maxValue: 1,
44
+ defaultValue: 0.1,
45
+ },
46
+ {
47
+ name: 'bloomRadius',
48
+ description: 'Bloom radius',
49
+ type: 'number',
50
+ minValue: 1,
51
+ maxValue: 10,
52
+ defaultValue: 3,
53
+ },
54
+ {
55
+ name: 'dofFocusDistance',
56
+ description: 'Depth of field focus distance',
57
+ type: 'number',
58
+ minValue: 0,
59
+ maxValue: 1,
60
+ defaultValue: 0.5,
61
+ },
62
+ {
63
+ name: 'dofFocusRange',
64
+ description: 'Depth of field focus range',
65
+ type: 'number',
66
+ minValue: 0.01,
67
+ maxValue: 1,
68
+ defaultValue: 0.1,
69
+ },
70
+ {
71
+ name: 'dofBlurStrength',
72
+ description: 'Depth of field blur strength',
73
+ type: 'number',
74
+ minValue: 0,
75
+ maxValue: 10,
76
+ defaultValue: 2,
77
+ },
78
+ ],
79
+ shader: `
80
+ struct Params {
81
+ chromatic_aberration: f32,
82
+ vignette_strength: f32,
83
+ vignette_radius: f32,
84
+ distortion: f32,
85
+ bloom_strength: f32,
86
+ bloom_radius: f32,
87
+ dof_focus_distance: f32,
88
+ dof_focus_range: f32,
89
+ dof_blur_strength: f32,
90
+ }
91
+
92
+ @group(0) @binding(0) var input_texture: texture_2d<f32>;
93
+ @group(0) @binding(1) var output_texture: texture_storage_2d<rgba8unorm, write>;
94
+ @group(0) @binding(2) var<uniform> params: Params;
95
+ @group(0) @binding(3) var depth_texture: texture_2d<f32>;
96
+ @group(0) @binding(4) var texture_sampler: sampler;
97
+
98
+ // Helper functions
99
+ fn get_uv(coord: vec2<i32>, dimensions: vec2<u32>) -> vec2<f32> {
100
+ return (vec2<f32>(coord) + 0.5) / vec2<f32>(dimensions);
101
+ }
102
+
103
+ fn sample_texture(uv: vec2<f32>) -> vec4<f32> {
104
+ let dimensions = vec2<i32>(textureDimensions(input_texture));
105
+ let coord = vec2<i32>(uv * vec2<f32>(dimensions));
106
+ return textureLoad(input_texture, coord, 0);
107
+ }
108
+
109
+ fn apply_chromatic_aberration(uv: vec2<f32>, strength: f32) -> vec3<f32> {
110
+ let center = vec2<f32>(0.5, 0.5);
111
+ let dist = uv - center;
112
+
113
+ let r = sample_texture(uv + dist * strength).r;
114
+ let g = sample_texture(uv).g;
115
+ let b = sample_texture(uv - dist * strength).b;
116
+
117
+ return vec3<f32>(r, g, b);
118
+ }
119
+
120
+ fn apply_vignette(color: vec3<f32>, uv: vec2<f32>, strength: f32, radius: f32) -> vec3<f32> {
121
+ let center = vec2<f32>(0.5, 0.5);
122
+ let dist = distance(uv, center);
123
+ let vignette = smoothstep(radius, radius - 0.05, dist);
124
+ return color * mix(1.0, vignette, strength);
125
+ }
126
+
127
+ fn apply_distortion(uv: vec2<f32>, strength: f32) -> vec2<f32> {
128
+ let center = vec2<f32>(0.5, 0.5);
129
+ let dist = uv - center;
130
+ let r2 = dot(dist, dist);
131
+ let f = 1.0 + r2 * (strength * 0.5);
132
+ return center + dist * f;
133
+ }
134
+
135
+ fn apply_bloom(color: vec3<f32>, uv: vec2<f32>, strength: f32, radius: f32) -> vec3<f32> {
136
+ var blurred_color = vec3<f32>(0.0);
137
+ let dimensions = vec2<f32>(textureDimensions(input_texture));
138
+ let pixel_size = 1.0 / dimensions;
139
+
140
+ for (var i = -4; i <= 4; i++) {
141
+ for (var j = -4; j <= 4; j++) {
142
+ let offset = vec2<f32>(f32(i), f32(j)) * pixel_size * radius;
143
+ let sample = sample_texture(uv + offset).rgb;
144
+ let weight = 1.0 - length(offset) / (radius * 5.0 * pixel_size);
145
+ bloom += max(vec3<f32>(0.0), sample - 0.5) * weight;
146
+ }
147
+ }
148
+
149
+ bloom /= 81.0; // Normalize by the number of samples
150
+ return color + bloom * strength;
151
+ }
152
+
153
+ fn apply_variable_chromatic_aberration(uv: vec2<f32>, strength: f32) -> vec3<f32> {
154
+ let center = vec2<f32>(0.5, 0.5);
155
+ let dist = distance(uv, center);
156
+ let strength_scaled = strength * smoothstep(0.0, 1.0, dist * 2.0);
157
+
158
+ let dist_vec = (uv - center) * strength_scaled;
159
+ let r = sample_texture(uv + dist_vec).r;
160
+ let g = sample_texture(uv).g;
161
+ let b = sample_texture(uv - dist_vec).b;
162
+
163
+ return vec3<f32>(r, g, b);
164
+ }
165
+
166
+ fn get_depth(uv: vec2<f32>) -> f32 {
167
+ return textureSample(depth_texture, texture_sampler, uv).r;
168
+ }
169
+
170
+ fn apply_depth_of_field(color: vec3<f32>, uv: vec2<f32>, focus_distance: f32, focus_range: f32, blur_strength: f32) -> vec3<f32> {
171
+ let depth = get_depth(uv);
172
+ let coc = abs(depth - focus_distance) / focus_range;
173
+ let blur_amount = smoothstep(0.0, 1.0, coc) * blur_strength;
174
+
175
+ var blurred_color = vec3<f32>(0.0);
176
+ let dimensions = vec2<f32>(textureDimensions(input_texture));
177
+ let pixel_size = 1.0 / dimensions;
178
+
179
+ for (var i = -4; i <= 4; i++) {
180
+ for (var j = -4; j <= 4; j++) {
181
+ let offset = vec2<f32>(f32(i), f32(j)) * pixel_size * blur_amount;
182
+ blurred_color += sample_texture(uv + offset).rgb;
183
+ }
184
+ }
185
+
186
+ blurred_color /= 81.0; // Normalize by the number of samples
187
+ return mix(color, blurred_color, blur_amount);
188
+ }
189
+
190
+ @compute @workgroup_size(8, 8)
191
+ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
192
+ let dimensions = textureDimensions(input_texture);
193
+ let coord = vec2<i32>(global_id.xy);
194
+
195
+ if (coord.x >= i32(dimensions.x) || coord.y >= i32(dimensions.y)) {
196
+ return;
197
+ }
198
+
199
+ var uv = vec2<f32>(f32(coord.x) / f32(dimensions.x), f32(coord.y) / f32(dimensions.y));
200
+
201
+ // Apply lens distortion
202
+ uv = apply_distortion(uv, params.distortion);
203
+
204
+ // Check if the distorted UV is within bounds
205
+ if (any(uv < vec2<f32>(0.0)) || any(uv > vec2<f32>(1.0))) {
206
+ textureStore(output_texture, coord, vec4<f32>(0.0, 0.0, 0.0, 1.0));
207
+ return;
208
+ }
209
+
210
+ // Apply variable chromatic aberration
211
+ var color = apply_variable_chromatic_aberration(uv, params.chromatic_aberration);
212
+
213
+ // Apply bloom
214
+ color = apply_bloom(color, uv, params.bloom_strength, params.bloom_radius);
215
+
216
+ // Apply depth of field
217
+ color = apply_depth_of_field(color, uv, params.dof_focus_distance, params.dof_focus_range, params.dof_blur_strength);
218
+
219
+ // Apply vignette
220
+ color = apply_vignette(color, uv, params.vignette_strength, params.vignette_radius);
221
+
222
+ // Ensure color values are within [0, 1] range
223
+ color = clamp(color, vec3<f32>(0.0), vec3<f32>(1.0));
224
+
225
+ textureStore(output_texture, coord, vec4<f32>(color, 1.0));
226
+ }
227
+ `,
228
+ }
src/experiments/grading/filters/cinematic.ts ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ColorGradingFilter } from '../types'
2
+
3
+ export const cinematic: ColorGradingFilter = {
4
+ name: 'Cinematic Color Grading',
5
+ parameters: [
6
+ {
7
+ name: 'preset',
8
+ description: 'Cinematic color preset',
9
+ type: 'string',
10
+ allowedValues: [
11
+ 'Blade Runner',
12
+ 'Matrix',
13
+ 'Mad Max',
14
+ 'Moonlight',
15
+ 'La La Land',
16
+ ],
17
+ defaultValue: 'Blade Runner',
18
+ },
19
+ {
20
+ name: 'intensity',
21
+ description: 'Intensity of the cinematic effect',
22
+ type: 'number',
23
+ minValue: 0,
24
+ maxValue: 1,
25
+ defaultValue: 0.5,
26
+ },
27
+ {
28
+ name: 'contrast',
29
+ description: 'Image contrast',
30
+ type: 'number',
31
+ minValue: 0.5,
32
+ maxValue: 2,
33
+ defaultValue: 1.2,
34
+ },
35
+ ],
36
+ shader: `
37
+ struct Params {
38
+ preset: u32,
39
+ intensity: f32,
40
+ contrast: f32,
41
+ }
42
+
43
+ @group(0) @binding(0) var input_texture: texture_2d<f32>;
44
+ @group(0) @binding(1) var output_texture: texture_storage_2d<rgba8unorm, write>;
45
+ @group(0) @binding(2) var<uniform> params: Params;
46
+
47
+ fn apply_preset(color: vec3<f32>, preset: u32) -> vec3<f32> {
48
+ switch preset {
49
+ case 0u: { // Blade Runner
50
+ return mix(color, color * vec3<f32>(0.9, 1.1, 1.5), params.intensity);
51
+ }
52
+ case 1u: { // Matrix
53
+ return mix(color, color * vec3<f32>(0.8, 1.2, 0.8), params.intensity);
54
+ }
55
+ case 2u: { // Mad Max
56
+ return mix(color, color * vec3<f32>(1.2, 1.0, 0.8), params.intensity);
57
+ }
58
+ case 3u: { // Moonlight
59
+ return mix(color, color * vec3<f32>(0.9, 1.0, 1.2), params.intensity);
60
+ }
61
+ case 4u: { // La La Land
62
+ return mix(color, color * vec3<f32>(1.1, 1.0, 0.9), params.intensity);
63
+ }
64
+ default: {
65
+ return color;
66
+ }
67
+ }
68
+ }
69
+
70
+ @compute @workgroup_size(8, 8)
71
+ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
72
+ let dimensions = textureDimensions(input_texture);
73
+ let coord = vec2<i32>(global_id.xy);
74
+
75
+ if (coord.x >= dimensions.x || coord.y >= dimensions.y) {
76
+ return;
77
+ }
78
+
79
+ var color = textureLoad(input_texture, coord, 0).rgb;
80
+
81
+ // Apply contrast
82
+ color = (color - 0.5) * params.contrast + 0.5;
83
+
84
+ // Apply cinematic color preset
85
+ color = apply_preset(color, params.preset);
86
+
87
+ // Add subtle vignette effect
88
+ let uv = vec2<f32>(coord) / vec2<f32>(dimensions);
89
+ let vignette = 1.0 - smoothstep(0.5, 1.5, distance(uv, vec2<f32>(0.5)));
90
+ color *= mix(1.0, vignette, 0.2);
91
+
92
+ // Ensure color values are within [0, 1] range
93
+ color = clamp(color, vec3<f32>(0.0), vec3<f32>(1.0));
94
+
95
+ textureStore(output_texture, coord, vec4<f32>(color, 1.0));
96
+ }
97
+ `,
98
+ }
src/experiments/grading/filters/colorMapping.ts ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ColorGradingFilter } from '../types'
2
+
3
+ // Example filter implementations
4
+ export const colorMapping: ColorGradingFilter = {
5
+ name: 'Color Mapping',
6
+ parameters: [
7
+ {
8
+ name: 'redMultiplier',
9
+ description: 'Red channel multiplier',
10
+ type: 'number',
11
+ minValue: 0,
12
+ maxValue: 2,
13
+ defaultValue: 1,
14
+ },
15
+ {
16
+ name: 'greenMultiplier',
17
+ description: 'Green channel multiplier',
18
+ type: 'number',
19
+ minValue: 0,
20
+ maxValue: 2,
21
+ defaultValue: 1,
22
+ },
23
+ {
24
+ name: 'blueMultiplier',
25
+ description: 'Blue channel multiplier',
26
+ type: 'number',
27
+ minValue: 0,
28
+ maxValue: 2,
29
+ defaultValue: 1,
30
+ },
31
+ ],
32
+ shader: `
33
+ @group(0) @binding(0) var inputTexture : texture_2d<f32>;
34
+ @group(0) @binding(1) var outputTexture : texture_storage_2d<rgba8unorm, write>;
35
+ @group(0) @binding(2) var<uniform> params : vec3<f32>;
36
+
37
+ @compute @workgroup_size(8, 8)
38
+ fn main(@builtin(global_invocation_id) global_id : vec3<u32>) {
39
+ let dims = textureDimensions(inputTexture);
40
+ if (global_id.x >= dims.x || global_id.y >= dims.y) {
41
+ return;
42
+ }
43
+ let color = textureLoad(inputTexture, global_id.xy, 0);
44
+ let mapped = vec4<f32>(
45
+ color.r * params.x,
46
+ color.g * params.y,
47
+ color.b * params.z,
48
+ color.a
49
+ );
50
+ textureStore(outputTexture, global_id.xy, mapped);
51
+ }
52
+ `,
53
+ }
src/experiments/grading/filters/colorTemperature.ts ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ColorGradingFilter } from '../types'
2
+
3
+ export const colorTemperature: ColorGradingFilter = {
4
+ name: 'Color Temperature Adjustment',
5
+ parameters: [
6
+ {
7
+ name: 'temperature',
8
+ description: 'Color temperature in Kelvin',
9
+ type: 'number',
10
+ minValue: 1000,
11
+ maxValue: 40000,
12
+ defaultValue: 6500,
13
+ },
14
+ {
15
+ name: 'tint',
16
+ description: 'Green-Magenta tint',
17
+ type: 'number',
18
+ minValue: -100,
19
+ maxValue: 100,
20
+ defaultValue: 0,
21
+ },
22
+ ],
23
+ shader: `
24
+ struct Params {
25
+ temperature: f32,
26
+ tint: f32,
27
+ }
28
+
29
+ @group(0) @binding(0) var input_texture: texture_2d<f32>;
30
+ @group(0) @binding(1) var output_texture: texture_storage_2d<rgba8unorm, write>;
31
+ @group(0) @binding(2) var<uniform> params: Params;
32
+
33
+ fn rgb_to_xyz(rgb: vec3<f32>) -> vec3<f32> {
34
+ let m = mat3x3<f32>(
35
+ 0.4124564, 0.3575761, 0.1804375,
36
+ 0.2126729, 0.7151522, 0.0721750,
37
+ 0.0193339, 0.1191920, 0.9503041
38
+ );
39
+ return m * rgb;
40
+ }
41
+
42
+ fn xyz_to_rgb(xyz: vec3<f32>) -> vec3<f32> {
43
+ let m = mat3x3<f32>(
44
+ 3.2404542, -1.5371385, -0.4985314,
45
+ -0.9692660, 1.8760108, 0.0415560,
46
+ 0.0556434, -0.2040259, 1.0572252
47
+ );
48
+ return m * xyz;
49
+ }
50
+
51
+ fn temperature_to_xyz(temperature: f32) -> vec3<f32> {
52
+ let temp = temperature / 100.0;
53
+ var x: f32;
54
+ if (temp <= 66.0) {
55
+ x = 0.3;
56
+ } else {
57
+ x = 0.3 + 0.06 * pow((temp - 66.0) / 100.0, 2.5);
58
+ }
59
+
60
+ var y: f32;
61
+ if (temp <= 66.0) {
62
+ y = 0.2 + 0.1 * log(temp) / log(66.0);
63
+ } else {
64
+ y = 0.3;
65
+ }
66
+
67
+ let z = 1.0 - x - y;
68
+ return vec3<f32>(x, y, z);
69
+ }
70
+
71
+ @compute @workgroup_size(8, 8)
72
+ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
73
+ let dimensions = textureDimensions(input_texture);
74
+ let coord = vec2<i32>(global_id.xy);
75
+
76
+ if (coord.x >= dimensions.x || coord.y >= dimensions.y) {
77
+ return;
78
+ }
79
+
80
+ var color = textureLoad(input_texture, coord, 0).rgb;
81
+
82
+ // Convert to XYZ color space
83
+ var xyz = rgb_to_xyz(color);
84
+
85
+ // Apply color temperature adjustment
86
+ let target_xyz = temperature_to_xyz(params.temperature);
87
+ let reference_xyz = temperature_to_xyz(6500.0); // Reference D65 white point
88
+ xyz *= target_xyz / reference_xyz;
89
+
90
+ // Apply tint (green-magenta balance)
91
+ let tint_factor = 1.0 + params.tint / 100.0;
92
+ xyz.y *= tint_factor;
93
+
94
+ // Convert back to RGB
95
+ color = xyz_to_rgb(xyz);
96
+
97
+ // Ensure color values are within [0, 1] range
98
+ color = clamp(color, vec3<f32>(0.0), vec3<f32>(1.0));
99
+
100
+ textureStore(output_texture, coord, vec4<f32>(color, 1.0));
101
+ }
102
+ `,
103
+ }
src/experiments/grading/filters/crossProcessing.ts ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ColorGradingFilter } from '../types'
2
+
3
+ export const crossProcessing: ColorGradingFilter = {
4
+ name: 'Cross-Processing',
5
+ parameters: [
6
+ {
7
+ name: 'intensity',
8
+ description: 'Intensity of the cross-processing effect',
9
+ type: 'number',
10
+ minValue: 0,
11
+ maxValue: 1,
12
+ defaultValue: 0.5,
13
+ },
14
+ {
15
+ name: 'contrastBoost',
16
+ description: 'Amount of contrast boost',
17
+ type: 'number',
18
+ minValue: 0,
19
+ maxValue: 1,
20
+ defaultValue: 0.3,
21
+ },
22
+ {
23
+ name: 'colorShift',
24
+ description: 'Direction of color shift',
25
+ type: 'string',
26
+ allowedValues: ['Cool', 'Warm'],
27
+ defaultValue: 'Cool',
28
+ },
29
+ ],
30
+ shader: `
31
+ struct Params {
32
+ intensity: f32,
33
+ contrast_boost: f32,
34
+ color_shift: u32,
35
+ }
36
+
37
+ @group(0) @binding(0) var input_texture: texture_2d<f32>;
38
+ @group(0) @binding(1) var output_texture: texture_storage_2d<rgba8unorm, write>;
39
+ @group(0) @binding(2) var<uniform> params: Params;
40
+
41
+ fn rgb_to_hsv(rgb: vec3<f32>) -> vec3<f32> {
42
+ let v = max(max(rgb.r, rgb.g), rgb.b);
43
+ let c = v - min(min(rgb.r, rgb.g), rgb.b);
44
+ let s = select(0.0, c / v, v != 0.0);
45
+
46
+ var h: f32;
47
+ if (c == 0.0) {
48
+ h = 0.0;
49
+ } else if (v == rgb.r) {
50
+ h = (rgb.g - rgb.b) / c;
51
+ } else if (v == rgb.g) {
52
+ h = 2.0 + (rgb.b - rgb.r) / c;
53
+ } else {
54
+ h = 4.0 + (rgb.r - rgb.g) / c;
55
+ }
56
+ h = fract(h / 6.0);
57
+
58
+ return vec3<f32>(h, s, v);
59
+ }
60
+
61
+ fn hsv_to_rgb(hsv: vec3<f32>) -> vec3<f32> {
62
+ let h = hsv.x * 6.0;
63
+ let s = hsv.y;
64
+ let v = hsv.z;
65
+
66
+ let c = v * s;
67
+ let x = c * (1.0 - abs(fract(h / 2.0) * 2.0 - 1.0));
68
+ let m = v - c;
69
+
70
+ var rgb: vec3<f32>;
71
+ if (h < 1.0) {
72
+ rgb = vec3<f32>(c, x, 0.0);
73
+ } else if (h < 2.0) {
74
+ rgb = vec3<f32>(x, c, 0.0);
75
+ } else if (h < 3.0) {
76
+ rgb = vec3<f32>(0.0, c, x);
77
+ } else if (h < 4.0) {
78
+ rgb = vec3<f32>(0.0, x, c);
79
+ } else if (h < 5.0) {
80
+ rgb = vec3<f32>(x, 0.0, c);
81
+ } else {
82
+ rgb = vec3<f32>(c, 0.0, x);
83
+ }
84
+
85
+ return rgb + vec3<f32>(m);
86
+ }
87
+
88
+ @compute @workgroup_size(8, 8)
89
+ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
90
+ let dimensions = textureDimensions(input_texture);
91
+ let coord = vec2<i32>(global_id.xy);
92
+
93
+ if (coord.x >= dimensions.x || coord.y >= dimensions.y) {
94
+ return;
95
+ }
96
+
97
+ var color = textureLoad(input_texture, coord, 0).rgb;
98
+
99
+ // Convert to HSV
100
+ var hsv = rgb_to_hsv(color);
101
+
102
+ // Apply color shift
103
+ if (params.color_shift == 0u) { // Cool shift
104
+ hsv.x = fract(hsv.x - 0.1 * params.intensity);
105
+ } else { // Warm shift
106
+ hsv.x = fract(hsv.x + 0.1 * params.intensity);
107
+ }
108
+
109
+ // Increase saturation
110
+ hsv.y = clamp(hsv.y + 0.2 * params.intensity, 0.0, 1.0);
111
+
112
+ // Convert back to RGB
113
+ color = hsv_to_rgb(hsv);
114
+
115
+ // Apply contrast boost
116
+ color = (color - 0.5) * (1.0 + params.contrast_boost) + 0.5;
117
+
118
+ // Adjust individual channels for cross-processing look
119
+ color.r = clamp(color.r + 0.1 * params.intensity, 0.0, 1.0);
120
+ color.g = clamp(color.g - 0.05 * params.intensity, 0.0, 1.0);
121
+ color.b = clamp(color.b + 0.15 * params.intensity, 0.0, 1.0);
122
+
123
+ textureStore(output_texture, coord, vec4<f32>(color, 1.0));
124
+ }
125
+ `,
126
+ }
src/experiments/grading/filters/filmDegradation.ts ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ColorGradingFilter } from '../types'
2
+
3
+ export const filmDegradation: ColorGradingFilter = {
4
+ name: 'Film Degradation',
5
+ parameters: [
6
+ {
7
+ name: 'scratchesIntensity',
8
+ description: 'Intensity of film scratches',
9
+ type: 'number',
10
+ minValue: 0,
11
+ maxValue: 1,
12
+ defaultValue: 0.3,
13
+ },
14
+ {
15
+ name: 'dustIntensity',
16
+ description: 'Intensity of dust and spots',
17
+ type: 'number',
18
+ minValue: 0,
19
+ maxValue: 1,
20
+ defaultValue: 0.2,
21
+ },
22
+ {
23
+ name: 'colorFading',
24
+ description: 'Color fading effect',
25
+ type: 'number',
26
+ minValue: 0,
27
+ maxValue: 1,
28
+ defaultValue: 0.3,
29
+ },
30
+ {
31
+ name: 'lightLeakIntensity',
32
+ description: 'Intensity of light leaks',
33
+ type: 'number',
34
+ minValue: 0,
35
+ maxValue: 1,
36
+ defaultValue: 0.2,
37
+ },
38
+ ],
39
+ shader: `
40
+ struct Params {
41
+ scratches_intensity: f32,
42
+ dust_intensity: f32,
43
+ color_fading: f32,
44
+ light_leak_intensity: f32,
45
+ }
46
+
47
+ @group(0) @binding(0) var input_texture: texture_2d<f32>;
48
+ @group(0) @binding(1) var output_texture: texture_storage_2d<rgba8unorm, write>;
49
+ @group(0) @binding(2) var<uniform> params: Params;
50
+
51
+ fn rand(co: vec2<f32>) -> f32 {
52
+ return fract(sin(dot(co, vec2<f32>(12.9898, 78.233))) * 43758.5453);
53
+ }
54
+
55
+ fn noise(p: vec2<f32>) -> f32 {
56
+ let ip = floor(p);
57
+ let u = fract(p);
58
+ let u2 = u * u * (3.0 - 2.0 * u);
59
+
60
+ let n00 = rand(ip);
61
+ let n01 = rand(ip + vec2<f32>(0.0, 1.0));
62
+ let n10 = rand(ip + vec2<f32>(1.0, 0.0));
63
+ let n11 = rand(ip + vec2<f32>(1.0, 1.0));
64
+
65
+ return mix(mix(n00, n10, u2.x), mix(n01, n11, u2.x), u2.y);
66
+ }
67
+
68
+ @compute @workgroup_size(8, 8)
69
+ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
70
+ let dimensions = textureDimensions(input_texture);
71
+ let coord = vec2<i32>(global_id.xy);
72
+
73
+ if (coord.x >= dimensions.x || coord.y >= dimensions.y) {
74
+ return;
75
+ }
76
+
77
+ var color = textureLoad(input_texture, coord, 0).rgb;
78
+
79
+ // Apply color fading
80
+ color = mix(color, vec3<f32>(0.5), params.color_fading);
81
+
82
+ // Apply scratches
83
+ let scratch = noise(vec2<f32>(coord.y * 0.1, 0.0));
84
+ if (scratch > 1.0 - params.scratches_intensity * 0.1) {
85
+ color += vec3<f32>(0.1);
86
+ }
87
+
88
+ // Apply dust and spots
89
+ let dust = noise(vec2<f32>(coord) * 0.02);
90
+ if (dust < params.dust_intensity * 0.2) {
91
+ color -= vec3<f32>(0.1);
92
+ }
93
+
94
+ // Apply light leak
95
+ let leak = noise(vec2<f32>(coord) * 0.005);
96
+ color += vec3<f32>(1.0, 0.5, 0.0) * leak * params.light_leak_intensity;
97
+
98
+ // Ensure color values are within [0, 1] range
99
+ color = clamp(color, vec3<f32>(0.0), vec3<f32>(1.0));
100
+
101
+ textureStore(output_texture, coord, vec4<f32>(color, 1.0));
102
+ }
103
+ `,
104
+ }
src/experiments/grading/filters/infrared.ts ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ColorGradingFilter } from '../types'
2
+
3
+ export const infraredBlackAndWhite: ColorGradingFilter = {
4
+ name: 'Infrared Black and White',
5
+ parameters: [
6
+ {
7
+ name: 'contrast',
8
+ description: 'Image contrast',
9
+ type: 'number',
10
+ minValue: 0.5,
11
+ maxValue: 2.0,
12
+ defaultValue: 1.2,
13
+ },
14
+ {
15
+ name: 'grain',
16
+ description: 'Film grain intensity',
17
+ type: 'number',
18
+ minValue: 0,
19
+ maxValue: 1,
20
+ defaultValue: 0.2,
21
+ },
22
+ {
23
+ name: 'glow',
24
+ description: 'Infrared glow effect',
25
+ type: 'number',
26
+ minValue: 0,
27
+ maxValue: 1,
28
+ defaultValue: 0.3,
29
+ },
30
+ ],
31
+ shader: `
32
+ struct Params {
33
+ contrast: f32,
34
+ grain: f32,
35
+ glow: f32,
36
+ }
37
+
38
+ @group(0) @binding(0) var input_texture: texture_2d<f32>;
39
+ @group(0) @binding(1) var output_texture: texture_storage_2d<rgba8unorm, write>;
40
+ @group(0) @binding(2) var<uniform> params: Params;
41
+
42
+ fn rand(co: vec2<f32>) -> f32 {
43
+ return fract(sin(dot(co, vec2<f32>(12.9898, 78.233))) * 43758.5453);
44
+ }
45
+
46
+ @compute @workgroup_size(8, 8)
47
+ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
48
+ let dimensions = textureDimensions(input_texture);
49
+ let coord = vec2<i32>(global_id.xy);
50
+
51
+ if (coord.x >= dimensions.x || coord.y >= dimensions.y) {
52
+ return;
53
+ }
54
+
55
+ var color = textureLoad(input_texture, coord, 0).rgb;
56
+
57
+ // Convert to infrared-like grayscale
58
+ let ir_gray = dot(color, vec3<f32>(0.2, 0.7, 0.1));
59
+
60
+ // Apply contrast
61
+ let contrasted = (ir_gray - 0.5) * params.contrast + 0.5;
62
+
63
+ // Apply glow effect
64
+ var glow_sum = vec3<f32>(0.0);
65
+ let glow_radius = 5;
66
+ for (var i = -glow_radius; i <= glow_radius; i++) {
67
+ for (var j = -glow_radius; j <= glow_radius; j++) {
68
+ let sample_coord = coord + vec2<i32>(i, j);
69
+ if (sample_coord.x >= 0 && sample_coord.x < dimensions.x &&
70
+ sample_coord.y >= 0 && sample_coord.y < dimensions.y) {
71
+ let sample = textureLoad(input_texture, sample_coord, 0).rgb;
72
+ let sample_gray = dot(sample, vec3<f32>(0.2, 0.7, 0.1));
73
+ glow_sum += vec3<f32>(sample_gray);
74
+ }
75
+ }
76
+ }
77
+ let glow_avg = glow_sum / f32((2 * glow_radius + 1) * (2 * glow_radius + 1));
78
+ let glowed = mix(vec3<f32>(contrasted), glow_avg, params.glow);
79
+
80
+ // Apply grain
81
+ let grain = (rand(vec2<f32>(coord)) - 0.5) * params.grain;
82
+ let final_color = clamp(glowed + grain, vec3<f32>(0.0), vec3<f32>(1.0));
83
+
84
+ textureStore(output_texture, coord, vec4<f32>(final_color, 1.0));
85
+ }
86
+ `,
87
+ }
src/experiments/grading/filters/lomography.ts ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ColorGradingFilter } from '../types'
2
+
3
+ export const lomography: ColorGradingFilter = {
4
+ name: 'Lomography',
5
+ parameters: [
6
+ {
7
+ name: 'saturation',
8
+ description: 'Color saturation',
9
+ type: 'number',
10
+ minValue: 0,
11
+ maxValue: 2,
12
+ defaultValue: 1.3,
13
+ },
14
+ {
15
+ name: 'contrast',
16
+ description: 'Image contrast',
17
+ type: 'number',
18
+ minValue: 0.5,
19
+ maxValue: 2,
20
+ defaultValue: 1.2,
21
+ },
22
+ {
23
+ name: 'vignetteIntensity',
24
+ description: 'Intensity of vignette effect',
25
+ type: 'number',
26
+ minValue: 0,
27
+ maxValue: 1,
28
+ defaultValue: 0.5,
29
+ },
30
+ {
31
+ name: 'lightLeakIntensity',
32
+ description: 'Intensity of light leak effect',
33
+ type: 'number',
34
+ minValue: 0,
35
+ maxValue: 1,
36
+ defaultValue: 0.3,
37
+ },
38
+ ],
39
+ shader: `
40
+ struct Params {
41
+ saturation: f32,
42
+ contrast: f32,
43
+ vignette_intensity: f32,
44
+ light_leak_intensity: f32,
45
+ }
46
+
47
+ @group(0) @binding(0) var input_texture: texture_2d<f32>;
48
+ @group(0) @binding(1) var output_texture: texture_storage_2d<rgba8unorm, write>;
49
+ @group(0) @binding(2) var<uniform> params: Params;
50
+
51
+ fn rgb_to_hsv(rgb: vec3<f32>) -> vec3<f32> {
52
+ let v = max(max(rgb.r, rgb.g), rgb.b);
53
+ let c = v - min(min(rgb.r, rgb.g), rgb.b);
54
+ let s = select(0.0, c / v, v != 0.0);
55
+
56
+ var h: f32;
57
+ if (c == 0.0) {
58
+ h = 0.0;
59
+ } else if (v == rgb.r) {
60
+ h = (rgb.g - rgb.b) / c;
61
+ } else if (v == rgb.g) {
62
+ h = 2.0 + (rgb.b - rgb.r) / c;
63
+ } else {
64
+ h = 4.0 + (rgb.r - rgb.g) / c;
65
+ }
66
+ h = fract(h / 6.0);
67
+
68
+ return vec3<f32>(h, s, v);
69
+ }
70
+
71
+ fn hsv_to_rgb(hsv: vec3<f32>) -> vec3<f32> {
72
+ let h = hsv.x * 6.0;
73
+ let s = hsv.y;
74
+ let v = hsv.z;
75
+
76
+ let c = v * s;
77
+ let x = c * (1.0 - abs(fract(h / 2.0) * 2.0 - 1.0));
78
+ let m = v - c;
79
+
80
+ var rgb: vec3<f32>;
81
+ if (h < 1.0) {
82
+ rgb = vec3<f32>(c, x, 0.0);
83
+ } else if (h < 2.0) {
84
+ rgb = vec3<f32>(x, c, 0.0);
85
+ } else if (h < 3.0) {
86
+ rgb = vec3<f32>(0.0, c, x);
87
+ } else if (h < 4.0) {
88
+ rgb = vec3<f32>(0.0, x, c);
89
+ } else if (h < 5.0) {
90
+ rgb = vec3<f32>(x, 0.0, c);
91
+ } else {
92
+ rgb = vec3<f32>(c, 0.0, x);
93
+ }
94
+
95
+ return rgb + vec3<f32>(m);
96
+ }
97
+
98
+ fn rand(co: vec2<f32>) -> f32 {
99
+ return fract(sin(dot(co, vec2<f32>(12.9898, 78.233))) * 43758.5453);
100
+ }
101
+
102
+ @compute @workgroup_size(8, 8)
103
+ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
104
+ let dimensions = textureDimensions(input_texture);
105
+ let coord = vec2<i32>(global_id.xy);
106
+
107
+ if (coord.x >= dimensions.x || coord.y >= dimensions.y) {
108
+ return;
109
+ }
110
+
111
+ var color = textureLoad(input_texture, coord, 0).rgb;
112
+
113
+ // Convert to HSV
114
+ var hsv = rgb_to_hsv(color);
115
+
116
+ // Increase saturation
117
+ hsv.y = clamp(hsv.y * params.saturation, 0.0, 1.0);
118
+
119
+ // Convert back to RGB
120
+ color = hsv_to_rgb(hsv);
121
+
122
+ // Apply contrast
123
+ color = (color - 0.5) * params.contrast + 0.5;
124
+
125
+ // Apply vignette
126
+ let center = vec2<f32>(0.5, 0.5);
127
+ let uv = vec2<f32>(coord) / vec2<f32>(dimensions);
128
+ let dist = distance(uv, center);
129
+ let vignette = 1.0 - smoothstep(0.3, 0.7, dist * params.vignette_intensity);
130
+ color *= vignette;
131
+
132
+ // Apply light leak
133
+ let leak = rand(uv * 10.0);
134
+ let leak_color = vec3<f32>(1.0, 0.5, 0.2); // Warm light leak color
135
+ color = mix(color, leak_color, leak * params.light_leak_intensity);
136
+
137
+ // Ensure color values are within [0, 1] range
138
+ color = clamp(color, vec3<f32>(0.0), vec3<f32>(1.0));
139
+
140
+ textureStore(output_texture, coord, vec4<f32>(color, 1.0));
141
+ }
142
+ `,
143
+ }
src/experiments/grading/filters/splitToning.ts ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ColorGradingFilter } from '../types'
2
+
3
+ export const splitToning: ColorGradingFilter = {
4
+ name: 'Split Toning',
5
+ parameters: [
6
+ {
7
+ name: 'highlightColor',
8
+ description: 'Color for highlights',
9
+ type: 'string',
10
+ allowedValues: ['Red', 'Green', 'Blue', 'Yellow', 'Cyan', 'Magenta'],
11
+ defaultValue: 'Yellow',
12
+ },
13
+ {
14
+ name: 'shadowColor',
15
+ description: 'Color for shadows',
16
+ type: 'string',
17
+ allowedValues: ['Red', 'Green', 'Blue', 'Yellow', 'Cyan', 'Magenta'],
18
+ defaultValue: 'Blue',
19
+ },
20
+ {
21
+ name: 'balance',
22
+ description: 'Balance between highlights and shadows',
23
+ type: 'number',
24
+ minValue: -1,
25
+ maxValue: 1,
26
+ defaultValue: 0,
27
+ },
28
+ {
29
+ name: 'intensity',
30
+ description: 'Intensity of the split toning effect',
31
+ type: 'number',
32
+ minValue: 0,
33
+ maxValue: 1,
34
+ defaultValue: 0.5,
35
+ },
36
+ ],
37
+ shader: `
38
+ struct Params {
39
+ highlight_color: u32,
40
+ shadow_color: u32,
41
+ balance: f32,
42
+ intensity: f32,
43
+ }
44
+
45
+ @group(0) @binding(0) var input_texture: texture_2d<f32>;
46
+ @group(0) @binding(1) var output_texture: texture_storage_2d<rgba8unorm, write>;
47
+ @group(0) @binding(2) var<uniform> params: Params;
48
+
49
+ fn get_color(color_index: u32) -> vec3<f32> {
50
+ switch color_index {
51
+ case 0u: { return vec3<f32>(1.0, 0.0, 0.0); } // Red
52
+ case 1u: { return vec3<f32>(0.0, 1.0, 0.0); } // Green
53
+ case 2u: { return vec3<f32>(0.0, 0.0, 1.0); } // Blue
54
+ case 3u: { return vec3<f32>(1.0, 1.0, 0.0); } // Yellow
55
+ case 4u: { return vec3<f32>(0.0, 1.0, 1.0); } // Cyan
56
+ case 5u: { return vec3<f32>(1.0, 0.0, 1.0); } // Magenta
57
+ default: { return vec3<f32>(1.0); } // White
58
+ }
59
+ }
60
+
61
+ fn rgb_to_hsv(rgb: vec3<f32>) -> vec3<f32> {
62
+ let v = max(max(rgb.r, rgb.g), rgb.b);
63
+ let c = v - min(min(rgb.r, rgb.g), rgb.b);
64
+ let s = select(0.0, c / v, v != 0.0);
65
+
66
+ var h: f32;
67
+ if (c == 0.0) {
68
+ h = 0.0;
69
+ } else if (v == rgb.r) {
70
+ h = (rgb.g - rgb.b) / c;
71
+ } else if (v == rgb.g) {
72
+ h = 2.0 + (rgb.b - rgb.r) / c;
73
+ } else {
74
+ h = 4.0 + (rgb.r - rgb.g) / c;
75
+ }
76
+ h = fract(h / 6.0);
77
+
78
+ return vec3<f32>(h, s, v);
79
+ }
80
+
81
+ fn hsv_to_rgb(hsv: vec3<f32>) -> vec3<f32> {
82
+ let h = hsv.x * 6.0;
83
+ let s = hsv.y;
84
+ let v = hsv.z;
85
+
86
+ let c = v * s;
87
+ let x = c * (1.0 - abs(fract(h / 2.0) * 2.0 - 1.0));
88
+ let m = v - c;
89
+
90
+ var rgb: vec3<f32>;
91
+ if (h < 1.0) {
92
+ rgb = vec3<f32>(c, x, 0.0);
93
+ } else if (h < 2.0) {
94
+ rgb = vec3<f32>(x, c, 0.0);
95
+ } else if (h < 3.0) {
96
+ rgb = vec3<f32>(0.0, c, x);
97
+ } else if (h < 4.0) {
98
+ rgb = vec3<f32>(0.0, x, c);
99
+ } else if (h < 5.0) {
100
+ rgb = vec3<f32>(x, 0.0, c);
101
+ } else {
102
+ rgb = vec3<f32>(c, 0.0, x);
103
+ }
104
+
105
+ return rgb + vec3<f32>(m);
106
+ }
107
+
108
+ @compute @workgroup_size(8, 8)
109
+ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
110
+ let dimensions = textureDimensions(input_texture);
111
+ let coord = vec2<i32>(global_id.xy);
112
+
113
+ if (coord.x >= dimensions.x || coord.y >= dimensions.y) {
114
+ return;
115
+ }
116
+
117
+ var color = textureLoad(input_texture, coord, 0).rgb;
118
+
119
+ // Convert to HSV
120
+ var hsv = rgb_to_hsv(color);
121
+
122
+ let highlight_color = get_color(params.highlight_color);
123
+ let shadow_color = get_color(params.shadow_color);
124
+
125
+ // Calculate toning based on luminance and balance
126
+ let lum = dot(color, vec3<f32>(0.299, 0.587, 0.114));
127
+ let toning_factor = smoothstep(0.0, 1.0, lum + params.balance);
128
+ let toning_color = mix(shadow_color, highlight_color, toning_factor);
129
+
130
+ // Apply split toning
131
+ hsv.x = mix(hsv.x, rgb_to_hsv(toning_color).x, params.intensity * (1.0 - hsv.y));
132
+ hsv.y = mix(hsv.y, rgb_to_hsv(toning_color).y, params.intensity * 0.3);
133
+
134
+ // Convert back to RGB
135
+ color = hsv_to_rgb(hsv);
136
+
137
+ // Ensure color values are within [0, 1] range
138
+ color = clamp(color, vec3<f32>(0.0), vec3<f32>(1.0));
139
+
140
+ textureStore(output_texture, coord, vec4<f32>(color, 1.0));
141
+ }
142
+ `,
143
+ }
src/experiments/grading/filters/toneMapping.ts ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ColorGradingFilter } from '../types'
2
+
3
+ export const hdrToneMapping: ColorGradingFilter = {
4
+ name: 'HDR Tone Mapping',
5
+ parameters: [
6
+ {
7
+ name: 'exposure',
8
+ description: 'Exposure adjustment',
9
+ type: 'number',
10
+ minValue: -2,
11
+ maxValue: 2,
12
+ defaultValue: 0,
13
+ },
14
+ {
15
+ name: 'contrast',
16
+ description: 'Contrast adjustment',
17
+ type: 'number',
18
+ minValue: 0.5,
19
+ maxValue: 2,
20
+ defaultValue: 1,
21
+ },
22
+ {
23
+ name: 'saturation',
24
+ description: 'Color saturation',
25
+ type: 'number',
26
+ minValue: 0,
27
+ maxValue: 2,
28
+ defaultValue: 1,
29
+ },
30
+ {
31
+ name: 'highlights',
32
+ description: 'Highlight adjustment',
33
+ type: 'number',
34
+ minValue: -1,
35
+ maxValue: 1,
36
+ defaultValue: 0,
37
+ },
38
+ {
39
+ name: 'shadows',
40
+ description: 'Shadow adjustment',
41
+ type: 'number',
42
+ minValue: -1,
43
+ maxValue: 1,
44
+ defaultValue: 0,
45
+ },
46
+ ],
47
+ shader: `
48
+ struct Params {
49
+ exposure: f32,
50
+ contrast: f32,
51
+ saturation: f32,
52
+ highlights: f32,
53
+ shadows: f32,
54
+ }
55
+
56
+ @group(0) @binding(0) var input_texture: texture_2d<f32>;
57
+ @group(0) @binding(1) var output_texture: texture_storage_2d<rgba8unorm, write>;
58
+ @group(0) @binding(2) var<uniform> params: Params;
59
+
60
+ fn rgb_to_hsv(rgb: vec3<f32>) -> vec3<f32> {
61
+ let v = max(max(rgb.r, rgb.g), rgb.b);
62
+ let c = v - min(min(rgb.r, rgb.g), rgb.b);
63
+ let s = select(0.0, c / v, v != 0.0);
64
+
65
+ var h: f32;
66
+ if (c == 0.0) {
67
+ h = 0.0;
68
+ } else if (v == rgb.r) {
69
+ h = (rgb.g - rgb.b) / c;
70
+ } else if (v == rgb.g) {
71
+ h = 2.0 + (rgb.b - rgb.r) / c;
72
+ } else {
73
+ h = 4.0 + (rgb.r - rgb.g) / c;
74
+ }
75
+ h = fract(h / 6.0);
76
+
77
+ return vec3<f32>(h, s, v);
78
+ }
79
+
80
+ fn hsv_to_rgb(hsv: vec3<f32>) -> vec3<f32> {
81
+ let h = hsv.x * 6.0;
82
+ let s = hsv.y;
83
+ let v = hsv.z;
84
+
85
+ let c = v * s;
86
+ let x = c * (1.0 - abs(fract(h / 2.0) * 2.0 - 1.0));
87
+ let m = v - c;
88
+
89
+ var rgb: vec3<f32>;
90
+ if (h < 1.0) {
91
+ rgb = vec3<f32>(c, x, 0.0);
92
+ } else if (h < 2.0) {
93
+ rgb = vec3<f32>(x, c, 0.0);
94
+ } else if (h < 3.0) {
95
+ rgb = vec3<f32>(0.0, c, x);
96
+ } else if (h < 4.0) {
97
+ rgb = vec3<f32>(0.0, x, c);
98
+ } else if (h < 5.0) {
99
+ rgb = vec3<f32>(x, 0.0, c);
100
+ } else {
101
+ rgb = vec3<f32>(c, 0.0, x);
102
+ }
103
+
104
+ return rgb + vec3<f32>(m);
105
+ }
106
+
107
+ fn reinhard_tone_mapping(hdr: vec3<f32>) -> vec3<f32> {
108
+ return hdr / (hdr + 1.0);
109
+ }
110
+
111
+ @compute @workgroup_size(8, 8)
112
+ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
113
+ let dimensions = textureDimensions(input_texture);
114
+ let coord = vec2<i32>(global_id.xy);
115
+
116
+ if (coord.x >= dimensions.x || coord.y >= dimensions.y) {
117
+ return;
118
+ }
119
+
120
+ var color = textureLoad(input_texture, coord, 0).rgb;
121
+
122
+ // Apply exposure
123
+ color *= exp2(params.exposure);
124
+
125
+ // Apply contrast
126
+ color = pow(color, vec3<f32>(params.contrast));
127
+
128
+ // Apply highlights and shadows adjustments
129
+ let luminance = dot(color, vec3<f32>(0.299, 0.587, 0.114));
130
+ let shadow_adjust = 1.0 + params.shadows * (1.0 - luminance);
131
+ let highlight_adjust = 1.0 - params.highlights * luminance;
132
+ color *= shadow_adjust * highlight_adjust;
133
+
134
+ // Apply HDR tone mapping
135
+ color = reinhard_tone_mapping(color);
136
+
137
+ // Adjust saturation
138
+ var hsv = rgb_to_hsv(color);
139
+ hsv.y *= params.saturation;
140
+ color = hsv_to_rgb(hsv);
141
+
142
+ // Ensure color values are within [0, 1] range
143
+ color = clamp(color, vec3<f32>(0.0), vec3<f32>(1.0));
144
+
145
+ textureStore(output_texture, coord, vec4<f32>(color, 1.0));
146
+ }
147
+ `,
148
+ }
src/experiments/grading/filters/vintageFilm.ts ADDED
@@ -0,0 +1,299 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ColorGradingFilter } from '../types'
2
+
3
+ export const vintageFilm: ColorGradingFilter = {
4
+ name: 'Enhanced Vintage Film Stocks',
5
+ parameters: [
6
+ {
7
+ name: 'preset',
8
+ description: 'Vintage film stock preset',
9
+ type: 'string',
10
+ allowedValues: [
11
+ // Kodak films
12
+ 'Kodachrome 64',
13
+ 'Ektachrome 100',
14
+ 'Kodacolor 200',
15
+ 'Portra 400',
16
+ 'Tri-X 400',
17
+ 'Kodachrome 25',
18
+ 'Plus-X 125',
19
+ 'T-Max 400',
20
+ // Fujifilm
21
+ 'Fujicolor Pro 400H',
22
+ 'Velvia 50',
23
+ 'Provia 100F',
24
+ 'Superia 200',
25
+ 'Neopan 400',
26
+ // Ilford
27
+ 'HP5 Plus',
28
+ 'FP4 Plus',
29
+ 'Delta 3200',
30
+ // Agfa
31
+ 'Vista 200',
32
+ 'Ultra 50',
33
+ 'Scala 200X',
34
+ // Konica
35
+ 'Centuria 400',
36
+ 'VX 400',
37
+ // Other brands
38
+ 'CineStill 800T',
39
+ 'Polaroid 600',
40
+ 'Polaroid SX-70',
41
+ // Exotic and old formats
42
+ 'Autochrome Lumière',
43
+ 'Daguerreotype',
44
+ 'Cyanotype',
45
+ 'Tintype',
46
+ 'Technicolor',
47
+ 'Kodachrome II (1961)',
48
+ ],
49
+ defaultValue: 'Kodachrome 64',
50
+ },
51
+ {
52
+ name: 'intensity',
53
+ description: 'Intensity of the film stock effect',
54
+ type: 'number',
55
+ minValue: 0,
56
+ maxValue: 1,
57
+ defaultValue: 0.8,
58
+ },
59
+ {
60
+ name: 'grain',
61
+ description: 'Film grain intensity',
62
+ type: 'number',
63
+ minValue: 0,
64
+ maxValue: 1,
65
+ defaultValue: 0.2,
66
+ },
67
+ {
68
+ name: 'ageEffect',
69
+ description: 'Simulated age of the film',
70
+ type: 'number',
71
+ minValue: 0,
72
+ maxValue: 1,
73
+ defaultValue: 0,
74
+ },
75
+ {
76
+ name: 'colorShift',
77
+ description: 'Color shift adjustment',
78
+ type: 'number',
79
+ minValue: -1,
80
+ maxValue: 1,
81
+ defaultValue: 0,
82
+ },
83
+ {
84
+ name: 'contrast',
85
+ description: 'Contrast adjustment',
86
+ type: 'number',
87
+ minValue: 0.5,
88
+ maxValue: 2,
89
+ defaultValue: 1,
90
+ },
91
+ {
92
+ name: 'saturation',
93
+ description: 'Saturation adjustment',
94
+ type: 'number',
95
+ minValue: 0,
96
+ maxValue: 2,
97
+ defaultValue: 1,
98
+ },
99
+ ],
100
+ shader: `
101
+ struct Params {
102
+ preset: u32,
103
+ intensity: f32,
104
+ grain: f32,
105
+ age_effect: f32,
106
+ color_shift: f32,
107
+ contrast: f32,
108
+ saturation: f32,
109
+ }
110
+
111
+ @group(0) @binding(0) var input_texture: texture_2d<f32>;
112
+ @group(0) @binding(1) var output_texture: texture_storage_2d<rgba8unorm, write>;
113
+ @group(0) @binding(2) var<uniform> params: Params;
114
+
115
+ fn rand(co: vec2<f32>) -> f32 {
116
+ return fract(sin(dot(co, vec2<f32>(12.9898, 78.233))) * 43758.5453);
117
+ }
118
+
119
+ fn rgb_to_hsv(rgb: vec3<f32>) -> vec3<f32> {
120
+ let v = max(max(rgb.r, rgb.g), rgb.b);
121
+ let c = v - min(min(rgb.r, rgb.g), rgb.b);
122
+ let s = select(0.0, c / v, v != 0.0);
123
+
124
+ var h: f32;
125
+ if (c == 0.0) {
126
+ h = 0.0;
127
+ } else if (v == rgb.r) {
128
+ h = (rgb.g - rgb.b) / c;
129
+ } else if (v == rgb.g) {
130
+ h = 2.0 + (rgb.b - rgb.r) / c;
131
+ } else {
132
+ h = 4.0 + (rgb.r - rgb.g) / c;
133
+ }
134
+ h = fract(h / 6.0);
135
+
136
+ return vec3<f32>(h, s, v);
137
+ }
138
+
139
+ fn hsv_to_rgb(hsv: vec3<f32>) -> vec3<f32> {
140
+ let h = hsv.x * 6.0;
141
+ let s = hsv.y;
142
+ let v = hsv.z;
143
+
144
+ let c = v * s;
145
+ let x = c * (1.0 - abs(fract(h / 2.0) * 2.0 - 1.0));
146
+ let m = v - c;
147
+
148
+ var rgb: vec3<f32>;
149
+ if (h < 1.0) {
150
+ rgb = vec3<f32>(c, x, 0.0);
151
+ } else if (h < 2.0) {
152
+ rgb = vec3<f32>(x, c, 0.0);
153
+ } else if (h < 3.0) {
154
+ rgb = vec3<f32>(0.0, c, x);
155
+ } else if (h < 4.0) {
156
+ rgb = vec3<f32>(0.0, x, c);
157
+ } else if (h < 5.0) {
158
+ rgb = vec3<f32>(x, 0.0, c);
159
+ } else {
160
+ rgb = vec3<f32>(c, 0.0, x);
161
+ }
162
+
163
+ return rgb + vec3<f32>(m);
164
+ }
165
+
166
+ fn apply_film_preset(color: vec3<f32>, preset: u32) -> vec3<f32> {
167
+ switch preset {
168
+ // Kodak films
169
+ case 0u: { return color * vec3<f32>(1.1, 1.0, 0.9) + vec3<f32>(0.0, 0.03, 0.07); } // Kodachrome 64
170
+ case 1u: { return color * vec3<f32>(1.0, 1.05, 1.1) + vec3<f32>(0.05, 0.0, -0.05); } // Ektachrome 100
171
+ case 2u: { return color * vec3<f32>(1.05, 1.0, 0.95) + vec3<f32>(0.02, 0.02, 0.0); } // Kodacolor 200
172
+ case 3u: { return color * vec3<f32>(1.1, 1.05, 1.0) + vec3<f32>(0.05, 0.05, 0.0); } // Portra 400
173
+ case 4u: { // Tri-X 400
174
+ let bw = dot(color, vec3<f32>(0.299, 0.587, 0.114));
175
+ return vec3<f32>(bw * 1.1);
176
+ }
177
+ case 5u: { return color * vec3<f32>(1.2, 1.1, 0.9) + vec3<f32>(-0.05, 0.05, 0.1); } // Kodachrome 25
178
+ case 6u: { // Plus-X 125
179
+ let bw = dot(color, vec3<f32>(0.299, 0.587, 0.114));
180
+ return vec3<f32>(bw * 1.05 + 0.02);
181
+ }
182
+ case 7u: { // T-Max 400
183
+ let bw = dot(color, vec3<f32>(0.299, 0.587, 0.114));
184
+ return vec3<f32>(bw * 1.15 - 0.05);
185
+ }
186
+ // Fujifilm
187
+ case 8u: { return color * vec3<f32>(1.05, 1.1, 1.15) + vec3<f32>(0.1, 0.0, 0.1); } // Fujicolor Pro 400H
188
+ case 9u: { return color * vec3<f32>(1.2, 1.1, 1.0) + vec3<f32>(0.0, 0.1, 0.2); } // Velvia 50
189
+ case 10u: { return color * vec3<f32>(1.05, 1.05, 1.1) + vec3<f32>(0.05, 0.05, 0.0); } // Provia 100F
190
+ case 11u: { return color * vec3<f32>(1.1, 1.05, 0.95) + vec3<f32>(0.0, 0.05, 0.1); } // Superia 200
191
+ case 12u: { // Neopan 400
192
+ let bw = dot(color, vec3<f32>(0.299, 0.587, 0.114));
193
+ return vec3<f32>(bw * 1.1 - 0.03);
194
+ }
195
+ // Ilford
196
+ case 13u: { // HP5 Plus
197
+ let bw = dot(color, vec3<f32>(0.299, 0.587, 0.114));
198
+ return vec3<f32>(bw * 1.05 + 0.05);
199
+ }
200
+ case 14u: { // FP4 Plus
201
+ let bw = dot(color, vec3<f32>(0.299, 0.587, 0.114));
202
+ return vec3<f32>(bw * 1.02 + 0.02);
203
+ }
204
+ case 15u: { // Delta 3200
205
+ let bw = dot(color, vec3<f32>(0.299, 0.587, 0.114));
206
+ return vec3<f32>(bw * 1.2 - 0.1);
207
+ }
208
+ // Agfa
209
+ case 16u: { return color * vec3<f32>(1.05, 1.0, 0.95) + vec3<f32>(0.05, 0.0, -0.05); } // Vista 200
210
+ case 17u: { return color * vec3<f32>(1.1, 1.05, 0.9) + vec3<f32>(0.0, 0.05, 0.1); } // Ultra 50
211
+ case 18u: { // Scala 200X
212
+ let bw = dot(color, vec3<f32>(0.299, 0.587, 0.114));
213
+ return vec3<f32>(bw * 1.1 + 0.05);
214
+ }
215
+ // Konica
216
+ case 19u: { return color * vec3<f32>(1.05, 1.1, 1.0) + vec3<f32>(0.05, 0.0, 0.05); } // Centuria 400
217
+ case 20u: { return color * vec3<f32>(1.1, 1.05, 0.95) + vec3<f32>(0.0, 0.05, 0.1); } // VX 400
218
+ // Other brands
219
+ case 21u: { return color * vec3<f32>(1.1, 1.0, 1.2) + vec3<f32>(0.1, 0.0, -0.1); } // CineStill 800T
220
+ case 22u: { return color * vec3<f32>(1.15, 1.1, 1.0) + vec3<f32>(0.05, 0.0, -0.05); } // Polaroid 600
221
+ case 23u: { return color * vec3<f32>(1.2, 1.15, 0.9) + vec3<f32>(0.1, 0.05, -0.1); } // Polaroid SX-70
222
+ // Exotic and old formats
223
+ case 24u: { // Autochrome Lumière
224
+ var sepia = rgb_to_hsv(color);
225
+ sepia.x = 0.08; // Hue shift towards sepia
226
+ sepia.y *= 0.7; // Reduce saturation
227
+ return hsv_to_rgb(sepia) * vec3<f32>(1.1, 1.0, 0.8);
228
+ }
229
+ case 25u: { // Daguerreotype
230
+ let bw = dot(color, vec3<f32>(0.299, 0.587, 0.114));
231
+ return vec3<f32>(bw) * vec3<f32>(0.9, 1.0, 1.1) + vec3<f32>(0.1, 0.1, 0.1);
232
+ }
233
+ case 26u: { // Cyanotype
234
+ let bw = dot(color, vec3<f32>(0.299, 0.587, 0.114));
235
+ return vec3<f32>(0.2, 0.4, 0.6) + bw * vec3<f32>(0.1, 0.3, 0.5);
236
+ }
237
+ case 27u: { // Tintype
238
+ let bw = dot(color, vec3<f32>(0.299, 0.587, 0.114));
239
+ return vec3<f32>(bw) * vec3<f32>(0.8, 0.8, 0.9) + vec3<f32>(0.1, 0.1, 0.05);
240
+ }
241
+ case 28u: { // Technicolor
242
+ return color * vec3<f32>(1.3, 1.1, 1.0) + vec3<f32>(0.0, 0.1, 0.2);
243
+ }
244
+ case 29u: { // Kodachrome II (1961)
245
+ return color * vec3<f32>(1.2, 1.0, 0.8) + vec3<f32>(-0.05, 0.05, 0.15);
246
+ }
247
+ default: {
248
+ return color;
249
+ }
250
+ }
251
+ }
252
+
253
+ fn apply_age_effect(color: vec3<f32>, age: f32) -> vec3<f32> {
254
+ let sepia = vec3<f32>(1.2, 1.0, 0.8);
255
+ let aged = mix(color, color * sepia, age);
256
+ return mix(aged, aged * (1.0 - age * 0.2), age); // Slight fading
257
+ }
258
+
259
+ @compute @workgroup_size(8, 8)
260
+ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
261
+ let dimensions = textureDimensions(input_texture);
262
+ let coord = vec2<i32>(global_id.xy);
263
+
264
+ if (coord.x >= dimensions.x || coord.y >= dimensions.y) {
265
+ return;
266
+ }
267
+
268
+ var color = textureLoad(input_texture, coord, 0).rgb;
269
+
270
+ // Apply film preset
271
+ color = mix(color, apply_film_preset(color, params.preset), params.intensity);
272
+
273
+ // Apply contrast adjustment
274
+ color = pow(color, vec3<f32>(params.contrast));
275
+
276
+ // Apply color shift
277
+ var hsv = rgb_to_hsv(color);
278
+ hsv.x = fract(hsv.x + params.color_shift);
279
+ color = hsv_to_rgb(hsv);
280
+
281
+ // Apply saturation adjustment
282
+ hsv = rgb_to_hsv(color);
283
+ hsv.y *= params.saturation;
284
+ color = hsv_to_rgb(hsv);
285
+
286
+ // Apply age effect
287
+ color = apply_age_effect(color, params.age_effect);
288
+
289
+ // Apply film grain
290
+ let grain = (rand(vec2<f32>(coord)) - 0.5) * params.grain;
291
+ color += vec3<f32>(grain);
292
+
293
+ // Ensure color values are within [0, 1] range
294
+ color = clamp(color, vec3<f32>(0.0), vec3<f32>(1.0));
295
+
296
+ textureStore(output_texture, coord, vec4<f32>(color, 1.0));
297
+ }
298
+ `,
299
+ }
src/experiments/grading/types.ts ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export type ColorGradingParameter =
2
+ | {
3
+ name: string
4
+ description: string
5
+ type: 'number'
6
+ minValue: number
7
+ maxValue: number
8
+ defaultValue: number
9
+ }
10
+ | {
11
+ name: string
12
+ description: string
13
+ type: 'string'
14
+ allowedValues: string[]
15
+ defaultValue: string
16
+ }
17
+
18
+ export type ColorGradingFilter = {
19
+ name: string
20
+ parameters: Array<ColorGradingParameter>
21
+ shader: string // WGSL shader code for the filter
22
+ }
src/lib/utils/formatSegmentForExport.test.ts CHANGED
@@ -1,7 +1,12 @@
1
  import { expect, test } from 'vitest'
 
 
 
 
 
 
2
 
3
  import { formatSegmentForExport } from './formatSegmentForExport'
4
- import { newSegment } from '@aitube/clap'
5
 
6
  test('formatSegmentForExport', () => {
7
  expect(
@@ -33,7 +38,7 @@ test('formatSegmentForExport', () => {
33
  assetFileFormat: '',
34
  assetSourceType: 'EMPTY',
35
  assetUrl: '',
36
- category: 'generic',
37
  createdAt: '2024-07-13T19:30:13.387Z',
38
  createdBy: 'ai',
39
  editedBy: 'ai',
@@ -43,7 +48,7 @@ test('formatSegmentForExport', () => {
43
  id: '301a3e6f-cb59-4a85-afd6-4737eeeee356',
44
  label: '',
45
  outputGain: 0,
46
- outputType: 'text',
47
  prompt: '',
48
  renderId: '',
49
  revision: 0,
@@ -51,7 +56,7 @@ test('formatSegmentForExport', () => {
51
  seed: 7549327,
52
  startTimeInLines: 0,
53
  startTimeInMs: 0,
54
- status: 'to_generate',
55
  track: 0,
56
  },
57
  shortId: 'generic0',
 
1
  import { expect, test } from 'vitest'
2
+ import {
3
+ ClapOutputType,
4
+ ClapSegmentCategory,
5
+ ClapSegmentStatus,
6
+ newSegment,
7
+ } from '@aitube/clap'
8
 
9
  import { formatSegmentForExport } from './formatSegmentForExport'
 
10
 
11
  test('formatSegmentForExport', () => {
12
  expect(
 
38
  assetFileFormat: '',
39
  assetSourceType: 'EMPTY',
40
  assetUrl: '',
41
+ category: ClapSegmentCategory.GENERIC,
42
  createdAt: '2024-07-13T19:30:13.387Z',
43
  createdBy: 'ai',
44
  editedBy: 'ai',
 
48
  id: '301a3e6f-cb59-4a85-afd6-4737eeeee356',
49
  label: '',
50
  outputGain: 0,
51
+ outputType: ClapOutputType.TEXT,
52
  prompt: '',
53
  renderId: '',
54
  revision: 0,
 
56
  seed: 7549327,
57
  startTimeInLines: 0,
58
  startTimeInMs: 0,
59
+ status: ClapSegmentStatus.TO_GENERATE,
60
  track: 0,
61
  },
62
  shortId: 'generic0',
src/lib/utils/getTypeAndExtension.test.ts CHANGED
@@ -1,4 +1,5 @@
1
  import { expect, test } from 'vitest'
 
2
 
3
  import { getTypeAndExtension } from './getTypeAndExtension'
4
 
@@ -13,18 +14,18 @@ test('getTypeAndExtension', () => {
13
  assetFileFormat: 'image/gif',
14
  category: 'image',
15
  extension: 'gif',
16
- outputType: 'image',
17
  })
18
  expect(getTypeAndExtension(pngUri)).toStrictEqual({
19
  assetFileFormat: 'image/png',
20
  category: 'image',
21
  extension: 'png',
22
- outputType: 'image',
23
  })
24
  expect(getTypeAndExtension(mp4Uri)).toStrictEqual({
25
  assetFileFormat: 'video/mp4',
26
  category: 'video',
27
  extension: 'mp4',
28
- outputType: 'video',
29
  })
30
  })
 
1
  import { expect, test } from 'vitest'
2
+ import { ClapOutputType } from '@aitube/clap'
3
 
4
  import { getTypeAndExtension } from './getTypeAndExtension'
5
 
 
14
  assetFileFormat: 'image/gif',
15
  category: 'image',
16
  extension: 'gif',
17
+ outputType: ClapOutputType.IMAGE,
18
  })
19
  expect(getTypeAndExtension(pngUri)).toStrictEqual({
20
  assetFileFormat: 'image/png',
21
  category: 'image',
22
  extension: 'png',
23
+ outputType: ClapOutputType.IMAGE,
24
  })
25
  expect(getTypeAndExtension(mp4Uri)).toStrictEqual({
26
  assetFileFormat: 'video/mp4',
27
  category: 'video',
28
  extension: 'mp4',
29
+ outputType: ClapOutputType.VIDEO,
30
  })
31
  })
src/services/ui/theme.ts CHANGED
@@ -21,6 +21,7 @@ export const baseClapSegmentCategoryColors: ClapSegmentCategoryColors = {
21
  [ClapSegmentCategory.MESH]: { hue: 32, saturation: 30, lightness: 78.6 },
22
  [ClapSegmentCategory.DEPTH]: { hue: 242, saturation: 30, lightness: 78.6 },
23
  [ClapSegmentCategory.EVENT]: { hue: 270, saturation: 30, lightness: 78.6 },
 
24
  [ClapSegmentCategory.INTERFACE]: {
25
  hue: 216,
26
  saturation: 30,
@@ -78,14 +79,14 @@ export const backstage: UITheme = {
78
  defaultBgColor: '#1c1917',
79
  defaultTextColor: '#d6d3d1',
80
  defaultPrimaryColor: '#FACC15',
81
- defaultBorderColor: '#152639',
82
  logoColor: '#FACC15',
83
  editorBgColor: '#292524',
84
  editorCursorColor: '#f5f5f4',
85
  editorTextColor: '#d6d3d1',
86
  editorMenuBgColor: '#1c1917',
87
  editorMenuTextColor: 'd6d3d1',
88
- editorBorderColor: '#152639',
89
  monitorBgColor: '#1c1917',
90
  monitorSecondaryTextColor: '#D6D3D1',
91
  monitorPrimaryTextColor: '#FACC15',
@@ -565,6 +566,11 @@ export const silent: UITheme = {
565
  [ClapSegmentCategory.MESH]: { hue: 32, saturation: 0, lightness: 85 },
566
  [ClapSegmentCategory.DEPTH]: { hue: 242, saturation: 0, lightness: 85 },
567
  [ClapSegmentCategory.EVENT]: { hue: 270, saturation: 0, lightness: 85 },
 
 
 
 
 
568
  [ClapSegmentCategory.INTERFACE]: {
569
  hue: 216,
570
  saturation: 0,
 
21
  [ClapSegmentCategory.MESH]: { hue: 32, saturation: 30, lightness: 78.6 },
22
  [ClapSegmentCategory.DEPTH]: { hue: 242, saturation: 30, lightness: 78.6 },
23
  [ClapSegmentCategory.EVENT]: { hue: 270, saturation: 30, lightness: 78.6 },
24
+ [ClapSegmentCategory.EFFECT]: { hue: 270, saturation: 30, lightness: 78.6 },
25
  [ClapSegmentCategory.INTERFACE]: {
26
  hue: 216,
27
  saturation: 30,
 
79
  defaultBgColor: '#1c1917',
80
  defaultTextColor: '#d6d3d1',
81
  defaultPrimaryColor: '#FACC15',
82
+ defaultBorderColor: '#3e3a39',
83
  logoColor: '#FACC15',
84
  editorBgColor: '#292524',
85
  editorCursorColor: '#f5f5f4',
86
  editorTextColor: '#d6d3d1',
87
  editorMenuBgColor: '#1c1917',
88
  editorMenuTextColor: 'd6d3d1',
89
+ editorBorderColor: '#3e3a39',
90
  monitorBgColor: '#1c1917',
91
  monitorSecondaryTextColor: '#D6D3D1',
92
  monitorPrimaryTextColor: '#FACC15',
 
566
  [ClapSegmentCategory.MESH]: { hue: 32, saturation: 0, lightness: 85 },
567
  [ClapSegmentCategory.DEPTH]: { hue: 242, saturation: 0, lightness: 85 },
568
  [ClapSegmentCategory.EVENT]: { hue: 270, saturation: 0, lightness: 85 },
569
+ [ClapSegmentCategory.EFFECT]: {
570
+ hue: 270,
571
+ saturation: 0,
572
+ lightness: 85,
573
+ },
574
  [ClapSegmentCategory.INTERFACE]: {
575
  hue: 216,
576
  saturation: 0,
tsconfig.json CHANGED
@@ -19,7 +19,8 @@
19
  ],
20
  "paths": {
21
  "@/*": ["./src/*"]
22
- }
 
23
  },
24
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "vitest.config.mts"],
25
  "exclude": ["node_modules"]
 
19
  ],
20
  "paths": {
21
  "@/*": ["./src/*"]
22
+ },
23
+ "types": ["@webgpu/types", "@types/dom-speech-recognition"]
24
  },
25
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "vitest.config.mts"],
26
  "exclude": ["node_modules"]