@vibecuting/video-project-core 0.1.29 → 0.1.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/package.json +9 -5
  2. package/src/base/BaseRemotionScene.test.tsx +11 -1
  3. package/src/base/index.ts +1 -0
  4. package/src/base/utils/asset-source.ts +11 -0
  5. package/src/base/utils/background-audio-layer.tsx +90 -0
  6. package/src/base/utils/background-layer.tsx +84 -0
  7. package/src/base/utils/chapter-progress-foreground.tsx +125 -0
  8. package/src/base/utils/chapter-progress-state.test.ts +28 -0
  9. package/src/base/utils/chapter-progress-state.ts +33 -0
  10. package/src/base/utils/display-motion.test.ts +21 -0
  11. package/src/base/utils/display-motion.ts +52 -0
  12. package/src/base/utils/display-surface.ts +57 -0
  13. package/src/base/utils/index.ts +10 -0
  14. package/src/base/utils/subtitle-style.ts +28 -0
  15. package/src/base/utils/video-layer-types.test.ts +145 -0
  16. package/src/base/utils/video-layer-types.ts +220 -0
  17. package/src/base/utils/voice-captions-foreground.tsx +169 -0
  18. package/src/core/intro/index.ts +18 -18
  19. package/src/core/outro/index.ts +33 -33
  20. package/src/core/scene/2dscene/{default-2d-scene-Horizontal.stories.tsx → default-2d-scene/default-2d-scene-Horizontal.stories.tsx} +1 -1
  21. package/src/core/scene/2dscene/{default-2d-scene-Horizontal.tsx → default-2d-scene/default-2d-scene-Horizontal.tsx} +1 -1
  22. package/src/core/scene/2dscene/{default-2d-scene-Landscape.tsx → default-2d-scene/default-2d-scene-Landscape.tsx} +1 -1
  23. package/src/core/scene/2dscene/{default-2d-scene.stories.tsx → default-2d-scene/default-2d-scene.stories.tsx} +1 -1
  24. package/src/core/scene/2dscene/{default-2d-scene.tsx → default-2d-scene/default-2d-scene.tsx} +4 -4
  25. package/src/core/scene/2dscene/index.ts +3 -3
  26. package/src/core/scene/3dscene/{default-3d-scene-Horizontal.stories.tsx → default-3d-scene/default-3d-scene-Horizontal.stories.tsx} +1 -1
  27. package/src/core/scene/3dscene/{default-3d-scene-Horizontal.tsx → default-3d-scene/default-3d-scene-Horizontal.tsx} +1 -1
  28. package/src/core/scene/3dscene/{default-3d-scene-Landscape.tsx → default-3d-scene/default-3d-scene-Landscape.tsx} +1 -1
  29. package/src/core/scene/3dscene/{default-3d-scene.stories.tsx → default-3d-scene/default-3d-scene.stories.tsx} +1 -1
  30. package/src/core/scene/3dscene/{default-3d-scene.tsx → default-3d-scene/default-3d-scene.tsx} +4 -4
  31. package/src/core/scene/3dscene/index.ts +3 -3
  32. package/src/core/scene/html-in-canvas/browser/default-html-in-canvas-browser-scene-Horizontal.stories.tsx +35 -0
  33. package/src/core/scene/html-in-canvas/browser/default-html-in-canvas-browser-scene-Landscape.stories.tsx +80 -0
  34. package/src/core/scene/html-in-canvas/dashboard/default-html-in-canvas-dashboard-scene-Horizontal.stories.tsx +35 -0
  35. package/src/core/scene/html-in-canvas/dashboard/default-html-in-canvas-dashboard-scene-Landscape.stories.tsx +35 -0
  36. package/src/core/scene/html-in-canvas/dashboard-shell/default-dashboard-shell-html-in-canvas-scene.stories.tsx +40 -0
  37. package/src/core/scene/html-in-canvas/dashboard-shell/default-dashboard-shell-html-in-canvas-scene.tsx +44 -0
  38. package/src/core/scene/html-in-canvas/dashboard-shell/index.ts +8 -0
  39. package/src/core/scene/html-in-canvas/docs/default-html-in-canvas-docs-scene-Horizontal.stories.tsx +35 -0
  40. package/src/core/scene/html-in-canvas/docs/default-html-in-canvas-docs-scene-Landscape.stories.tsx +35 -0
  41. package/src/core/scene/html-in-canvas/document/article/default-article-html-in-canvas-scene.stories.tsx +38 -0
  42. package/src/core/scene/html-in-canvas/document/article/default-article-html-in-canvas-scene.tsx +50 -0
  43. package/src/core/scene/html-in-canvas/document/article/index.ts +8 -0
  44. package/src/core/scene/html-in-canvas/document/default-document-html-in-canvas-scene.stories.tsx +40 -0
  45. package/src/core/scene/html-in-canvas/document/default-document-html-in-canvas-scene.tsx +50 -0
  46. package/src/core/scene/html-in-canvas/document/index.ts +31 -0
  47. package/src/core/scene/html-in-canvas/document/report/default-report-html-in-canvas-scene.stories.tsx +38 -0
  48. package/src/core/scene/html-in-canvas/document/report/default-report-html-in-canvas-scene.tsx +51 -0
  49. package/src/core/scene/html-in-canvas/document/report/index.ts +8 -0
  50. package/src/core/scene/html-in-canvas/document/whitepaper/default-whitepaper-html-in-canvas-scene.stories.tsx +41 -0
  51. package/src/core/scene/html-in-canvas/document/whitepaper/default-whitepaper-html-in-canvas-scene.tsx +50 -0
  52. package/src/core/scene/html-in-canvas/document/whitepaper/index.ts +8 -0
  53. package/src/core/scene/html-in-canvas/editor/default-html-in-canvas-editor-scene-Horizontal.stories.tsx +35 -0
  54. package/src/core/scene/html-in-canvas/editor/default-html-in-canvas-editor-scene-Landscape.stories.tsx +35 -0
  55. package/src/core/scene/html-in-canvas/full-bleed/default-full-bleed-html-in-canvas-scene.stories.tsx +40 -0
  56. package/src/core/scene/html-in-canvas/full-bleed/default-full-bleed-html-in-canvas-scene.tsx +38 -0
  57. package/src/core/scene/html-in-canvas/full-bleed/index.ts +8 -0
  58. package/src/core/scene/html-in-canvas/index.ts +6 -0
  59. package/src/core/scene/html-in-canvas/landing-page/default-landing-page-html-in-canvas-scene.stories.tsx +40 -0
  60. package/src/core/scene/html-in-canvas/landing-page/default-landing-page-html-in-canvas-scene.tsx +46 -0
  61. package/src/core/scene/html-in-canvas/landing-page/feature-grid/default-feature-grid-html-in-canvas-scene.stories.tsx +38 -0
  62. package/src/core/scene/html-in-canvas/landing-page/feature-grid/default-feature-grid-html-in-canvas-scene.tsx +41 -0
  63. package/src/core/scene/html-in-canvas/landing-page/feature-grid/index.ts +8 -0
  64. package/src/core/scene/html-in-canvas/landing-page/hero/default-hero-html-in-canvas-scene.stories.tsx +38 -0
  65. package/src/core/scene/html-in-canvas/landing-page/hero/default-hero-html-in-canvas-scene.tsx +46 -0
  66. package/src/core/scene/html-in-canvas/landing-page/hero/index.ts +8 -0
  67. package/src/core/scene/html-in-canvas/landing-page/index.ts +31 -0
  68. package/src/core/scene/html-in-canvas/landing-page/pricing/default-pricing-html-in-canvas-scene.stories.tsx +38 -0
  69. package/src/core/scene/html-in-canvas/landing-page/pricing/default-pricing-html-in-canvas-scene.tsx +42 -0
  70. package/src/core/scene/html-in-canvas/landing-page/pricing/index.ts +8 -0
  71. package/src/core/scene/html-in-canvas/media-wall/collage/default-collage-html-in-canvas-scene.stories.tsx +38 -0
  72. package/src/core/scene/html-in-canvas/media-wall/collage/default-collage-html-in-canvas-scene.tsx +42 -0
  73. package/src/core/scene/html-in-canvas/media-wall/collage/index.ts +8 -0
  74. package/src/core/scene/html-in-canvas/media-wall/default-media-wall-html-in-canvas-scene.stories.tsx +40 -0
  75. package/src/core/scene/html-in-canvas/media-wall/default-media-wall-html-in-canvas-scene.tsx +35 -0
  76. package/src/core/scene/html-in-canvas/media-wall/gallery/default-gallery-html-in-canvas-scene.stories.tsx +38 -0
  77. package/src/core/scene/html-in-canvas/media-wall/gallery/default-gallery-html-in-canvas-scene.tsx +43 -0
  78. package/src/core/scene/html-in-canvas/media-wall/gallery/index.ts +8 -0
  79. package/src/core/scene/html-in-canvas/media-wall/grid/default-grid-html-in-canvas-scene.stories.tsx +38 -0
  80. package/src/core/scene/html-in-canvas/media-wall/grid/default-grid-html-in-canvas-scene.tsx +35 -0
  81. package/src/core/scene/html-in-canvas/media-wall/grid/index.ts +8 -0
  82. package/src/core/scene/html-in-canvas/media-wall/index.ts +31 -0
  83. package/src/core/scene/html-in-canvas/shared/default-html-in-canvas-scene.tsx +1315 -0
  84. package/src/core/scene/index.ts +1 -0
  85. package/src/core/scene/photo/3dvr-photo/{default-3dvr-photo-scene.stories.tsx → default-3dvr-photo-scene/default-3dvr-photo-scene.stories.tsx} +2 -2
  86. package/src/core/scene/photo/3dvr-photo/{default-3dvr-photo-scene.tsx → default-3dvr-photo-scene/default-3dvr-photo-scene.tsx} +4 -4
  87. package/src/core/scene/photo/3dvr-photo/{default-3dvr-photo-scene-Horizontal.stories.tsx → default-3dvr-photo-scene-Horizontal/default-3dvr-photo-scene-Horizontal.stories.tsx} +1 -1
  88. package/src/core/scene/photo/3dvr-photo/{default-3dvr-photo-scene-Horizontal.tsx → default-3dvr-photo-scene-Horizontal/default-3dvr-photo-scene-Horizontal.tsx} +4 -4
  89. package/src/core/scene/photo/3dvr-photo/{default-3dvr-photo-scene-Landscape.tsx → default-3dvr-photo-scene-Landscape/default-3dvr-photo-scene-Landscape.tsx} +4 -4
  90. package/src/core/scene/photo/3dvr-photo/default-dolly-3dvr-photo-scene/default-dolly-3dvr-photo-scene.stories.tsx +38 -0
  91. package/src/core/scene/photo/3dvr-photo/default-dolly-3dvr-photo-scene/default-dolly-3dvr-photo-scene.tsx +36 -0
  92. package/src/core/scene/photo/3dvr-photo/default-orbit-3dvr-photo-scene/default-orbit-3dvr-photo-scene.stories.tsx +38 -0
  93. package/src/core/scene/photo/3dvr-photo/default-orbit-3dvr-photo-scene/default-orbit-3dvr-photo-scene.tsx +34 -0
  94. package/src/core/scene/photo/3dvr-photo/default-poster-3dvr-photo-scene/default-poster-3dvr-photo-scene.stories.tsx +38 -0
  95. package/src/core/scene/photo/3dvr-photo/default-poster-3dvr-photo-scene/default-poster-3dvr-photo-scene.tsx +39 -0
  96. package/src/core/scene/photo/3dvr-photo/index.ts +6 -3
  97. package/src/core/scene/photo/effects-photo/default-chrome-effects-photo-scene/default-chrome-effects-photo-scene.stories.tsx +24 -0
  98. package/src/core/scene/photo/effects-photo/default-chrome-effects-photo-scene/default-chrome-effects-photo-scene.tsx +39 -0
  99. package/src/core/scene/photo/effects-photo/default-cool-tone-effects-photo-scene/default-cool-tone-effects-photo-scene.stories.tsx +24 -0
  100. package/src/core/scene/photo/effects-photo/default-cool-tone-effects-photo-scene/default-cool-tone-effects-photo-scene.tsx +39 -0
  101. package/src/core/scene/photo/effects-photo/default-dream-effects-photo-scene/default-dream-effects-photo-scene.stories.tsx +23 -0
  102. package/src/core/scene/photo/effects-photo/default-dream-effects-photo-scene/default-dream-effects-photo-scene.tsx +37 -0
  103. package/src/core/scene/photo/effects-photo/default-duotone-effects-photo-scene/default-duotone-effects-photo-scene.stories.tsx +25 -0
  104. package/src/core/scene/photo/effects-photo/default-duotone-effects-photo-scene/default-duotone-effects-photo-scene.tsx +41 -0
  105. package/src/core/scene/photo/effects-photo/{default-effects-photo-scene.stories.tsx → default-effects-photo-scene/default-effects-photo-scene.stories.tsx} +2 -2
  106. package/src/core/scene/photo/effects-photo/default-effects-photo-scene/default-effects-photo-scene.tsx +639 -0
  107. package/src/core/scene/photo/effects-photo/{default-effects-photo-scene-Horizontal.stories.tsx → default-effects-photo-scene-Horizontal/default-effects-photo-scene-Horizontal.stories.tsx} +1 -1
  108. package/src/core/scene/photo/effects-photo/{default-effects-photo-scene-Horizontal.tsx → default-effects-photo-scene-Horizontal/default-effects-photo-scene-Horizontal.tsx} +4 -4
  109. package/src/core/scene/photo/effects-photo/{default-effects-photo-scene-Landscape.tsx → default-effects-photo-scene-Landscape/default-effects-photo-scene-Landscape.tsx} +4 -4
  110. package/src/core/scene/photo/effects-photo/default-glow-effects-photo-scene/default-glow-effects-photo-scene.stories.tsx +39 -0
  111. package/src/core/scene/photo/effects-photo/default-glow-effects-photo-scene/default-glow-effects-photo-scene.tsx +37 -0
  112. package/src/core/scene/photo/effects-photo/default-grain-effects-photo-scene/default-grain-effects-photo-scene.stories.tsx +39 -0
  113. package/src/core/scene/photo/effects-photo/default-grain-effects-photo-scene/default-grain-effects-photo-scene.tsx +37 -0
  114. package/src/core/scene/photo/effects-photo/default-halation-effects-photo-scene/default-halation-effects-photo-scene.stories.tsx +24 -0
  115. package/src/core/scene/photo/effects-photo/default-halation-effects-photo-scene/default-halation-effects-photo-scene.tsx +39 -0
  116. package/src/core/scene/photo/effects-photo/default-infrared-effects-photo-scene/default-infrared-effects-photo-scene.stories.tsx +24 -0
  117. package/src/core/scene/photo/effects-photo/default-infrared-effects-photo-scene/default-infrared-effects-photo-scene.tsx +39 -0
  118. package/src/core/scene/photo/effects-photo/default-light-leak-effects-photo-scene/default-light-leak-effects-photo-scene.stories.tsx +24 -0
  119. package/src/core/scene/photo/effects-photo/default-light-leak-effects-photo-scene/default-light-leak-effects-photo-scene.tsx +39 -0
  120. package/src/core/scene/photo/effects-photo/default-mono-effects-photo-scene/default-mono-effects-photo-scene.stories.tsx +23 -0
  121. package/src/core/scene/photo/effects-photo/default-mono-effects-photo-scene/default-mono-effects-photo-scene.tsx +37 -0
  122. package/src/core/scene/photo/effects-photo/default-noir-effects-photo-scene/default-noir-effects-photo-scene.stories.tsx +23 -0
  123. package/src/core/scene/photo/effects-photo/default-noir-effects-photo-scene/default-noir-effects-photo-scene.tsx +37 -0
  124. package/src/core/scene/photo/effects-photo/default-pastel-effects-photo-scene/default-pastel-effects-photo-scene.stories.tsx +24 -0
  125. package/src/core/scene/photo/effects-photo/default-pastel-effects-photo-scene/default-pastel-effects-photo-scene.tsx +39 -0
  126. package/src/core/scene/photo/effects-photo/default-retro-effects-photo-scene/default-retro-effects-photo-scene.stories.tsx +24 -0
  127. package/src/core/scene/photo/effects-photo/default-retro-effects-photo-scene/default-retro-effects-photo-scene.tsx +39 -0
  128. package/src/core/scene/photo/effects-photo/default-sepia-effects-photo-scene/default-sepia-effects-photo-scene.stories.tsx +23 -0
  129. package/src/core/scene/photo/effects-photo/default-sepia-effects-photo-scene/default-sepia-effects-photo-scene.tsx +37 -0
  130. package/src/core/scene/photo/effects-photo/default-soft-focus-effects-photo-scene/default-soft-focus-effects-photo-scene.stories.tsx +39 -0
  131. package/src/core/scene/photo/effects-photo/default-soft-focus-effects-photo-scene/default-soft-focus-effects-photo-scene.tsx +37 -0
  132. package/src/core/scene/photo/effects-photo/default-vibrant-effects-photo-scene/default-vibrant-effects-photo-scene.stories.tsx +23 -0
  133. package/src/core/scene/photo/effects-photo/default-vibrant-effects-photo-scene/default-vibrant-effects-photo-scene.tsx +37 -0
  134. package/src/core/scene/photo/effects-photo/default-vignette-effects-photo-scene/default-vignette-effects-photo-scene.stories.tsx +39 -0
  135. package/src/core/scene/photo/effects-photo/default-vignette-effects-photo-scene/default-vignette-effects-photo-scene.tsx +37 -0
  136. package/src/core/scene/photo/effects-photo/default-warmth-effects-photo-scene/default-warmth-effects-photo-scene.stories.tsx +40 -0
  137. package/src/core/scene/photo/effects-photo/default-warmth-effects-photo-scene/default-warmth-effects-photo-scene.tsx +39 -0
  138. package/src/core/scene/photo/effects-photo/index.ts +21 -3
  139. package/src/core/scene/photo/index.ts +25 -9
  140. package/src/core/scene/photo/{default-live-photo-scene-Horizontal.stories.tsx → live-photo/default-live-photo-scene-Horizontal.stories.tsx} +1 -1
  141. package/src/core/scene/photo/{default-live-photo-scene-Horizontal.tsx → live-photo/default-live-photo-scene-Horizontal.tsx} +1 -1
  142. package/src/core/scene/photo/{default-live-photo-scene-Landscape.tsx → live-photo/default-live-photo-scene-Landscape.tsx} +1 -1
  143. package/src/core/scene/photo/{default-live-photo-scene.stories.tsx → live-photo/default-live-photo-scene.stories.tsx} +1 -1
  144. package/src/core/scene/photo/{default-live-photo-scene.tsx → live-photo/default-live-photo-scene.tsx} +5 -3
  145. package/src/core/scene/photo/photo-storybook.test.tsx +2 -2
  146. package/src/core/scene/photo/{default-photo-strip-scene-Horizontal.tsx → photo-strip/default-photo-strip-scene-Horizontal.tsx} +1 -1
  147. package/src/core/scene/photo/{default-photo-strip-scene-Landscape.tsx → photo-strip/default-photo-strip-scene-Landscape.tsx} +1 -1
  148. package/src/core/scene/photo/{default-photo-strip-scene.stories.tsx → photo-strip/default-photo-strip-scene.stories.tsx} +1 -1
  149. package/src/core/scene/photo/{default-photo-strip-scene.tsx → photo-strip/default-photo-strip-scene.tsx} +2 -2
  150. package/src/core/scene/photo/{default-photo-wall-scene-Horizontal.tsx → photo-wall/default-photo-wall-scene-Horizontal.tsx} +1 -1
  151. package/src/core/scene/photo/{default-photo-wall-scene-Landscape.tsx → photo-wall/default-photo-wall-scene-Landscape.tsx} +1 -1
  152. package/src/core/scene/photo/{default-photo-wall-scene.stories.tsx → photo-wall/default-photo-wall-scene.stories.tsx} +1 -1
  153. package/src/core/scene/photo/{default-photo-wall-scene.tsx → photo-wall/default-photo-wall-scene.tsx} +2 -2
  154. package/src/core/scene/slide/{default-slide-scene-Horizontal.animated.stories.tsx → default-slide-scene/default-slide-scene-Horizontal.animated.stories.tsx} +1 -1
  155. package/src/core/scene/slide/{default-slide-scene-Horizontal.tsx → default-slide-scene/default-slide-scene-Horizontal.tsx} +1 -1
  156. package/src/core/scene/slide/{default-slide-scene-Landscape.tsx → default-slide-scene/default-slide-scene-Landscape.tsx} +1 -1
  157. package/src/core/scene/slide/{default-slide-scene.animated.stories.tsx → default-slide-scene/default-slide-scene.animated.stories.tsx} +1 -1
  158. package/src/core/scene/slide/{default-slide-scene.tsx → default-slide-scene/default-slide-scene.tsx} +5 -5
  159. package/src/core/scene/slide/index.ts +3 -3
  160. package/src/core/scene/video/{default-video-scene-Horizontal.stories.tsx → default-video-scene/default-video-scene-Horizontal.stories.tsx} +1 -1
  161. package/src/core/scene/video/{default-video-scene-Horizontal.tsx → default-video-scene/default-video-scene-Horizontal.tsx} +1 -1
  162. package/src/core/scene/video/{default-video-scene-Landscape.tsx → default-video-scene/default-video-scene-Landscape.tsx} +1 -1
  163. package/src/core/scene/video/{default-video-scene.stories.tsx → default-video-scene/default-video-scene.stories.tsx} +1 -1
  164. package/src/core/scene/video/{default-video-scene.tsx → default-video-scene/default-video-scene.tsx} +3 -3
  165. package/src/core/scene/video/{default-video-split-scene-Horizontal.tsx → default-video-split-scene/default-video-split-scene-Horizontal.tsx} +1 -1
  166. package/src/core/scene/video/{default-video-split-scene-Landscape.tsx → default-video-split-scene/default-video-split-scene-Landscape.tsx} +1 -1
  167. package/src/core/scene/video/{default-video-split-scene.stories.tsx → default-video-split-scene/default-video-split-scene.stories.tsx} +1 -1
  168. package/src/core/scene/video/{default-video-split-scene.tsx → default-video-split-scene/default-video-split-scene.tsx} +2 -2
  169. package/src/core/scene/video/{default-video-wall-scene-Horizontal.tsx → default-video-wall-scene/default-video-wall-scene-Horizontal.tsx} +1 -1
  170. package/src/core/scene/video/{default-video-wall-scene-Landscape.tsx → default-video-wall-scene/default-video-wall-scene-Landscape.tsx} +1 -1
  171. package/src/core/scene/video/{default-video-wall-scene.stories.tsx → default-video-wall-scene/default-video-wall-scene.stories.tsx} +1 -1
  172. package/src/core/scene/video/{default-video-wall-scene.tsx → default-video-wall-scene/default-video-wall-scene.tsx} +2 -2
  173. package/src/core/scene/video/index.ts +9 -9
  174. package/src/lint/index.ts +2 -0
  175. package/src/lint/scene-convention-lint.test.ts +86 -0
  176. package/src/lint/scene-convention-lint.ts +247 -0
  177. package/src/storybook/index.ts +19 -0
  178. package/src/storybook/remotion-preview.test.tsx +53 -0
  179. package/src/storybook/remotion-preview.tsx +85 -11
  180. package/src/core/scene/photo/effects-photo/default-effects-photo-scene.tsx +0 -352
  181. /package/src/core/scene/slide/{default-slide-scene-Horizontal.stories.tsx → default-slide-scene/default-slide-scene-Horizontal.stories.tsx} +0 -0
  182. /package/src/core/scene/slide/{default-slide-scene.stories.tsx → default-slide-scene/default-slide-scene.stories.tsx} +0 -0
@@ -1,7 +1,7 @@
1
1
  import type { CSSProperties, ReactNode } from 'react'
2
2
  import { createContext, useContext } from 'react'
3
3
 
4
- type RemotionPreviewValue = {
4
+ export type RemotionPreviewValue = {
5
5
  frame: number
6
6
  fps: number
7
7
  width: number
@@ -60,9 +60,9 @@ type SpringConfig = {
60
60
  delay?: number
61
61
  }
62
62
 
63
- function clamp01(value: number) {
64
- if (value < 0) return 0
65
- if (value > 1) return 1
63
+ function clamp(value: number, min: number, max: number) {
64
+ if (value < min) return min
65
+ if (value > max) return max
66
66
  return value
67
67
  }
68
68
 
@@ -84,19 +84,13 @@ export function spring({
84
84
  const eased = 1 - Math.exp(-progress * (damping / Math.max(0.001, mass)))
85
85
  const wobble = Math.sin(progress * Math.PI * (stiffness / 55)) * 0.015
86
86
 
87
- return clamp01(eased + wobble)
87
+ return clamp(eased + wobble, 0, 1)
88
88
  }
89
89
 
90
90
  type Extrapolate = 'clamp' | 'extend' | 'identity'
91
91
 
92
92
  type EasingFunction = (value: number) => number
93
93
 
94
- function clamp(value: number, min: number, max: number) {
95
- if (value < min) return min
96
- if (value > max) return max
97
- return value
98
- }
99
-
100
94
  function wrapInOut(easing: EasingFunction): EasingFunction {
101
95
  return (value) => {
102
96
  if (value <= 0.5) {
@@ -197,6 +191,63 @@ export function Img({
197
191
  return <img {...rest} src={src} alt={alt} style={style} />
198
192
  }
199
193
 
194
+ export function Audio({
195
+ src,
196
+ volume,
197
+ style,
198
+ ...rest
199
+ }: {
200
+ src: string
201
+ volume?: number | ((frame: number) => number)
202
+ style?: CSSProperties
203
+ [key: string]: unknown
204
+ }) {
205
+ void volume
206
+
207
+ return <audio {...rest} src={src} style={style} />
208
+ }
209
+
210
+ export const HTML_IN_CANVAS_UNSUPPORTED_MESSAGE =
211
+ 'HtmlInCanvas is not available in Storybook preview, falling back to the DOM renderer.'
212
+
213
+ export function isHtmlInCanvasSupported() {
214
+ return false
215
+ }
216
+
217
+ type HtmlInCanvasProps = {
218
+ width: number
219
+ height: number
220
+ durationInFrames?: number
221
+ pixelDensity?: number
222
+ effects?: unknown
223
+ children?: ReactNode
224
+ onPaint?: unknown
225
+ onInit?: unknown
226
+ style?: CSSProperties
227
+ }
228
+
229
+ function HtmlInCanvasFallback({ children, style }: HtmlInCanvasProps) {
230
+ return (
231
+ <div
232
+ style={{
233
+ position: 'absolute',
234
+ inset: 0,
235
+ overflow: 'hidden',
236
+ boxSizing: 'border-box',
237
+ ...style,
238
+ }}
239
+ >
240
+ {children}
241
+ </div>
242
+ )
243
+ }
244
+
245
+ HtmlInCanvasFallback.isSupported = isHtmlInCanvasSupported
246
+
247
+ export const HtmlInCanvas = HtmlInCanvasFallback as typeof HtmlInCanvasFallback & {
248
+ isSupported: typeof isHtmlInCanvasSupported
249
+ }
250
+
200
251
  export function AbsoluteFill({
201
252
  children,
202
253
  style,
@@ -220,3 +271,26 @@ export function AbsoluteFill({
220
271
  </div>
221
272
  )
222
273
  }
274
+
275
+ export function Sequence({
276
+ children,
277
+ }: {
278
+ from?: number
279
+ durationInFrames?: number
280
+ children?: ReactNode
281
+ }) {
282
+ return <>{children}</>
283
+ }
284
+
285
+ export function random(seed?: string | number) {
286
+ const value = String(seed ?? 0)
287
+ let hash = 0
288
+ for (let index = 0; index < value.length; index += 1) {
289
+ hash = (hash * 31 + value.charCodeAt(index)) >>> 0
290
+ }
291
+ return (hash % 10000) / 10000
292
+ }
293
+
294
+ export function staticFile(path: string) {
295
+ return path
296
+ }
@@ -1,352 +0,0 @@
1
- import { useMemo } from 'react'
2
-
3
- import { z } from 'zod'
4
-
5
- import { VideoComponent, defineScenePluginMetadata } from '@vibecuting/component-project-helper'
6
- import { Easing, Img, interpolate, spring, useCurrentFrame, useVideoConfig } from 'remotion'
7
-
8
- import { BaseRemotionScene, type BaseRemotionSceneProps, useRemotionSceneRuntime, useSceneConfig } from '../../../../base'
9
- import { defineSceneComponent } from '../../../../plugins/scene-component'
10
-
11
- export type PhotoEffectType = 'vignette' | 'grain' | 'glow' | 'warmth' | 'soft-focus'
12
-
13
- export interface PhotoEffect {
14
- type: PhotoEffectType
15
- intensity?: number
16
- hue?: string
17
- }
18
-
19
- export interface DefaultEffectsPhotoSceneProps extends BaseRemotionSceneProps {
20
- sceneId?: string
21
- sceneName?: string
22
- title?: string
23
- subtitle?: string
24
- badge?: string
25
- imageSrc: string
26
- effects?: PhotoEffect[]
27
- accent?: string
28
- secondaryAccent?: string
29
- textColor?: string
30
- }
31
-
32
- export const componentMetadata = defineScenePluginMetadata({
33
- resourceKind: 'scene',
34
- name: 'DefaultEffectsPhotoScene',
35
- description: 'Photo scene with layered Remotion effects and cinematic grading',
36
- sourceFile: 'src/core/scene/photo/effects-photo/default-effects-photo-scene.tsx',
37
- pluginKey: 'core.photo.effects-photo',
38
- tags: ['scene', 'photo', 'effects', 'image', 'cinematic'],
39
- aspectRatio: '16:9',
40
- sceneType: 'scene',
41
- sceneFamily: 'custom',
42
- rootLayout: 'absolute-fill',
43
- propsTypeName: 'DefaultEffectsPhotoSceneProps',
44
- })
45
-
46
- function matchesEffect(effects: PhotoEffect[] | undefined, type: PhotoEffectType) {
47
- return effects?.some((effect) => effect.type === type) ?? false
48
- }
49
-
50
- function effectIntensity(effects: PhotoEffect[] | undefined, type: PhotoEffectType, fallback: number) {
51
- return effects?.find((effect) => effect.type === type)?.intensity ?? fallback
52
- }
53
-
54
- export const DefaultEffectsPhotoScene = VideoComponent(componentMetadata)(
55
- defineSceneComponent({
56
- family: 'custom',
57
- propsSchema: z.object({
58
- sceneId: z.string().optional(),
59
- sceneName: z.string().optional(),
60
- title: z.string().optional(),
61
- subtitle: z.string().optional(),
62
- badge: z.string().optional(),
63
- imageSrc: z.string(),
64
- effects: z
65
- .array(
66
- z.object({
67
- type: z.enum(['vignette', 'grain', 'glow', 'warmth', 'soft-focus']),
68
- intensity: z.number().min(0).max(1).optional(),
69
- hue: z.string().optional(),
70
- }),
71
- )
72
- .optional(),
73
- accent: z.string().optional(),
74
- secondaryAccent: z.string().optional(),
75
- textColor: z.string().optional(),
76
- }),
77
- component: function DefaultEffectsPhotoScene({
78
- id,
79
- name,
80
- sceneId,
81
- sceneName,
82
- title,
83
- subtitle,
84
- badge,
85
- imageSrc,
86
- effects,
87
- accent,
88
- secondaryAccent,
89
- textColor,
90
- }: DefaultEffectsPhotoSceneProps) {
91
- const runtime = useRemotionSceneRuntime()
92
- const sceneConfig = useSceneConfig()
93
- const frame = useCurrentFrame()
94
- const { fps } = useVideoConfig()
95
- const portrait = runtime.height > runtime.width
96
- const animated = sceneConfig.sceneType === 'animation'
97
- const animationProgress =
98
- sceneConfig.sceneType === 'animation'
99
- ? spring({
100
- frame,
101
- fps,
102
- config: { damping: 22, mass: 0.8, stiffness: 130 },
103
- })
104
- : 1
105
- const reveal = sceneConfig.sceneType === 'animation' ? spring({ frame, fps, delay: 6, config: { damping: 20, mass: 0.7, stiffness: 150 } }) : 1
106
- const focusDrift = sceneConfig.sceneType === 'animation' ? Math.sin((frame / fps) * Math.PI * 0.75) : 0
107
- const scale = 1.01 + (1 - animationProgress) * 0.06 + focusDrift * 0.008
108
- const translateX = (1 - animationProgress) * (portrait ? -8 : -12) + focusDrift * (portrait ? 8 : 12)
109
- const translateY = (1 - animationProgress) * 10 + focusDrift * 16
110
- const titleSize = Math.round(runtime.height * (portrait ? 0.034 : 0.04))
111
- const subtitleSize = Math.round(runtime.height * 0.017)
112
- const framePaddingX = Math.round(runtime.width * (portrait ? 0.015 : 0.014))
113
- const framePaddingY = Math.round(runtime.height * (portrait ? 0.014 : 0.012))
114
- const frameLeft = framePaddingX
115
- const frameTop = framePaddingY
116
- const frameWidth = Math.max(1, runtime.width - framePaddingX * 2)
117
- const frameHeight = Math.max(1, runtime.height - framePaddingY * 2)
118
- const imageFilter = animated ? 'brightness(1.08) contrast(1.04) saturate(1.08)' : 'brightness(1.9) contrast(1.18) saturate(1.22)'
119
- const vignette = matchesEffect(effects, 'vignette')
120
- const grain = matchesEffect(effects, 'grain')
121
- const glow = matchesEffect(effects, 'glow')
122
- const warmth = matchesEffect(effects, 'warmth')
123
- const softFocus = matchesEffect(effects, 'soft-focus')
124
- const vignetteOpacity = effectIntensity(effects, 'vignette', 0.52) * (0.65 + reveal * 0.35)
125
- const glowOpacity = effectIntensity(effects, 'glow', 0.45) * (0.7 + reveal * 0.3)
126
- const grainOpacity = effectIntensity(effects, 'grain', 0.12)
127
- const warmthHue = effects?.find((effect) => effect.type === 'warmth')?.hue ?? accent ?? '#f97316'
128
- const focusOverlay = interpolate(reveal, [0, 1], [0, 1], {
129
- easing: Easing.inOut(Easing.quad),
130
- extrapolateLeft: 'clamp',
131
- extrapolateRight: 'clamp',
132
- })
133
-
134
- const effectLayers = useMemo(
135
- () => (
136
- <>
137
- {glow ? (
138
- <div
139
- aria-hidden="true"
140
- style={{
141
- position: 'absolute',
142
- inset: '4%',
143
- opacity: glowOpacity * 0.55,
144
- filter: 'blur(20px) saturate(1.18) brightness(0.98)',
145
- transform: `scale(${1.03 + (1 - animationProgress) * 0.02})`,
146
- pointerEvents: 'none',
147
- }}
148
- >
149
- <Img
150
- src={imageSrc}
151
- alt={title ?? 'Effects photo'}
152
- style={{
153
- width: '100%',
154
- height: '100%',
155
- objectFit: 'cover',
156
- }}
157
- />
158
- </div>
159
- ) : null}
160
- {softFocus ? (
161
- <div
162
- aria-hidden="true"
163
- style={{
164
- position: 'absolute',
165
- inset: 0,
166
- opacity: 0.18 + focusOverlay * 0.08,
167
- filter: 'blur(10px) saturate(1.04)',
168
- transform: `scale(${1.02 + focusOverlay * 0.01})`,
169
- pointerEvents: 'none',
170
- }}
171
- >
172
- <Img
173
- src={imageSrc}
174
- alt={title ?? 'Effects photo'}
175
- style={{
176
- width: '100%',
177
- height: '100%',
178
- objectFit: 'cover',
179
- }}
180
- />
181
- </div>
182
- ) : null}
183
- {vignette ? (
184
- <div
185
- aria-hidden="true"
186
- style={{
187
- position: 'absolute',
188
- inset: 0,
189
- background:
190
- 'radial-gradient(circle at center, rgba(255,255,255,0.04) 0%, rgba(255,255,255,0.01) 28%, rgba(2,6,23,0.14) 56%, rgba(2,6,23,0.46) 100%)',
191
- opacity: vignetteOpacity * 0.72,
192
- pointerEvents: 'none',
193
- }}
194
- />
195
- ) : null}
196
- {warmth ? (
197
- <div
198
- aria-hidden="true"
199
- style={{
200
- position: 'absolute',
201
- inset: 0,
202
- background: `linear-gradient(135deg, ${warmthHue} 0%, rgba(255,255,255,0.02) 36%, ${secondaryAccent ?? 'rgba(59,130,246,0.14)'} 100%)`,
203
- mixBlendMode: 'screen',
204
- opacity: 0.08 + focusOverlay * 0.08,
205
- pointerEvents: 'none',
206
- }}
207
- />
208
- ) : null}
209
- {grain ? (
210
- <div
211
- aria-hidden="true"
212
- style={{
213
- position: 'absolute',
214
- inset: 0,
215
- opacity: grainOpacity,
216
- backgroundImage:
217
- 'radial-gradient(rgba(255,255,255,0.35) 0.7px, transparent 0.7px), radial-gradient(rgba(0,0,0,0.3) 0.7px, transparent 0.7px)',
218
- backgroundSize: '4px 4px, 4px 4px',
219
- backgroundPosition: '0 0, 2px 2px',
220
- mixBlendMode: 'soft-light',
221
- pointerEvents: 'none',
222
- }}
223
- />
224
- ) : null}
225
- </>
226
- ),
227
- [
228
- animationProgress,
229
- focusOverlay,
230
- grain,
231
- grainOpacity,
232
- glow,
233
- glowOpacity,
234
- imageSrc,
235
- secondaryAccent,
236
- softFocus,
237
- title,
238
- vignette,
239
- vignetteOpacity,
240
- warmth,
241
- warmthHue,
242
- ],
243
- )
244
-
245
- return (
246
- <BaseRemotionScene
247
- id={id ?? sceneId}
248
- name={name ?? sceneName ?? title}
249
- style={{
250
- background:
251
- portrait
252
- ? `linear-gradient(180deg, ${accent ?? '#020617'} 0%, #000000 100%)`
253
- : `radial-gradient(circle at 50% 18%, ${secondaryAccent ?? 'rgba(255,255,255,0.08)'} 0%, ${accent ?? '#020617'} 52%, #000000 100%)`,
254
- color: textColor ?? '#f8fafc',
255
- padding: Math.round(runtime.height * (portrait ? 0.02 : 0.03)),
256
- }}
257
- >
258
- <div
259
- style={{
260
- position: 'absolute',
261
- inset: 0,
262
- overflow: 'hidden',
263
- border: '1px solid rgba(255,255,255,0.1)',
264
- background: 'rgba(2,6,23,0.82)',
265
- isolation: 'isolate',
266
- }}
267
- >
268
- <div
269
- style={{
270
- position: 'absolute',
271
- top: frameTop,
272
- left: frameLeft,
273
- width: frameWidth,
274
- height: frameHeight,
275
- border: animated ? '1px solid rgba(255,255,255,0.1)' : '1px solid rgba(255,255,255,0.16)',
276
- boxShadow: animated ? '0 18px 56px rgba(0,0,0,0.24)' : '0 12px 32px rgba(0,0,0,0.14)',
277
- backgroundColor: animated ? 'rgba(2,6,23,0.14)' : 'rgba(248,250,252,0.06)',
278
- backgroundImage: `url(${imageSrc})`,
279
- backgroundSize: 'cover',
280
- backgroundPosition: `${50}% ${portrait ? 44 : 52}%`,
281
- backgroundRepeat: 'no-repeat',
282
- overflow: 'hidden',
283
- filter: imageFilter,
284
- }}
285
- >
286
- </div>
287
-
288
- <div
289
- style={{
290
- position: 'absolute',
291
- top: frameTop,
292
- left: frameLeft,
293
- width: frameWidth,
294
- height: frameHeight,
295
- }}
296
- >
297
- {effectLayers}
298
- </div>
299
-
300
- <div
301
- aria-hidden="true"
302
- style={{
303
- position: 'absolute',
304
- inset: 0,
305
- background:
306
- 'linear-gradient(180deg, rgba(2,6,23,0.04) 0%, rgba(2,6,23,0.12) 38%, rgba(2,6,23,0.52) 100%)',
307
- pointerEvents: 'none',
308
- }}
309
- />
310
-
311
- <div
312
- style={{
313
- position: 'absolute',
314
- inset: 0,
315
- display: 'grid',
316
- alignContent: 'space-between',
317
- padding: Math.round(runtime.height * (portrait ? 0.02 : 0.03)),
318
- zIndex: 2,
319
- pointerEvents: 'none',
320
- }}
321
- >
322
- <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'start', gap: 12 }}>
323
- <div
324
- style={{
325
- display: 'inline-flex',
326
- alignItems: 'center',
327
- gap: 8,
328
- border: '1px solid rgba(255,255,255,0.18)',
329
- background: 'rgba(2,6,23,0.6)',
330
- color: '#f8fafc',
331
- padding: '8px 12px',
332
- letterSpacing: '0.22em',
333
- textTransform: 'uppercase',
334
- fontSize: 11,
335
- lineHeight: 1,
336
- }}
337
- >
338
- {badge ?? 'Effects Photo'}
339
- </div>
340
- </div>
341
-
342
- <div style={{ display: 'grid', gap: 8, maxWidth: portrait ? '86%' : '58%' }}>
343
- {title ? <div style={{ fontSize: titleSize, fontWeight: 800, letterSpacing: '-0.06em', lineHeight: 0.94 }}>{title}</div> : null}
344
- {subtitle ? <div style={{ fontSize: subtitleSize, lineHeight: 1.45, opacity: 0.84 }}>{subtitle}</div> : null}
345
- </div>
346
- </div>
347
- </div>
348
- </BaseRemotionScene>
349
- )
350
- },
351
- }),
352
- )