@evatril/video-templates 2.0.6 → 2.0.8

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 (59) hide show
  1. package/package.json +1 -1
  2. package/public/video-images/03022026-bg-2.webp +0 -0
  3. package/public/video-images/03022026-bg-3.webp +0 -0
  4. package/public/video-images/03022026-bg-4.webp +0 -0
  5. package/public/video-images/03022026-bg-5.webp +0 -0
  6. package/public/video-images/03022026-bg.webp +0 -0
  7. package/public/video-images/03022026-krishnaradha-2.webp +0 -0
  8. package/public/video-images/03022026-krishnaradha-4.webp +0 -0
  9. package/public/video-images/03022026-krishnaradha-5.webp +0 -0
  10. package/public/video-images/03022026-krishnaradha.webp +0 -0
  11. package/public/video-images/20012026-bg.png +0 -0
  12. package/public/video-images/20012026-bride.png +0 -0
  13. package/public/video-images/20012026-butterfly.png +0 -0
  14. package/public/video-images/20012026-couple-walk.png +0 -0
  15. package/public/video-images/20012026-floral-left.png +0 -0
  16. package/public/video-images/20012026-groom.png +0 -0
  17. package/public/video-images/20012026-peacock.png +0 -0
  18. package/public/video-images/20012026-wedding-gate.png +0 -0
  19. package/public/video-images/28012026-BottomLeftFlower.webp +0 -0
  20. package/public/video-images/28012026-BottomRightFlower.webp +0 -0
  21. package/public/video-images/28012026-FlowerBorder.webp +0 -0
  22. package/public/video-images/28012026-Ganesh.webp +0 -0
  23. package/public/video-images/28012026-TopBorder.webp +0 -0
  24. package/public/video-images/28012026-TopLeftFlower.webp +0 -0
  25. package/public/video-images/28012026-TopRightFlower.webp +0 -0
  26. package/public/video-images/28012026-bg.webp +0 -0
  27. package/public/video-images/28012026-border.webp +0 -0
  28. package/public/video-images/28012026-frame.webp +0 -0
  29. package/public/video-images/wedding2.mp3 +0 -0
  30. package/src/Invitations/Elements/BlowingLeaves28012026.jsx +68 -0
  31. package/src/Invitations/Elements/FlowerReveal_TL_BR_28012026.jsx +114 -0
  32. package/src/Invitations/Elements/FlowerReveal_TR_BL_28012026.jsx +116 -0
  33. package/src/Invitations/Elements/GaneshBorder28012026.jsx +95 -0
  34. package/src/Invitations/Elements/GaneshGoldenHalo.jsx +90 -0
  35. package/src/Invitations/Elements/HeartDraw28012026.jsx +51 -0
  36. package/src/Invitations/Elements/HeartFlight28012026.jsx +72 -0
  37. package/src/Invitations/Elements/HoldSlide.jsx +103 -0
  38. package/src/Invitations/Elements/LetterReveal28012026.jsx +47 -0
  39. package/src/Invitations/Elements/PageFlipTransition.jsx +180 -0
  40. package/src/Invitations/Elements/{SmoothRevealFromTop.jsx → SmoothRevealFromTop20012026.jsx} +1 -1
  41. package/src/Invitations/Elements/WordReveal28012026.jsx +92 -0
  42. package/src/Invitations/Frames/F03022026_01.jsx +214 -0
  43. package/src/Invitations/Frames/F03022026_02.jsx +312 -0
  44. package/src/Invitations/Frames/F03022026_03.jsx +332 -0
  45. package/src/Invitations/Frames/F03022026_04.jsx +300 -0
  46. package/src/Invitations/Frames/F03022026_05.jsx +235 -0
  47. package/src/Invitations/Frames/F20012026_01.jsx +0 -14
  48. package/src/Invitations/Frames/F20012026_02.jsx +125 -224
  49. package/src/Invitations/Frames/F20012026_03.jsx +29 -57
  50. package/src/Invitations/Frames/F28012026_01.jsx +51 -0
  51. package/src/Invitations/Frames/F28012026_02.jsx +246 -0
  52. package/src/Invitations/Frames/F28012026_03.jsx +268 -0
  53. package/src/Invitations/Frames/F28012026_04.jsx +275 -0
  54. package/src/Invitations/Frames/F28012026_05.jsx +179 -0
  55. package/src/Invitations/Themes/T03022026_01.jsx +269 -0
  56. package/src/Invitations/Themes/T20012026_01.jsx +75 -33
  57. package/src/Invitations/Themes/T28012026_01.jsx +241 -0
  58. package/src/compositions.jsx +21 -4
  59. package/src/index.js +3 -1
@@ -0,0 +1,275 @@
1
+ import React from "react";
2
+ import {
3
+ AbsoluteFill,
4
+ useCurrentFrame,
5
+ useVideoConfig,
6
+ interpolate,
7
+ Easing,
8
+ Img,
9
+ staticFile,
10
+ } from "remotion";
11
+ import { HeartFlight28012026 } from "../Elements/HeartFlight28012026";
12
+
13
+ export const F28012026_04 = ({
14
+ secondName,
15
+ secondSideNote,
16
+ secondPhoto,
17
+
18
+ }) => {
19
+ const frame = useCurrentFrame();
20
+ const { fps } = useVideoConfig();
21
+
22
+ const topBorderStart = fps * 0;
23
+
24
+ const topBorderOpacity = interpolate(
25
+ frame,
26
+ [topBorderStart, topBorderStart + 20],
27
+ [0, 1],
28
+ {
29
+ extrapolateRight: "clamp",
30
+ easing: Easing.out(Easing.ease),
31
+ }
32
+ );
33
+
34
+ const topBorderTranslate = interpolate(
35
+ frame,
36
+ [topBorderStart, topBorderStart + 20],
37
+ [-60, 0], // slides DOWN from top
38
+ {
39
+ extrapolateRight: "clamp",
40
+ }
41
+ );
42
+
43
+ const borderStart = fps * 1; // border at 1s
44
+ const photoStart = borderStart + 20; // photo after border
45
+
46
+ const borderOpacity = interpolate(frame, [borderStart, borderStart + 25], [0, 1], {
47
+ extrapolateRight: "clamp",
48
+ easing: Easing.out(Easing.ease),
49
+ });
50
+
51
+ const borderScale = interpolate(frame, [borderStart, borderStart + 25], [0.7, 1], {
52
+ extrapolateRight: "clamp",
53
+ });
54
+
55
+ const photoOpacity = interpolate(frame, [photoStart, photoStart + 25], [0, 1], {
56
+ extrapolateRight: "clamp",
57
+ });
58
+
59
+ const photoScale = interpolate(frame, [photoStart, photoStart + 25], [0.7, 1], {
60
+ extrapolateRight: "clamp",
61
+ });
62
+
63
+ const nameStart = fps * 2.5; // adjust timing if needed
64
+
65
+ const nameOpacity = interpolate(frame, [nameStart, nameStart + 20], [0, 1], {
66
+ extrapolateRight: "clamp",
67
+ easing: Easing.out(Easing.ease),
68
+ });
69
+
70
+
71
+ const nameTranslateX = interpolate(
72
+ frame,
73
+ [
74
+ nameStart,
75
+ nameStart + fps * 2,
76
+ nameStart + fps * 2.3,
77
+ ],
78
+ [-600, 10, 0],
79
+ {
80
+ extrapolateLeft: "clamp",
81
+ extrapolateRight: "clamp",
82
+ easing: Easing.inOut(Easing.cubic),
83
+ }
84
+ );
85
+
86
+ const emojiStart = nameStart + 20;
87
+
88
+ const emojiOpacity = interpolate(frame, [emojiStart, emojiStart + 20], [0, 1], {
89
+ extrapolateRight: "clamp",
90
+ easing: Easing.out(Easing.ease),
91
+ });
92
+
93
+ const emojiTranslateX = interpolate(
94
+ frame,
95
+ [
96
+ emojiStart,
97
+ emojiStart + fps * 2,
98
+ emojiStart + fps * 2.3,
99
+ ],
100
+ [-600, 10, 0],
101
+ {
102
+ extrapolateLeft: "clamp",
103
+ extrapolateRight: "clamp",
104
+ easing: Easing.inOut(Easing.cubic),
105
+ }
106
+ );
107
+
108
+
109
+ const sideNoteStart = nameStart + fps * 1.5; // appears ~0.8s after name
110
+
111
+ const sideOpacity = interpolate(frame, [sideNoteStart, sideNoteStart + 20], [0, 1], {
112
+ extrapolateRight: "clamp",
113
+ easing: Easing.out(Easing.ease),
114
+ });
115
+
116
+ const sideTranslateX = interpolate(
117
+ frame,
118
+ [
119
+ sideNoteStart,
120
+ sideNoteStart + fps * 2,
121
+ sideNoteStart + fps * 2.3,
122
+ ],
123
+ [-600, 10, 0],
124
+ {
125
+ extrapolateLeft: "clamp",
126
+ extrapolateRight: "clamp",
127
+ easing: Easing.inOut(Easing.cubic),
128
+ }
129
+ );
130
+
131
+
132
+ return (
133
+ <AbsoluteFill
134
+ style={{
135
+ overflow: "hidden",
136
+ }}
137
+ >
138
+ {/* <MultiHeartFloat28012026 startAfter={3} count={18} emoji="💖" /> */}
139
+ <HeartFlight28012026 emoji="💗" />
140
+
141
+ {/* Top Border */}
142
+ <div
143
+ style={{
144
+ position: "absolute",
145
+ top: 0,
146
+ left: 10,
147
+ width: "100%",
148
+ display: "flex",
149
+ justifyContent: "center",
150
+ }}
151
+ >
152
+ <Img
153
+ src={staticFile("video-images/28012026-TopBorder.webp")}
154
+ style={{
155
+ width: "90%",
156
+ transform: `translateY(${topBorderTranslate}px) scale(1.2)`,
157
+ opacity: topBorderOpacity,
158
+ }}
159
+ />
160
+ </div>
161
+
162
+ {secondPhoto && (
163
+ <div
164
+ style={{
165
+ position: "absolute",
166
+ top: "12%",
167
+ left: "50%",
168
+ transform: "translateX(-50%)",
169
+ width: 860,
170
+ height: 860,
171
+ pointerEvents: "none",
172
+ zIndex: 2,
173
+ }}
174
+ >
175
+ {/* BORDER */}
176
+ <Img
177
+ src={staticFile("video-images/28012026-border.webp")}
178
+ style={{
179
+ position: "absolute",
180
+ inset: 0,
181
+ width: "100%",
182
+ height: "100%",
183
+ opacity: borderOpacity,
184
+ transform: `scale(${borderScale})`,
185
+ zIndex: 1
186
+ }}
187
+ />
188
+
189
+ {/* BRIDE PHOTO */}
190
+ <Img
191
+ src={secondPhoto}
192
+ style={{
193
+ position: "absolute",
194
+ inset: 0,
195
+ margin: "auto",
196
+ width: "72%",
197
+ height: "70%",
198
+ bottom: "15%",
199
+ objectFit: "cover",
200
+ borderRadius: "50%",
201
+ opacity: photoOpacity,
202
+ transform: `scale(${photoScale})`,
203
+ }}
204
+ />
205
+ </div>
206
+ )}
207
+
208
+ {/* NAME + SIDE NOTE UNDER IMAGE */}
209
+ <div
210
+ style={{
211
+ position: "absolute",
212
+ top: "60%",
213
+ width: "100%",
214
+ textAlign: "center",
215
+ opacity: nameOpacity,
216
+
217
+ }}
218
+ >
219
+ <h1
220
+ style={{
221
+ fontFamily: "Dancing Script",
222
+ color: "#C94A6A",
223
+ fontSize: 100,
224
+ letterSpacing: 3,
225
+ margin: "0 auto 35px auto",
226
+ maxWidth: "80%",
227
+ lineHeight: "1.3",
228
+ fontWeight: "600",
229
+ opacity: nameOpacity,
230
+ transform: `translateX(${nameTranslateX}px)`,
231
+ }}
232
+ >
233
+ {secondName}
234
+
235
+ </h1>
236
+
237
+ <div
238
+ style={{
239
+ display: "flex",
240
+ justifyContent: "center",
241
+ alignItems: "center",
242
+ gap: 12,
243
+ fontSize: 60,
244
+ marginBottom: 25,
245
+ opacity: emojiOpacity,
246
+ transform: `translateX(${emojiTranslateX}px)`,
247
+ }}
248
+ >
249
+ ✨ ✨
250
+ </div>
251
+
252
+ <div
253
+ style={{
254
+ fontFamily: "Playfair Display",
255
+ color: "#8A7A5A",
256
+ fontSize: 50,
257
+ letterSpacing: 3,
258
+ margin: "0 auto",
259
+ maxWidth: "80%",
260
+ lineHeight: "1.3",
261
+ fontWeight: "600",
262
+ opacity: sideOpacity,
263
+ transform: `translateX(${sideTranslateX}px)`,
264
+ }}
265
+ >
266
+ {secondSideNote}
267
+ </div>
268
+ </div>
269
+
270
+
271
+
272
+
273
+ </AbsoluteFill>
274
+ );
275
+ };
@@ -0,0 +1,179 @@
1
+ import React from "react";
2
+ import {
3
+ AbsoluteFill,
4
+ Img,
5
+ useCurrentFrame,
6
+ useVideoConfig,
7
+ interpolate,
8
+ Easing,
9
+ staticFile,
10
+ } from "remotion";
11
+ import { WordReveal28012026 } from "../Elements/WordReveal28012026";
12
+
13
+ export const F28012026_05 = ({
14
+ eventDateTime,
15
+ venueName,
16
+ venueAddress,
17
+ familyMember,
18
+ }) => {
19
+ const frame = useCurrentFrame();
20
+ const { fps, height } = useVideoConfig();
21
+
22
+ // 🔥 Start animation immediately
23
+ const safeFrame = frame;
24
+
25
+ // 🌿 Slow elegant downward slide (3 seconds)
26
+ const frameY = interpolate(
27
+ safeFrame,
28
+ [0, fps * 3],
29
+ [-height, 0],
30
+ {
31
+ extrapolateLeft: "clamp",
32
+ extrapolateRight: "clamp",
33
+ easing: Easing.out(Easing.cubic),
34
+ }
35
+ );
36
+
37
+ // ✨ Gentle fade in
38
+ const opacity = interpolate(
39
+ safeFrame,
40
+ [0, fps * 1.5],
41
+ [0, 1],
42
+ {
43
+ extrapolateLeft: "clamp",
44
+ extrapolateRight: "clamp",
45
+ }
46
+ );
47
+
48
+ // Text start timing
49
+ const frameStart = fps * 0.5;
50
+
51
+ const getDateParts = (iso) => {
52
+ if (!iso) return { day: "", month: "", year: "", time: "" };
53
+
54
+ const d = new Date(iso);
55
+
56
+ return {
57
+ day: d.getDate(),
58
+ month: d.toLocaleString("en-US", { month: "long" }),
59
+ year: d.getFullYear(),
60
+ time: d.toLocaleTimeString("en-US", {
61
+ hour: "2-digit",
62
+ minute: "2-digit",
63
+ hour12: true,
64
+ }),
65
+ };
66
+ };
67
+
68
+ const { day, month, year, time } = getDateParts(eventDateTime);
69
+
70
+ const textWrapper = {
71
+ maxWidth: "70%",
72
+ textAlign: "center",
73
+ margin: "0 auto",
74
+ };
75
+
76
+ return (
77
+ <AbsoluteFill style={{ overflow: "hidden" }}>
78
+ {/* Background Frame */}
79
+ <Img
80
+ src={staticFile("video-images/28012026-frame.webp")}
81
+ style={{
82
+ position: "absolute",
83
+ inset: 0,
84
+ width: "100%",
85
+ height: "100%",
86
+ objectFit: "cover",
87
+ transform: `translateY(${frameY}px)`,
88
+ opacity,
89
+ }}
90
+ />
91
+
92
+ {/* Text Content */}
93
+ <div
94
+ style={{
95
+ position: "absolute",
96
+ inset: 0,
97
+ display: "flex",
98
+ flexDirection: "column",
99
+ justifyContent: "start",
100
+ alignItems: "center",
101
+ paddingTop: "40%",
102
+ gap: 30,
103
+ zIndex: 5,
104
+ }}
105
+ >
106
+ <div style={textWrapper}>
107
+ <WordReveal28012026
108
+ text={venueName}
109
+ start={frameStart + 40}
110
+ fontSize={70}
111
+ color="#7B1E3A"
112
+ fontFamily="Playfair Display"
113
+ />
114
+ </div>
115
+
116
+ <div style={textWrapper}>
117
+ <WordReveal28012026
118
+ text={venueAddress}
119
+ start={frameStart + 50}
120
+ fontSize={60}
121
+ color="#4A3A2A"
122
+ fontFamily="Playfair Display"
123
+ />
124
+ </div>
125
+
126
+ <div style={textWrapper}>
127
+ <WordReveal28012026
128
+ text="On the joyous occasion"
129
+ start={frameStart + 60}
130
+ fontSize={70}
131
+ color="#6B1E2E"
132
+ fontFamily="Dancing Script"
133
+ />
134
+ </div>
135
+
136
+ <div style={textWrapper}>
137
+ <WordReveal28012026
138
+ text={`${day} ${month} ${year}`}
139
+ start={frameStart + 80}
140
+ fontSize={60}
141
+ color="#8A6A3F"
142
+ fontFamily="Great Vibes"
143
+ letterSpacing={6}
144
+ />
145
+ </div>
146
+
147
+ <div style={textWrapper}>
148
+ <WordReveal28012026
149
+ text="Wedding Time"
150
+ start={frameStart + 100}
151
+ fontSize={60}
152
+ color="#7B1E3A"
153
+ fontFamily="Dancing Script"
154
+ />
155
+ </div>
156
+
157
+ <div style={textWrapper}>
158
+ <WordReveal28012026
159
+ text={time}
160
+ start={frameStart + 110}
161
+ fontSize={60}
162
+ color="#4B3A28"
163
+ fontFamily="Dancing Script"
164
+ />
165
+ </div>
166
+
167
+ <div style={textWrapper}>
168
+ <WordReveal28012026
169
+ text={familyMember}
170
+ start={frameStart + 130}
171
+ fontSize={50}
172
+ color="#B2455D"
173
+ fontFamily="Playfair Display"
174
+ />
175
+ </div>
176
+ </div>
177
+ </AbsoluteFill>
178
+ );
179
+ };
@@ -0,0 +1,269 @@
1
+ import React, { useMemo } from "react";
2
+ import {
3
+ Sequence,
4
+ useVideoConfig,
5
+ Audio,
6
+ staticFile,
7
+ AbsoluteFill,
8
+ Img,
9
+ useCurrentFrame,
10
+ interpolate,
11
+ Easing,
12
+ } from "remotion";
13
+
14
+ import { usePreloadImages } from "../hooks/usePreloadImages.js";
15
+ import { F03022026_01 } from "../Frames/F03022026_01.jsx";
16
+ import { F03022026_02 } from "../Frames/F03022026_02.jsx";
17
+ import { F03022026_03 } from "../Frames/F03022026_03.jsx";
18
+ import { F03022026_04 } from "../Frames/F03022026_04.jsx";
19
+ import { F03022026_05 } from "../Frames/F03022026_05.jsx";
20
+ import { HoldSlide } from "../Elements/HoldSlide.jsx";
21
+
22
+ export const T03022026_01 = ({
23
+ event,
24
+ formData,
25
+ eventDateTime,
26
+ occasionDate,
27
+ venue,
28
+ welcomeMessage,
29
+ invitationMessage,
30
+ familyMember,
31
+ }) => {
32
+ const frame = useCurrentFrame();
33
+ const { fps, durationInFrames } = useVideoConfig();
34
+
35
+ /* ---------------- MUSIC FADE ---------------- */
36
+ const fadeDuration = 2 * fps;
37
+ const fadeOutStart = durationInFrames - fadeDuration;
38
+ const musicVolume = interpolate(
39
+ frame,
40
+ [0, fadeOutStart, durationInFrames],
41
+ [0.4, 0.4, 0],
42
+ {
43
+ easing: Easing.inOut(Easing.ease),
44
+ extrapolateLeft: "clamp",
45
+ extrapolateRight: "clamp",
46
+ }
47
+ );
48
+ const slideDuration = 1 * fps;
49
+
50
+ const firstSceneContent = 5 * fps;
51
+ const secondSceneContent = 6 * fps;
52
+ const thirdSceneContent = 7 * fps;
53
+ const fourSceneContent = 7 * fps;
54
+ const fiveSceneContent = 9 * fps;
55
+ const firstSceneDuration = firstSceneContent + slideDuration;
56
+ const secondSceneDuration = secondSceneContent + slideDuration;
57
+ const thirdSceneDuration = thirdSceneContent + slideDuration;
58
+ const fourSceneDuration = fourSceneContent + slideDuration;
59
+ const fiveSceneDuration = fiveSceneContent + slideDuration;
60
+
61
+ /* ---------------- SAFE DATA ---------------- */
62
+ const whoIsCreating =
63
+ event?.eventData?.occasion_data?.who_is_creating ??
64
+ event?.occasion_data?.who_is_creating ??
65
+ event?.who_is_creating;
66
+
67
+ const isBrideCreating =
68
+ whoIsCreating === "Bride" || !whoIsCreating;
69
+
70
+ const brideName =
71
+ event?.eventData?.occasion_data?.bride_name ??
72
+ event?.occasion_data?.bride_name ??
73
+ formData?.bride_name ??
74
+ "";
75
+
76
+ const groomName =
77
+ event?.eventData?.occasion_data?.groom_name ??
78
+ event?.occasion_data?.groom_name ??
79
+ formData?.groom_name ??
80
+ "";
81
+
82
+ const bridePhoto =
83
+ event?.eventData?.occasion_data?.bride_photo?.url ??
84
+ event?.occasion_data?.bride_photo?.url ??
85
+ formData?.bride_photo ??
86
+ "";
87
+
88
+ const groomPhoto =
89
+ event?.eventData?.occasion_data?.groom_photo?.url ??
90
+ event?.occasion_data?.groom_photo?.url ??
91
+ formData?.groom_photo ??
92
+ "";
93
+
94
+ const firstName = isBrideCreating ? brideName : groomName;
95
+ const secondName = isBrideCreating ? groomName : brideName;
96
+
97
+ const firstPhoto = isBrideCreating ? bridePhoto : groomPhoto;
98
+ const secondPhoto = isBrideCreating ? groomPhoto : bridePhoto;
99
+
100
+
101
+ const firstSideNote = isBrideCreating
102
+ ? formData?.bride_side_note || ""
103
+ : formData?.groom_side_note || "";
104
+
105
+ const secondSideNote = isBrideCreating
106
+ ? formData?.groom_side_note || ""
107
+ : formData?.bride_side_note || "";
108
+
109
+ const venueName =
110
+ venue?.name || formData?.venue_name || "";
111
+
112
+ const venueAddress =
113
+ venue?.address || formData?.venue_address || "";
114
+
115
+ /* ---------------- PRELOAD IMAGES ---------------- */
116
+
117
+ const imagesToPreload = useMemo(
118
+ () => [
119
+ staticFile("video-images/03022026-bg.webp"),
120
+ staticFile("video-images/03022026-bg-2.webp"),
121
+ staticFile("video-images/03022026-bg-3.webp"),
122
+ staticFile("video-images/03022026-bg-4.webp"),
123
+ staticFile("video-images/03022026-bg-5.webp"),
124
+ staticFile("video-images/03022026-krishnaradha.webp"),
125
+ staticFile("video-images/03022026-krishnaradha-2.webp"),
126
+ staticFile("video-images/03022026-krishnaradha-4.webp"),
127
+ staticFile("video-images/03022026-krishnaradha-5.webp"),
128
+ ],
129
+ []
130
+ );
131
+
132
+ usePreloadImages(imagesToPreload);
133
+
134
+ const Page = ({ bg, children }) => (
135
+ <AbsoluteFill>
136
+ <Img
137
+ src={bg}
138
+ style={{
139
+ position: "absolute",
140
+ inset: 0,
141
+ width: "100%",
142
+ height: "100%",
143
+ objectFit: "cover",
144
+ }}
145
+ />
146
+ {children}
147
+ </AbsoluteFill>
148
+ );
149
+
150
+ const backgrounds = useMemo(
151
+ () => [
152
+ staticFile("video-images/03022026-bg.webp"),
153
+ staticFile("video-images/03022026-bg-2.webp"),
154
+ staticFile("video-images/03022026-bg-3.webp"),
155
+ staticFile("video-images/03022026-bg-4.webp"),
156
+ staticFile("video-images/03022026-bg-5.webp"),
157
+ ],
158
+ []
159
+ );
160
+
161
+ return (
162
+ <AbsoluteFill>
163
+ {/* 🎵 MUSIC */}
164
+ <Audio
165
+ src={staticFile("video-images/wedding2.mp3")}
166
+ volume={musicVolume}
167
+ />
168
+
169
+ {/* 🌸 SCENE 1 (0–10s) */}
170
+ <Sequence from={0} durationInFrames={firstSceneDuration}>
171
+ <HoldSlide
172
+ contentDuration={firstSceneContent}
173
+ slideDuration={slideDuration}
174
+ nextBg={backgrounds[1]}
175
+ >
176
+ <Page bg={backgrounds[0]}>
177
+ <F03022026_01 />
178
+ </Page>
179
+ </HoldSlide>
180
+ </Sequence>
181
+
182
+ {/* 🌸 SCENE 2 (10–20s) */}
183
+ <Sequence from={firstSceneDuration} durationInFrames={secondSceneDuration}>
184
+ <HoldSlide
185
+ contentDuration={secondSceneContent}
186
+ slideDuration={slideDuration}
187
+ nextBg={backgrounds[2]}
188
+ >
189
+ <Page bg={backgrounds[1]}>
190
+ <F03022026_02
191
+ firstName={firstName}
192
+ secondName={secondName}
193
+ welcomeMessage={welcomeMessage}
194
+ occasionDate={occasionDate}
195
+ />
196
+ </Page>
197
+ </HoldSlide>
198
+ </Sequence>
199
+
200
+ {/* 🌸 SCENE 3 (20–30s) */}
201
+ <Sequence
202
+ from={firstSceneDuration + secondSceneDuration}
203
+ durationInFrames={thirdSceneDuration}
204
+ >
205
+ <HoldSlide
206
+ contentDuration={thirdSceneContent}
207
+ slideDuration={slideDuration}
208
+ nextBg={backgrounds[3]}
209
+
210
+ >
211
+ <Page bg={backgrounds[2]}>
212
+ <F03022026_03
213
+ firstName={firstName}
214
+ firstPhoto={firstPhoto}
215
+ firstSideNote={firstSideNote}
216
+ secondName={secondName}
217
+ secondPhoto={secondPhoto}
218
+ secondSideNote={secondSideNote}
219
+ invitationMessage={invitationMessage}
220
+ />
221
+ </Page>
222
+ </HoldSlide>
223
+ </Sequence>
224
+
225
+ {/* SCENE 4 */}
226
+ <Sequence
227
+ from={firstSceneDuration + secondSceneDuration + thirdSceneDuration}
228
+ durationInFrames={fourSceneDuration}
229
+ >
230
+ <HoldSlide
231
+ contentDuration={fourSceneContent}
232
+ slideDuration={slideDuration}
233
+ nextBg={backgrounds[4]}
234
+ >
235
+ <Page bg={backgrounds[3]}>
236
+ <F03022026_04
237
+ eventDateTime={eventDateTime}
238
+ venueName={venueName}
239
+ venueAddress={venueAddress}
240
+ />
241
+ </Page>
242
+ </HoldSlide>
243
+ </Sequence>
244
+
245
+ {/* SCENE 5 */}
246
+ <Sequence
247
+ from={
248
+ firstSceneDuration +
249
+ secondSceneDuration +
250
+ thirdSceneDuration +
251
+ fourSceneDuration
252
+ }
253
+ durationInFrames={fiveSceneDuration}
254
+ >
255
+ <HoldSlide
256
+ contentDuration={fiveSceneContent}
257
+ slideDuration={slideDuration}
258
+ >
259
+ <Page bg={backgrounds[4]}>
260
+ <F03022026_05 familyMember={familyMember} />
261
+ </Page>
262
+ </HoldSlide>
263
+ </Sequence>
264
+
265
+ </AbsoluteFill>
266
+ );
267
+ };
268
+
269
+ T03022026_01.duration = 30 * 38;