@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
@@ -0,0 +1,145 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ videoLayerBackgroundSchema,
4
+ videoLayerDisplaySchema,
5
+ videoLayerDialogueAudioManifestSchema,
6
+ } from "./video-layer-types";
7
+ import { buildVideoLayerBgmCues, getVideoLayerCueVolume } from "./background-audio-layer";
8
+ import { getDialogueManifestDurationInFrames } from "./voice-captions-foreground";
9
+
10
+ describe("video layer schemas", () => {
11
+ it("accepts image backgrounds", () => {
12
+ expect(
13
+ videoLayerBackgroundSchema.parse({
14
+ mode: "image",
15
+ baseColor: "#020617",
16
+ imageUrl: "https://example.com/bg.jpg",
17
+ imageOpacity: 0.8,
18
+ accentColor: "rgba(56, 189, 248, 0.4)",
19
+ }),
20
+ ).toEqual({
21
+ mode: "image",
22
+ baseColor: "#020617",
23
+ imageUrl: "https://example.com/bg.jpg",
24
+ imageOpacity: 0.8,
25
+ accentColor: "rgba(56, 189, 248, 0.4)",
26
+ });
27
+ });
28
+
29
+ it("rejects middle chapter progress placement", () => {
30
+ const surface = {
31
+ enabled: true,
32
+ position: { placement: "top" as const, align: "center" as const },
33
+ style: {
34
+ fontFamily: "sans-serif",
35
+ fontSize: 24,
36
+ fontWeight: 700,
37
+ color: "#fff",
38
+ },
39
+ };
40
+
41
+ expect(() =>
42
+ videoLayerDisplaySchema.parse({
43
+ title: surface,
44
+ subtitles: surface,
45
+ chapterInfo: {
46
+ ...surface,
47
+ position: { placement: "middle", align: "center" },
48
+ },
49
+ watermark: surface,
50
+ }),
51
+ ).toThrow("只支持 top 或 bottom");
52
+ });
53
+
54
+ it("accepts dialogue manifests used by voice captions", () => {
55
+ expect(
56
+ videoLayerDialogueAudioManifestSchema.parse({
57
+ projectId: "project-a",
58
+ generatedAt: "2026-06-22T00:00:00.000Z",
59
+ backend: "litellm",
60
+ fps: 30,
61
+ entries: [
62
+ {
63
+ chapterId: "intro",
64
+ chapterTitle: "Intro",
65
+ sceneId: "scene-1",
66
+ sceneTitle: "Scene 1",
67
+ lineIndex: 0,
68
+ speaker: "Narrator",
69
+ voice: null,
70
+ text: "Hello",
71
+ captionText: "Hello",
72
+ startFrame: 0,
73
+ durationInFrames: 45,
74
+ audioFile: "hello.wav",
75
+ },
76
+ ],
77
+ }).entries,
78
+ ).toHaveLength(1);
79
+ });
80
+ });
81
+
82
+ describe("background audio helpers", () => {
83
+ it("builds bgm cues from chapter plans and runtime timings", () => {
84
+ expect(
85
+ buildVideoLayerBgmCues(
86
+ [{ id: "intro", bgm: { mood: "warm", source: "assets/audio/intro.mp3", volume: 0.5 } }],
87
+ [{ key: "intro", startFrame: 30, durationInFrames: 90 }],
88
+ ),
89
+ ).toEqual([
90
+ {
91
+ id: "bgm-intro",
92
+ source: "assets/audio/intro.mp3",
93
+ startFrame: 30,
94
+ durationInFrames: 90,
95
+ volume: 0.5,
96
+ fadeInFrames: undefined,
97
+ fadeOutFrames: undefined,
98
+ },
99
+ ]);
100
+ });
101
+
102
+ it("applies cue fade in and fade out volume", () => {
103
+ const cue = {
104
+ id: "sfx",
105
+ source: "assets/audio/hit.wav",
106
+ startFrame: 0,
107
+ durationInFrames: 100,
108
+ volume: 0.8,
109
+ fadeInFrames: 10,
110
+ fadeOutFrames: 20,
111
+ };
112
+
113
+ expect(getVideoLayerCueVolume(cue, 5)).toBe(0.4);
114
+ expect(getVideoLayerCueVolume(cue, 50)).toBe(0.8);
115
+ expect(getVideoLayerCueVolume(cue, 90)).toBe(0.4);
116
+ });
117
+
118
+ it("computes dialogue manifest duration from durationMs when present", () => {
119
+ expect(
120
+ getDialogueManifestDurationInFrames({
121
+ projectId: "p",
122
+ generatedAt: "2026-06-22T00:00:00.000Z",
123
+ backend: "test",
124
+ fps: 30,
125
+ entries: [
126
+ {
127
+ chapterId: "intro",
128
+ chapterTitle: "Intro",
129
+ sceneId: "scene-1",
130
+ sceneTitle: "Scene 1",
131
+ lineIndex: 0,
132
+ speaker: "Narrator",
133
+ voice: null,
134
+ text: "Hello",
135
+ captionText: "Hello",
136
+ startFrame: 10,
137
+ durationInFrames: 1,
138
+ durationMs: 2000,
139
+ audioFile: "hello.wav",
140
+ },
141
+ ],
142
+ }),
143
+ ).toBe(70);
144
+ });
145
+ });
@@ -0,0 +1,220 @@
1
+ import { z } from "zod";
2
+
3
+ export const videoLayerAspectRatioSchema = z.enum(["16:9", "9:16"]);
4
+
5
+ export const videoLayerResolutionSchema = z.union([
6
+ z.literal(1024),
7
+ z.literal(1080),
8
+ z.literal(1920),
9
+ ]);
10
+
11
+ export const videoLayerBackgroundSchema = z
12
+ .object({
13
+ mode: z.enum(["solid", "gradient", "image"]),
14
+ baseColor: z.string().min(1),
15
+ gradient: z.string().optional(),
16
+ imageUrl: z.string().optional(),
17
+ imageOpacity: z.number().min(0).max(1).optional(),
18
+ accentColor: z.string().optional(),
19
+ })
20
+ .strict();
21
+
22
+ export const videoLayerSurfaceMotionStrategySchema = z.enum([
23
+ "static",
24
+ "drift",
25
+ "float",
26
+ "loop",
27
+ ]);
28
+
29
+ export const videoLayerSurfaceEasingSchema = z.enum([
30
+ "linear",
31
+ "easeInOut",
32
+ "easeOut",
33
+ ]);
34
+
35
+ export const videoLayerSurfaceAlignSchema = z.enum(["left", "center", "right"]);
36
+
37
+ export const videoLayerSurfacePlacementSchema = z.enum(["top", "middle", "bottom"]);
38
+
39
+ export const videoLayerSurfacePositionSchema = z
40
+ .object({
41
+ placement: videoLayerSurfacePlacementSchema,
42
+ align: videoLayerSurfaceAlignSchema.optional(),
43
+ })
44
+ .strict();
45
+
46
+ export const videoLayerSurfaceMotionSchema = z
47
+ .object({
48
+ enabled: z.boolean().optional(),
49
+ strategy: videoLayerSurfaceMotionStrategySchema.optional(),
50
+ amplitudeX: z.number().optional(),
51
+ amplitudeY: z.number().optional(),
52
+ speed: z.number().optional(),
53
+ phase: z.number().optional(),
54
+ easing: videoLayerSurfaceEasingSchema.optional(),
55
+ })
56
+ .strict();
57
+
58
+ export const videoLayerSurfaceStyleSchema = z
59
+ .object({
60
+ fontFamily: z.string(),
61
+ fontSize: z.number(),
62
+ fontWeight: z.number(),
63
+ color: z.string(),
64
+ lineHeight: z.number().optional(),
65
+ backgroundColor: z.string().optional(),
66
+ borderRadius: z.number().optional(),
67
+ padding: z.number().optional(),
68
+ maxWidth: z.number().optional(),
69
+ shadow: z.string().optional(),
70
+ opacity: z.number().optional(),
71
+ foregroundColor: z.string().optional(),
72
+ foregroundGradient: z.string().optional(),
73
+ })
74
+ .strict();
75
+
76
+ export const videoLayerSurfaceResponsiveStyleSchema = z
77
+ .object({
78
+ portrait: videoLayerSurfaceStyleSchema.partial().optional(),
79
+ landscape: videoLayerSurfaceStyleSchema.partial().optional(),
80
+ })
81
+ .strict();
82
+
83
+ export const videoLayerSurfaceResponsivePositionSchema = z
84
+ .object({
85
+ portrait: videoLayerSurfacePositionSchema.partial().optional(),
86
+ landscape: videoLayerSurfacePositionSchema.partial().optional(),
87
+ })
88
+ .strict();
89
+
90
+ export const videoLayerSurfaceSchema = z
91
+ .object({
92
+ enabled: z.boolean(),
93
+ position: videoLayerSurfacePositionSchema,
94
+ style: videoLayerSurfaceStyleSchema,
95
+ responsiveStyle: videoLayerSurfaceResponsiveStyleSchema.optional(),
96
+ responsivePosition: videoLayerSurfaceResponsivePositionSchema.optional(),
97
+ motion: videoLayerSurfaceMotionSchema.optional(),
98
+ })
99
+ .strict();
100
+
101
+ export const videoLayerDisplaySchema = z
102
+ .object({
103
+ title: videoLayerSurfaceSchema,
104
+ subtitles: videoLayerSurfaceSchema,
105
+ chapterInfo: videoLayerSurfaceSchema,
106
+ watermark: videoLayerSurfaceSchema,
107
+ })
108
+ .strict()
109
+ .superRefine((value, ctx) => {
110
+ const chapterInfo = value.chapterInfo;
111
+ if (chapterInfo.position.placement === "middle") {
112
+ ctx.addIssue({
113
+ code: z.ZodIssueCode.custom,
114
+ path: ["chapterInfo", "position", "placement"],
115
+ message: "只支持 top 或 bottom",
116
+ });
117
+ }
118
+ });
119
+
120
+ export const videoLayerLayoutSchema = z
121
+ .object({
122
+ background: videoLayerBackgroundSchema,
123
+ })
124
+ .passthrough();
125
+
126
+ export const videoLayerDesignSchema = z
127
+ .object({
128
+ layout: videoLayerLayoutSchema,
129
+ display: videoLayerDisplaySchema,
130
+ })
131
+ .passthrough();
132
+
133
+ export const videoLayerChapterProgressItemSchema = z
134
+ .object({
135
+ title: z.string().min(1),
136
+ durationInFrames: z.number().int().positive(),
137
+ })
138
+ .strict();
139
+
140
+ export const videoLayerBackgroundMusicPlanSchema = z
141
+ .object({
142
+ mood: z.string().min(1),
143
+ source: z.string().optional(),
144
+ prompt: z.string().optional(),
145
+ volume: z.number().min(0).max(1).optional(),
146
+ fadeInFrames: z.number().int().nonnegative().optional(),
147
+ fadeOutFrames: z.number().int().nonnegative().optional(),
148
+ notes: z.string().optional(),
149
+ })
150
+ .strict();
151
+
152
+ export const videoLayerAudioCueSchema = z
153
+ .object({
154
+ id: z.string().min(1),
155
+ source: z.string().min(1),
156
+ startFrame: z.number().int().nonnegative(),
157
+ durationInFrames: z.number().int().positive(),
158
+ volume: z.number().min(0).max(1).optional(),
159
+ fadeInFrames: z.number().int().nonnegative().optional(),
160
+ fadeOutFrames: z.number().int().nonnegative().optional(),
161
+ })
162
+ .strict();
163
+
164
+ export const videoLayerDialogueAudioManifestEntrySchema = z
165
+ .object({
166
+ chapterId: z.string().min(1),
167
+ chapterTitle: z.string().min(1),
168
+ sceneId: z.string().min(1),
169
+ sceneTitle: z.string().min(1),
170
+ lineIndex: z.number().int().nonnegative(),
171
+ speaker: z.string().min(1),
172
+ voice: z.string().nullable(),
173
+ text: z.string().min(1),
174
+ captionText: z.string().min(1),
175
+ startFrame: z.number().int().nonnegative(),
176
+ durationInFrames: z.number().int().positive(),
177
+ durationMs: z.number().positive().optional(),
178
+ audioFile: z.string().min(1),
179
+ })
180
+ .strict();
181
+
182
+ export const videoLayerDialogueAudioManifestSchema = z
183
+ .object({
184
+ projectId: z.string().min(1),
185
+ generatedAt: z.string().min(1),
186
+ backend: z.string().min(1),
187
+ fps: z.number().int().positive(),
188
+ entries: z.array(videoLayerDialogueAudioManifestEntrySchema),
189
+ })
190
+ .strict();
191
+
192
+ export type VideoLayerAspectRatio = z.infer<typeof videoLayerAspectRatioSchema>;
193
+ export type VideoLayerResolution = z.infer<typeof videoLayerResolutionSchema>;
194
+ export type VideoLayerBackgroundConfig = z.infer<typeof videoLayerBackgroundSchema>;
195
+ export type VideoLayerSurfacePositionConfig = z.infer<typeof videoLayerSurfacePositionSchema>;
196
+ export type VideoLayerSurfaceMotionConfig = z.infer<typeof videoLayerSurfaceMotionSchema>;
197
+ export type VideoLayerSurfaceStyleConfig = z.infer<typeof videoLayerSurfaceStyleSchema>;
198
+ export type VideoLayerSurfaceResponsiveStyleConfig = z.infer<
199
+ typeof videoLayerSurfaceResponsiveStyleSchema
200
+ >;
201
+ export type VideoLayerSurfaceResponsivePositionConfig = z.infer<
202
+ typeof videoLayerSurfaceResponsivePositionSchema
203
+ >;
204
+ export type VideoLayerSurfaceConfig = z.infer<typeof videoLayerSurfaceSchema>;
205
+ export type VideoLayerDisplayConfig = z.infer<typeof videoLayerDisplaySchema>;
206
+ export type VideoLayerLayoutConfig = z.infer<typeof videoLayerLayoutSchema>;
207
+ export type VideoLayerDesign = z.infer<typeof videoLayerDesignSchema>;
208
+ export type VideoLayerChapterProgressItem = z.infer<
209
+ typeof videoLayerChapterProgressItemSchema
210
+ >;
211
+ export type VideoLayerBackgroundMusicPlan = z.infer<
212
+ typeof videoLayerBackgroundMusicPlanSchema
213
+ >;
214
+ export type VideoLayerAudioCue = z.infer<typeof videoLayerAudioCueSchema>;
215
+ export type VideoLayerDialogueAudioManifestEntry = z.infer<
216
+ typeof videoLayerDialogueAudioManifestEntrySchema
217
+ >;
218
+ export type VideoLayerDialogueAudioManifest = z.infer<
219
+ typeof videoLayerDialogueAudioManifestSchema
220
+ >;
@@ -0,0 +1,169 @@
1
+ import {
2
+ Audio,
3
+ Sequence,
4
+ staticFile,
5
+ useCurrentFrame,
6
+ useVideoConfig,
7
+ } from "remotion";
8
+ import { buildVideoLayerDisplaySurfaceStyle } from "./display-surface";
9
+ import { resolveVideoLayerSubtitleStyle } from "./subtitle-style";
10
+ import type {
11
+ VideoLayerDesign,
12
+ VideoLayerDialogueAudioManifest,
13
+ VideoLayerDialogueAudioManifestEntry,
14
+ } from "./video-layer-types";
15
+
16
+ type DialogueTimelineLine = {
17
+ chapterId: string;
18
+ sceneId: string;
19
+ lineIndex: number;
20
+ speaker: string;
21
+ voice?: string;
22
+ startFrame: number;
23
+ durationInFrames: number;
24
+ audioFile: string;
25
+ };
26
+
27
+ export type VideoVoiceCaptionsForegroundProps = {
28
+ design: VideoLayerDesign;
29
+ manifest: VideoLayerDialogueAudioManifest;
30
+ captions: Array<{
31
+ startMs: number;
32
+ endMs: number;
33
+ text: string;
34
+ }>;
35
+ };
36
+
37
+ export type DialogueAudioManifestEntry = VideoLayerDialogueAudioManifestEntry;
38
+ export type DialogueAudioManifest = VideoLayerDialogueAudioManifest;
39
+
40
+ export const getDialogueLineDurationInFrames = (
41
+ entry: VideoLayerDialogueAudioManifestEntry,
42
+ fps: number,
43
+ ) => {
44
+ if (typeof entry.durationMs === "number" && Number.isFinite(entry.durationMs)) {
45
+ return Math.max(1, Math.round((entry.durationMs / 1000) * fps));
46
+ }
47
+
48
+ return Math.max(1, entry.durationInFrames);
49
+ };
50
+
51
+ export const getDialogueManifestDurationInFrames = (
52
+ manifest: VideoLayerDialogueAudioManifest,
53
+ ) => {
54
+ return manifest.entries.reduce((maxEndFrame, entry) => {
55
+ const durationInFrames = getDialogueLineDurationInFrames(entry, manifest.fps);
56
+ return Math.max(maxEndFrame, entry.startFrame + durationInFrames);
57
+ }, 0);
58
+ };
59
+
60
+ const normalizeDialogueAudioFile = (audioFile: string) => {
61
+ const normalizedAudioFile = audioFile.replace(/^public\//, "").replace(/^\/+/, "");
62
+
63
+ return normalizedAudioFile.includes("/")
64
+ ? normalizedAudioFile
65
+ : `assets/audio/${normalizedAudioFile}`;
66
+ };
67
+
68
+ const buildDialogueTimeline = (
69
+ manifest: VideoLayerDialogueAudioManifest,
70
+ ): DialogueTimelineLine[] => {
71
+ return manifest.entries.map((entry) => ({
72
+ chapterId: entry.chapterId,
73
+ sceneId: entry.sceneId,
74
+ lineIndex: entry.lineIndex,
75
+ speaker: entry.speaker,
76
+ voice: entry.voice ?? undefined,
77
+ startFrame: entry.startFrame,
78
+ durationInFrames: getDialogueLineDurationInFrames(entry, manifest.fps),
79
+ audioFile: normalizeDialogueAudioFile(entry.audioFile),
80
+ }));
81
+ };
82
+
83
+ export const VideoVoiceCaptionsForeground = ({
84
+ design,
85
+ manifest,
86
+ captions,
87
+ }: VideoVoiceCaptionsForegroundProps) => {
88
+ const { fps, width, height } = useVideoConfig();
89
+ const frame = useCurrentFrame();
90
+ const dialogueTimeline = buildDialogueTimeline(manifest);
91
+ const subtitleSurface = resolveVideoLayerSubtitleStyle(design.display.subtitles, {
92
+ width,
93
+ height,
94
+ });
95
+
96
+ return (
97
+ <>
98
+ {dialogueTimeline.map((line) => (
99
+ <Sequence
100
+ key={`${line.chapterId}-${line.sceneId}-${line.lineIndex}`}
101
+ from={line.startFrame}
102
+ durationInFrames={line.durationInFrames}
103
+ >
104
+ <Audio src={staticFile(line.audioFile)} volume={1} />
105
+ </Sequence>
106
+ ))}
107
+ {subtitleSurface.enabled && captions.length > 0 ? (
108
+ <div
109
+ style={buildVideoLayerDisplaySurfaceStyle(subtitleSurface, frame, fps, {
110
+ background: "transparent",
111
+ padding: 0,
112
+ })}
113
+ >
114
+ {captions.map((caption, index) => {
115
+ const startFrame = Math.max(0, Math.round((caption.startMs / 1000) * fps));
116
+ const durationInFrames = Math.max(
117
+ 1,
118
+ Math.round(((caption.endMs - caption.startMs) / 1000) * fps),
119
+ );
120
+
121
+ return (
122
+ <Sequence
123
+ key={`${caption.startMs}-${index}`}
124
+ from={startFrame}
125
+ durationInFrames={durationInFrames}
126
+ >
127
+ <div
128
+ style={{
129
+ display: "flex",
130
+ alignItems: "center",
131
+ justifyContent: "center",
132
+ width: "100%",
133
+ opacity: 0.96,
134
+ boxSizing: "border-box",
135
+ }}
136
+ >
137
+ <div
138
+ style={{
139
+ display: "inline-flex",
140
+ alignItems: "center",
141
+ justifyContent: "center",
142
+ padding: subtitleSurface.style.padding ?? 0,
143
+ borderRadius: subtitleSurface.style.borderRadius ?? 0,
144
+ background:
145
+ subtitleSurface.style.backgroundColor ?? "rgba(2, 6, 23, 0.86)",
146
+ color: subtitleSurface.style.color,
147
+ fontFamily: subtitleSurface.style.fontFamily,
148
+ fontSize: subtitleSurface.style.fontSize,
149
+ fontWeight: subtitleSurface.style.fontWeight,
150
+ lineHeight: subtitleSurface.style.lineHeight ?? 1.25,
151
+ maxWidth: subtitleSurface.style.maxWidth ?? "100%",
152
+ boxShadow: subtitleSurface.style.shadow ?? "none",
153
+ whiteSpace: "pre-wrap",
154
+ textAlign: "center",
155
+ }}
156
+ >
157
+ {caption.text}
158
+ </div>
159
+ </div>
160
+ </Sequence>
161
+ );
162
+ })}
163
+ </div>
164
+ ) : null}
165
+ </>
166
+ );
167
+ };
168
+
169
+ export const VoiceCaptionsForeground = VideoVoiceCaptionsForeground;
@@ -1,18 +1,18 @@
1
- export { DefaultIntroBumper } from './default-intro-bumper'
2
- export { DefaultCinematicIntroBumper } from './default-cinematic-intro-bumper'
3
- export { DefaultNoirIntroBumper } from './default-noir-intro-bumper'
4
- export { DefaultTrailerIntroBumper } from './default-trailer-intro-bumper'
5
- export { DefaultFestivalIntroBumper } from './default-festival-intro-bumper'
6
- export { DefaultWesternIntroBumper } from './western-intro'
7
- export { DefaultSciFiIntroBumper } from './sci-fi-intro'
8
- export { DefaultNoirIntroBumperDeluxe } from './noir-intro-deluxe'
9
- export { DefaultTrailerIntroBumperPremiere } from './trailer-intro-premiere'
10
- export { DefaultFestivalIntroBumperSpotlight } from './festival-intro-spotlight'
11
- export { DefaultNoirIntroBumperCity } from './noir-intro-city'
12
- export { DefaultCyberpunkIntroBumperNeon } from './cyberpunk-intro-neon'
13
- export { DefaultWesternIntroBumperGangster } from './western-intro-gangster'
14
- export { DefaultCyberpunkIntroBumperHolo } from './cyberpunk-intro-holo'
15
- export { DefaultDocumentaryIntroBumper } from './documentary-intro-observation'
16
- export { DefaultThrillerIntroBumper } from './thriller-intro-suspense'
17
- export { DefaultFamilyIntroBumper } from './family-intro-reunion'
18
- export { DefaultTravelIntroBumper } from './travel-intro-journey'
1
+ export { DefaultIntroBumper } from './default-intro-bumper/index'
2
+ export { DefaultCinematicIntroBumper } from './default-cinematic-intro-bumper/index'
3
+ export { DefaultNoirIntroBumper } from './default-noir-intro-bumper/index'
4
+ export { DefaultTrailerIntroBumper } from './default-trailer-intro-bumper/index'
5
+ export { DefaultFestivalIntroBumper } from './default-festival-intro-bumper/index'
6
+ export { DefaultWesternIntroBumper } from './western-intro/index'
7
+ export { DefaultSciFiIntroBumper } from './sci-fi-intro/index'
8
+ export { DefaultNoirIntroBumperDeluxe } from './noir-intro-deluxe/index'
9
+ export { DefaultTrailerIntroBumperPremiere } from './trailer-intro-premiere/index'
10
+ export { DefaultFestivalIntroBumperSpotlight } from './festival-intro-spotlight/index'
11
+ export { DefaultNoirIntroBumperCity } from './noir-intro-city/index'
12
+ export { DefaultCyberpunkIntroBumperNeon } from './cyberpunk-intro-neon/index'
13
+ export { DefaultWesternIntroBumperGangster } from './western-intro-gangster/index'
14
+ export { DefaultCyberpunkIntroBumperHolo } from './cyberpunk-intro-holo/index'
15
+ export { DefaultDocumentaryIntroBumper } from './documentary-intro-observation/index'
16
+ export { DefaultThrillerIntroBumper } from './thriller-intro-suspense/index'
17
+ export { DefaultFamilyIntroBumper } from './family-intro-reunion/index'
18
+ export { DefaultTravelIntroBumper } from './travel-intro-journey/index'
@@ -1,64 +1,64 @@
1
- export { DefaultOutroBumper } from './default-outro-bumper'
2
- export { DefaultOutroBumperLandscape, DefaultOutroBumperLandscapeMetadata } from './default-outro-bumper'
3
- export { DefaultOutroBumperHorizontal, DefaultOutroBumperHorizontalMetadata } from './default-outro-bumper'
1
+ export { DefaultOutroBumper } from './default-outro-bumper/index'
2
+ export { DefaultOutroBumperLandscape, DefaultOutroBumperLandscapeMetadata } from './default-outro-bumper/index'
3
+ export { DefaultOutroBumperHorizontal, DefaultOutroBumperHorizontalMetadata } from './default-outro-bumper/index'
4
4
 
5
- export { DefaultCreditsRollOutro } from './default-credits-roll-outro'
6
- export { DefaultCreditsRollOutroLandscape, DefaultCreditsRollOutroLandscapeMetadata } from './default-credits-roll-outro'
7
- export { DefaultCreditsRollOutroHorizontal, DefaultCreditsRollOutroHorizontalMetadata } from './default-credits-roll-outro'
5
+ export { DefaultCreditsRollOutro } from './default-credits-roll-outro/index'
6
+ export { DefaultCreditsRollOutroLandscape, DefaultCreditsRollOutroLandscapeMetadata } from './default-credits-roll-outro/index'
7
+ export { DefaultCreditsRollOutroHorizontal, DefaultCreditsRollOutroHorizontalMetadata } from './default-credits-roll-outro/index'
8
8
 
9
- export { DefaultEpilogueOutro } from './default-epilogue-outro'
10
- export { DefaultEpilogueOutroLandscape, DefaultEpilogueOutroLandscapeMetadata } from './default-epilogue-outro'
11
- export { DefaultEpilogueOutroHorizontal, DefaultEpilogueOutroHorizontalMetadata } from './default-epilogue-outro'
9
+ export { DefaultEpilogueOutro } from './default-epilogue-outro/index'
10
+ export { DefaultEpilogueOutroLandscape, DefaultEpilogueOutroLandscapeMetadata } from './default-epilogue-outro/index'
11
+ export { DefaultEpilogueOutroHorizontal, DefaultEpilogueOutroHorizontalMetadata } from './default-epilogue-outro/index'
12
12
 
13
- export { DefaultBlackoutOutroBumper } from './default-blackout-outro-bumper'
13
+ export { DefaultBlackoutOutroBumper } from './default-blackout-outro-bumper/index'
14
14
  export {
15
15
  DefaultBlackoutOutroBumperLandscape,
16
16
  DefaultBlackoutOutroBumperLandscapeMetadata,
17
- } from './default-blackout-outro-bumper'
17
+ } from './default-blackout-outro-bumper/index'
18
18
  export {
19
19
  DefaultBlackoutOutroBumperHorizontal,
20
20
  DefaultBlackoutOutroBumperHorizontalMetadata,
21
- } from './default-blackout-outro-bumper'
21
+ } from './default-blackout-outro-bumper/index'
22
22
 
23
- export { DefaultSunsetOutroBumper } from './default-sunset-outro-bumper'
24
- export { DefaultSunsetOutroBumperLandscape, DefaultSunsetOutroBumperLandscapeMetadata } from './default-sunset-outro-bumper'
25
- export { DefaultSunsetOutroBumperHorizontal, DefaultSunsetOutroBumperHorizontalMetadata } from './default-sunset-outro-bumper'
26
- export { DefaultCreditsRollOutroRoyal } from './credits-roll-outro-royal'
23
+ export { DefaultSunsetOutroBumper } from './default-sunset-outro-bumper/index'
24
+ export { DefaultSunsetOutroBumperLandscape, DefaultSunsetOutroBumperLandscapeMetadata } from './default-sunset-outro-bumper/index'
25
+ export { DefaultSunsetOutroBumperHorizontal, DefaultSunsetOutroBumperHorizontalMetadata } from './default-sunset-outro-bumper/index'
26
+ export { DefaultCreditsRollOutroRoyal } from './credits-roll-outro-royal/index'
27
27
  export {
28
28
  DefaultCreditsRollOutroRoyalLandscape,
29
29
  DefaultCreditsRollOutroRoyalLandscapeMetadata,
30
- } from './credits-roll-outro-royal'
30
+ } from './credits-roll-outro-royal/index'
31
31
  export {
32
32
  DefaultCreditsRollOutroRoyalHorizontal,
33
33
  DefaultCreditsRollOutroRoyalHorizontalMetadata,
34
- } from './credits-roll-outro-royal'
35
- export { DefaultFestivalOutroBumper } from './festival-outro-encore'
34
+ } from './credits-roll-outro-royal/index'
35
+ export { DefaultFestivalOutroBumper } from './festival-outro-encore/index'
36
36
  export {
37
37
  DefaultFestivalOutroBumperLandscape,
38
38
  DefaultFestivalOutroBumperLandscapeMetadata,
39
- } from './festival-outro-encore'
39
+ } from './festival-outro-encore/index'
40
40
  export {
41
41
  DefaultFestivalOutroBumperHorizontal,
42
42
  DefaultFestivalOutroBumperHorizontalMetadata,
43
- } from './festival-outro-encore'
44
- export { DefaultAwardOutroBumper } from './award-outro-celebration'
43
+ } from './festival-outro-encore/index'
44
+ export { DefaultAwardOutroBumper } from './award-outro-celebration/index'
45
45
  export {
46
46
  DefaultAwardOutroBumperLandscape,
47
47
  DefaultAwardOutroBumperLandscapeMetadata,
48
- } from './award-outro-celebration'
48
+ } from './award-outro-celebration/index'
49
49
  export {
50
50
  DefaultAwardOutroBumperHorizontal,
51
51
  DefaultAwardOutroBumperHorizontalMetadata,
52
- } from './award-outro-celebration'
53
- export { DefaultMemoirOutroBumper } from './memoir-outro-reflection'
52
+ } from './award-outro-celebration/index'
53
+ export { DefaultMemoirOutroBumper } from './memoir-outro-reflection/index'
54
54
  export {
55
55
  DefaultMemoirOutroBumperLandscape,
56
56
  DefaultMemoirOutroBumperLandscapeMetadata,
57
- } from './memoir-outro-reflection'
57
+ } from './memoir-outro-reflection/index'
58
58
  export {
59
59
  DefaultMemoirOutroBumperHorizontal,
60
60
  DefaultMemoirOutroBumperHorizontalMetadata,
61
- } from './memoir-outro-reflection'
61
+ } from './memoir-outro-reflection/index'
62
62
 
63
63
  export {
64
64
  DefaultHeistOutroBumper,
@@ -66,9 +66,9 @@ export {
66
66
  DefaultHeistOutroBumperLandscapeMetadata,
67
67
  DefaultHeistOutroBumperHorizontal,
68
68
  DefaultHeistOutroBumperHorizontalMetadata,
69
- } from './heist-outro'
70
- export { DefaultRomanceOutroBumper } from './romance-outro'
71
- export { DefaultBlackoutOutroBumperFinale } from './blackout-outro-finale'
72
- export { DefaultSunsetOutroBumperCoda } from './sunset-outro-coda'
73
- export { DefaultCreditsRollOutroPremium } from './credits-roll-outro-premium'
74
- export { DefaultCreditsRollOutroEpic } from './credits-roll-outro-epic'
69
+ } from './heist-outro/index'
70
+ export { DefaultRomanceOutroBumper } from './romance-outro/index'
71
+ export { DefaultBlackoutOutroBumperFinale } from './blackout-outro-finale/index'
72
+ export { DefaultSunsetOutroBumperCoda } from './sunset-outro-coda/index'
73
+ export { DefaultCreditsRollOutroPremium } from './credits-roll-outro-premium/index'
74
+ export { DefaultCreditsRollOutroEpic } from './credits-roll-outro-epic/index'