@evatril/video-templates 2.0.0

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 (36) hide show
  1. package/package.json +14 -0
  2. package/public/Fonts/DancingScript-VariableFont_wght.ttf +0 -0
  3. package/public/Fonts/GreatVibes-Regular.ttf +0 -0
  4. package/public/Fonts/PlayfairDisplay-Italic-VariableFont_wght.ttf +0 -0
  5. package/public/video-images/20012026-bg.png +0 -0
  6. package/public/video-images/20012026-bride.png +0 -0
  7. package/public/video-images/20012026-butterfly.png +0 -0
  8. package/public/video-images/20012026-couple-walk.png +0 -0
  9. package/public/video-images/20012026-curtain-floral.png +0 -0
  10. package/public/video-images/20012026-floral-left.png +0 -0
  11. package/public/video-images/20012026-floral-right.png +0 -0
  12. package/public/video-images/20012026-groom.png +0 -0
  13. package/public/video-images/20012026-opening-gate.png +0 -0
  14. package/public/video-images/20012026-peacock.png +0 -0
  15. package/public/video-images/20012026-tree-left.png +0 -0
  16. package/public/video-images/20012026-tree-right.png +0 -0
  17. package/public/video-images/20012026-wedding-gate.png +0 -0
  18. package/public/video-images/wedding.mp3 +0 -0
  19. package/src/Invitations/Elements/Butterflies20012026.jsx +70 -0
  20. package/src/Invitations/Elements/CoupleWalk20012026.jsx +74 -0
  21. package/src/Invitations/Elements/FlowersSide20012026.jsx +143 -0
  22. package/src/Invitations/Elements/GroomBrideLoveScene20012026.jsx +163 -0
  23. package/src/Invitations/Elements/InkSmokeTransition20012026.jsx +72 -0
  24. package/src/Invitations/Elements/OpeningGate20012026.jsx +59 -0
  25. package/src/Invitations/Elements/PeacockDance20012026.jsx +68 -0
  26. package/src/Invitations/Elements/SideTrees20012026.jsx +104 -0
  27. package/src/Invitations/Elements/SmoothRevealFromTop.jsx +32 -0
  28. package/src/Invitations/Frames/F20012026_01.jsx +180 -0
  29. package/src/Invitations/Frames/F20012026_02.jsx +311 -0
  30. package/src/Invitations/Frames/F20012026_03.jsx +317 -0
  31. package/src/Invitations/Themes/T20012026_01.jsx +125 -0
  32. package/src/compositions.jsx +19 -0
  33. package/src/fonts/index.js +3 -0
  34. package/src/fonts/registerFonts.js +46 -0
  35. package/src/index.js +2 -0
  36. package/src/remotionRoot.jsx +5 -0
package/package.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "@evatril/video-templates",
3
+ "version": "2.0.0",
4
+ "description": "",
5
+ "main": "src/index.js",
6
+ "remotion": {
7
+ "entryPoint": "src/remotionRoot.jsx"
8
+ },
9
+ "peerDependencies": {
10
+ "react": ">=18",
11
+ "react-dom": ">=18",
12
+ "remotion": "^4.0.0"
13
+ }
14
+ }
Binary file
@@ -0,0 +1,70 @@
1
+ import React from "react";
2
+ import { Img, interpolate, staticFile } from "remotion";
3
+
4
+ export const Butterflies20012026 = ({ frame, fps, width, height }) => {
5
+ const GLOBAL_DELAY = fps * 2;
6
+ const butterflies = [
7
+ { sx: 0.1, sy: 0.9, ex: 0.8, ey: 0.2, delay: 0 },
8
+ { sx: 0.9, sy: 0.85, ex: 0.2, ey: 0.1, delay: 20 },
9
+ { sx: 0.3, sy: 1.0, ex: 0.7, ey: 0.3, delay: 40 },
10
+ ];
11
+
12
+ return (
13
+ <>
14
+ {butterflies.map((b, i) => {
15
+ const localFrame = frame - GLOBAL_DELAY - b.delay;
16
+ const progress = interpolate(
17
+ localFrame,
18
+ [0, fps * 6],
19
+ [0, 1],
20
+ {
21
+ extrapolateLeft: "clamp",
22
+ extrapolateRight: "clamp",
23
+ }
24
+ );
25
+
26
+ const x = interpolate(progress, [0, 1], [
27
+ b.sx * width,
28
+ b.ex * width,
29
+ ]);
30
+
31
+ const y =
32
+ interpolate(progress, [0, 1], [
33
+ b.sy * height,
34
+ b.ey * height,
35
+ ]) +
36
+ Math.sin(frame / 10 + i * 20) * 25;
37
+
38
+ const scale = interpolate(
39
+ progress,
40
+ [0, 0.1, 0.9, 1],
41
+ [0, 1, 1, 0.6]
42
+ );
43
+
44
+ const opacity = progress > 0.05 && progress < 0.95 ? 1 : 0;
45
+
46
+ return (
47
+ <Img
48
+ key={i}
49
+ src={staticFile("video-images/20012026-butterfly.png")}
50
+ style={{
51
+ position: "absolute",
52
+ left: x,
53
+ top: y,
54
+ width: 120,
55
+ height: 120,
56
+ opacity,
57
+ transform: `
58
+ translate(-50%, -50%)
59
+ scale(${scale})
60
+ rotate(${Math.sin(localFrame / 15 + i) * 15}deg)
61
+ `,
62
+ filter: "drop-shadow(0 0 6px rgba(0,255,255,0.45))",
63
+ pointerEvents: "none",
64
+ }}
65
+ />
66
+ );
67
+ })}
68
+ </>
69
+ );
70
+ };
@@ -0,0 +1,74 @@
1
+ import React from "react";
2
+ import {
3
+ Img,
4
+ staticFile,
5
+ useCurrentFrame,
6
+ useVideoConfig,
7
+ interpolate,
8
+ Easing,
9
+ } from "remotion";
10
+
11
+ export const CoupleWalk20012026 = () => {
12
+ const frame = useCurrentFrame();
13
+ const { fps, height } = useVideoConfig();
14
+
15
+ /* -----------------------------⏳ WALK SETTINGS ------------------------------*/
16
+ const delaySeconds = 0.5;
17
+ const walkDurationSeconds = 5;
18
+ const delayFrames = fps * delaySeconds;
19
+ const walkFrames = fps * walkDurationSeconds;
20
+ const localFrame = frame - delayFrames;
21
+ /* --------🚶 WALK FROM BOTTOM → UP (Bottom-center anchor)--------*/
22
+ const walkY = interpolate(
23
+ localFrame,
24
+ [0, walkFrames],
25
+ [height + 600, height - 950],
26
+ {
27
+ extrapolateLeft: "clamp",
28
+ extrapolateRight: "clamp",
29
+ easing: Easing.out(Easing.cubic),
30
+ }
31
+ );
32
+ const isWalking = localFrame >= 0 && localFrame <= walkFrames;
33
+
34
+ /* ------- ⬆️⬇️ SUBTLE BOUNCE -------*/
35
+ const bounce = isWalking
36
+ ? Math.sin(localFrame / 10) * 3
37
+ : 0;
38
+
39
+ /* ------- ↔️ NATURAL SWAY ------------*/
40
+ const sway = isWalking
41
+ ? Math.sin(localFrame / 14) * 2
42
+ : 0;
43
+
44
+ /* -------- 👣 FOOTSTEP SCALE ----------*/
45
+ const stepScale = isWalking
46
+ ? 1 + Math.sin(localFrame / 12) * 0.015
47
+ : 1;
48
+ return (
49
+ <div
50
+ style={{
51
+ flex: 1,
52
+ position: "relative",
53
+ overflow: "hidden",
54
+ }}
55
+ >
56
+
57
+ {/* 👰🤵 COUPLE (BOTTOM-CENTER) */}
58
+ <Img
59
+ src={staticFile("video-images/20012026-couple-walk.png")}
60
+ style={{
61
+ position: "absolute",
62
+ left: "50%",
63
+ transform: `
64
+ translateX(-50%)
65
+ translateY(${walkY + bounce}px)
66
+ translateX(${sway}px)
67
+ scale(${stepScale})
68
+ `,
69
+ width: "60%",
70
+ }}
71
+ />
72
+ </div>
73
+ );
74
+ };
@@ -0,0 +1,143 @@
1
+ import React from "react";
2
+ import {
3
+ Img,
4
+ staticFile,
5
+ useCurrentFrame,
6
+ useVideoConfig,
7
+ interpolate,
8
+ Easing,
9
+ } from "remotion";
10
+
11
+ /* 🌸 FALLING EMOJI FLOWER – MULTI LINE */
12
+ const FallingEmojiFlower = ({ index, row = 0, startAfter = 6 }) => {
13
+ const frame = useCurrentFrame();
14
+ const { height, width, fps } = useVideoConfig();
15
+
16
+ const delayFrames = fps * startAfter;
17
+
18
+ /* 🌸 CENTER STRIP */
19
+ const stripWidth = width * 0.28;
20
+ const baseX =
21
+ width / 2 - stripWidth / 2 + ((index * 50) % stripWidth);
22
+
23
+ /* 🌸 ROW OFFSET (2–3 LINES) */
24
+ const rowOffsetY = row * 60;
25
+
26
+ const individualDelay = index * 10 + row * 15;
27
+ const duration = fps * 4;
28
+
29
+ const localFrame = frame - delayFrames - individualDelay;
30
+
31
+ const progress = interpolate(
32
+ localFrame,
33
+ [0, duration],
34
+ [0, 1],
35
+ {
36
+ extrapolateLeft: "clamp",
37
+ extrapolateRight: "clamp",
38
+ }
39
+ );
40
+
41
+ const translateY = interpolate(
42
+ progress,
43
+ [0, 1],
44
+ [-80 + rowOffsetY, height + 80]
45
+ );
46
+
47
+ const sway =
48
+ progress < 1
49
+ ? Math.sin(localFrame / 15) * 14
50
+ : 0;
51
+
52
+ const rotate = progress * 360;
53
+
54
+ // ❌ Do not render before start or after finish
55
+ if (localFrame < 0 || localFrame > duration) return null;
56
+
57
+ return (
58
+ <div
59
+ style={{
60
+ position: "absolute",
61
+ left: baseX,
62
+ top: translateY,
63
+ fontSize: 44,
64
+ opacity: 0.85,
65
+ transform: `translateX(${sway}px) rotate(${rotate}deg)`,
66
+ pointerEvents: "none",
67
+ userSelect: "none",
68
+ }}
69
+ >
70
+ {["🌸", "🌺"][index % 2]}
71
+ </div>
72
+ );
73
+ };
74
+
75
+ export const FlowersSide20012026 = ({ startAfter = 1 }) => {
76
+ const frame = useCurrentFrame();
77
+ const { fps } = useVideoConfig();
78
+
79
+ const delayFrames = fps * startAfter;
80
+ const revealDuration = fps * 2.5; // ⏱ 2 seconds
81
+
82
+ const revealProgress = interpolate(
83
+ frame - delayFrames,
84
+ [0, revealDuration],
85
+ [0, 1],
86
+ {
87
+ extrapolateLeft: "clamp",
88
+ extrapolateRight: "clamp",
89
+ easing: Easing.out(Easing.cubic),
90
+ }
91
+ );
92
+
93
+ return (
94
+ <>
95
+ {/* 🌸 ONE-TIME FLOWER FALL (AFTER 2s) */}
96
+ {[0, 1, 2].map((row) =>
97
+ Array.from({ length: 5 }).map((_, i) => (
98
+ <FallingEmojiFlower
99
+ key={`row-${row}-${i}`}
100
+ index={i}
101
+ row={row}
102
+ startAfter={6}
103
+ />
104
+ ))
105
+ )}
106
+ {/* 🌸 LEFT FLOWER DECOR */}
107
+ <Img
108
+ src={staticFile("video-images/20012026-floral-left.png")}
109
+ style={{
110
+ position: "absolute",
111
+ left: 0,
112
+ bottom: 370,
113
+ width: "100%",
114
+ opacity: revealProgress,
115
+ transform: `
116
+ translateX(${interpolate(revealProgress, [0, 1], [-120, -30])}px)
117
+ scale(${interpolate(revealProgress, [0, 1], [0.96, 1])})
118
+ `,
119
+ pointerEvents: "none",
120
+ }}
121
+ />
122
+ {/* 🌸 RIGHT FLOWER DECOR */}
123
+ <Img
124
+ src={staticFile("video-images/20012026-floral-right.png")}
125
+ style={{
126
+ position: "absolute",
127
+ right: 0,
128
+ bottom: 370,
129
+ width: "100%",
130
+ opacity: revealProgress,
131
+ transform: `
132
+ translateX(${interpolate(revealProgress, [0, 1], [120, 30])}px)
133
+ scale(${interpolate(revealProgress, [0, 1], [0.96, 1])})
134
+ `,
135
+ pointerEvents: "none",
136
+ }}
137
+ />
138
+
139
+ </>
140
+ );
141
+ };
142
+
143
+
@@ -0,0 +1,163 @@
1
+ import React from "react";
2
+ import {
3
+ Img,
4
+ staticFile,
5
+ useCurrentFrame,
6
+ useVideoConfig,
7
+ interpolate,
8
+ Easing,
9
+ } from "remotion";
10
+
11
+ export const GroomBrideLoveScene20012026 = ({ startAfter = 3.5}) => {
12
+ const frame = useCurrentFrame();
13
+ const { fps, width } = useVideoConfig();
14
+
15
+ /* ---------------- TIMING ---------------- */
16
+ const showDelay = fps * startAfter; // when both appear
17
+ const walkDelay = showDelay + fps * 0.1; // groom starts walking after pause
18
+ const walkDuration = fps * 3.5; // slow cinematic walk
19
+
20
+ if (frame < showDelay) return null;
21
+
22
+ /* ---------------- OPACITY (BOTH SHOW SAME TIME) ---------------- */
23
+ const opacity = interpolate(
24
+ frame,
25
+ [showDelay, showDelay + fps * 0.5],
26
+ [0, 1],
27
+ { extrapolateLeft: "clamp" }
28
+ );
29
+
30
+ /* ---------------- WALK FRAME ---------------- */
31
+ const walkFrame = Math.max(0, frame - walkDelay);
32
+ const progress = interpolate(
33
+ walkFrame,
34
+ [0, walkDuration],
35
+ [0, 1],
36
+ {
37
+ extrapolateLeft: "clamp",
38
+ extrapolateRight: "clamp",
39
+ easing: Easing.inOut(Easing.cubic),
40
+ }
41
+ );
42
+
43
+ /* ---------------- POSITIONS ---------------- */
44
+ const brideX = width - 390; // 👰 fixed right
45
+ const groomStartX = -140; // 🤵 visible at left initially
46
+ const groomEndX = brideX - 260;
47
+
48
+ const groomX = interpolate(
49
+ progress,
50
+ [0, 1],
51
+ [groomStartX, groomEndX],
52
+ {
53
+ easing: Easing.inOut(Easing.cubic),
54
+ }
55
+ );
56
+
57
+ /* ---------------- 3D WALK MOTION ---------------- */
58
+ const footLift = Math.abs(Math.sin(walkFrame / 14)) * 8;
59
+ const bodySway = Math.sin(walkFrame / 26) * 6;
60
+ const depthScale = 1 + Math.sin(walkFrame / 18) * 0.03;
61
+ const rotateZ = Math.sin(walkFrame / 30) * 1.2;
62
+
63
+ /* ---------------- BRIDE TURN (SAFE FLIP) ---------------- */
64
+ const meetFrame = walkDelay + walkDuration;
65
+ const brideTurnDuration = fps * 0.6;
66
+ const brideFlip = interpolate(
67
+ frame,
68
+ [meetFrame, meetFrame + brideTurnDuration],
69
+ [1, -1], // RIGHT → LEFT
70
+ {
71
+ extrapolateLeft: "clamp",
72
+ extrapolateRight: "clamp",
73
+ easing: Easing.inOut(Easing.cubic),
74
+ }
75
+ );
76
+
77
+ /* ---------------- LOVE EMOJI ---------------- */
78
+ const loveStart = meetFrame + brideTurnDuration;
79
+ return (
80
+ <>
81
+ {/* 🤵 GROOM (SHOW → PAUSE → WALK) */}
82
+ <Img
83
+ src={staticFile("video-images/20012026-groom.png")}
84
+ style={{
85
+ position: "absolute",
86
+ bottom: 0,
87
+ width: "40%",
88
+ opacity,
89
+ transform: `
90
+ translateX(${groomX + bodySway}px)
91
+ translateY(${-footLift}px)
92
+ scale(${depthScale})
93
+ rotateZ(${rotateZ}deg)
94
+ `,
95
+ transformOrigin: "bottom center",
96
+ }}
97
+ />
98
+
99
+ {/* 👰 BRIDE (FIXED, SHOWS SAME TIME) */}
100
+ <Img
101
+ src={staticFile("video-images/20012026-bride.png")}
102
+ style={{
103
+ position: "absolute",
104
+ bottom: 0,
105
+ width: "40%",
106
+ opacity,
107
+ transform: `
108
+ translateX(${brideX}px)
109
+ scaleX(${brideFlip})
110
+ `,
111
+ transformOrigin: "bottom center",
112
+ }}
113
+ />
114
+ {/* ❤️ MULTIPLE FLOATING LOVE EMOJIS */}
115
+ {frame > loveStart &&
116
+ Array.from({ length: 16 }).map((_, i) => {
117
+ const emojiDelay = i * 8;
118
+ const emojiFrame = frame - loveStart - emojiDelay;
119
+
120
+ if (emojiFrame < 0) return null;
121
+
122
+ const floatY = interpolate(
123
+ emojiFrame,
124
+ [0, fps * 2.2],
125
+ [0, -240],
126
+ { extrapolateRight: "clamp" }
127
+ );
128
+
129
+ const emojiOpacity = interpolate(
130
+ emojiFrame,
131
+ [0, fps * 0.4, fps * 1.8],
132
+ [0, 1, 0],
133
+ { extrapolateRight: "clamp" }
134
+ );
135
+
136
+ const spreadX =
137
+ brideX + 60 + Math.sin(i * 35) * 100;
138
+
139
+ const scale = 0.7 + (i % 5) * 0.12;
140
+
141
+ return (
142
+ <div
143
+ key={i}
144
+ style={{
145
+ position: "absolute",
146
+ bottom: "30%",
147
+ left: spreadX,
148
+ fontSize: 66,
149
+ opacity: emojiOpacity,
150
+ transform: `
151
+ translateY(${floatY}px)
152
+ scale(${scale})
153
+ `,
154
+ pointerEvents: "none",
155
+ }}
156
+ >
157
+ 💖
158
+ </div>
159
+ );
160
+ })}
161
+ </>
162
+ );
163
+ };
@@ -0,0 +1,72 @@
1
+ import React from "react";
2
+ import {
3
+ AbsoluteFill,
4
+ useCurrentFrame,
5
+ useVideoConfig,
6
+ interpolate,
7
+ } from "remotion";
8
+
9
+ export const InkSmokeTransition20012026 = () => {
10
+ const frame = useCurrentFrame();
11
+ const { fps, width, height } = useVideoConfig();
12
+
13
+ const duration = fps * 1.2;
14
+
15
+ return (
16
+ <AbsoluteFill
17
+ style={{
18
+ pointerEvents: "none",
19
+ overflow: "hidden",
20
+ }}
21
+ >
22
+ {Array.from({ length: 12 }).map((_, i) => {
23
+ const delay = i * 3;
24
+ const localFrame = Math.max(0, frame - delay);
25
+
26
+ const scale = interpolate(
27
+ localFrame,
28
+ [0, duration],
29
+ [0.3, 3.4],
30
+ { extrapolateRight: "clamp" }
31
+ );
32
+
33
+ const opacity = interpolate(
34
+ localFrame,
35
+ [0, duration * 0.4, duration],
36
+ [0, 0.8, 0],
37
+ { extrapolateRight: "clamp" }
38
+ );
39
+
40
+ /* 🔑 CENTER-OUT POSITIONING */
41
+ const angle = (i / 12) * Math.PI * 2; // circular spread
42
+ const radius = 120; // initial spread radius
43
+
44
+ const offsetX = Math.cos(angle) * radius;
45
+ const offsetY = Math.sin(angle) * radius;
46
+
47
+ return (
48
+ <div
49
+ key={i}
50
+ style={{
51
+ position: "absolute",
52
+ width: 320 + i * 40,
53
+ height: 320 + i * 40,
54
+ borderRadius: "50%",
55
+ background:
56
+ "radial-gradient(circle, rgba(255,210,220,0.9), rgba(255,255,255,0.4))",
57
+
58
+ /* 🎯 START FROM CENTER */
59
+ left: width / 2 + offsetX - (320 + i * 40) / 2,
60
+ top: height / 2 + offsetY - (320 + i * 40) / 2,
61
+
62
+ transform: `scale(${scale})`,
63
+ opacity,
64
+ filter: "blur(35px)",
65
+ mixBlendMode: "screen",
66
+ }}
67
+ />
68
+ );
69
+ })}
70
+ </AbsoluteFill>
71
+ );
72
+ };
@@ -0,0 +1,59 @@
1
+ import React from "react";
2
+ import { Img, interpolate, Easing, staticFile } from "remotion";
3
+
4
+ export const OpeningGate20012026 = ({ frame, fps }) => {
5
+ // ⏱ 1 second gate opening
6
+ const OPEN_DURATION = fps * 1;
7
+
8
+ const progress = interpolate(
9
+ frame,
10
+ [0, OPEN_DURATION],
11
+ [0, 1],
12
+ {
13
+ extrapolateLeft: "clamp",
14
+ extrapolateRight: "clamp",
15
+ easing: Easing.out(Easing.ease),
16
+ }
17
+ );
18
+
19
+ const leftRotate = interpolate(progress, [0, 1], [0, -90]);
20
+ const rightRotate = interpolate(progress, [0, 1], [0, 90]);
21
+
22
+ return (
23
+ <div
24
+ style={{
25
+ position: "absolute",
26
+ inset: 0,
27
+ overflow: "hidden",
28
+ zIndex: 9999,
29
+ pointerEvents: "none",
30
+ }}
31
+ >
32
+ {/* 🚪 LEFT DOOR */}
33
+ <Img
34
+ src={staticFile("video-images/20012026-opening-gate.png")}
35
+ style={{
36
+ position: "absolute",
37
+ bottom: 0,
38
+ left: 0,
39
+ width: "100%",
40
+ transformOrigin: "left center",
41
+ transform: `perspective(9000px) rotateY(${leftRotate}deg)`,
42
+ }}
43
+ />
44
+
45
+ {/* 🚪 RIGHT DOOR */}
46
+ <Img
47
+ src={staticFile("video-images/20012026-opening-gate.png")}
48
+ style={{
49
+ position: "absolute",
50
+ bottom: 0,
51
+ right: 0,
52
+ width: "100%",
53
+ transformOrigin: "right center",
54
+ transform: `perspective(9000px) rotateY(${rightRotate}deg)`,
55
+ }}
56
+ />
57
+ </div>
58
+ );
59
+ };