Muhammad-Mehdi's picture
Backend and remotion-video for HF Space
cfe45d5
Raw
History Blame Contribute Delete
4.64 kB
import {
AbsoluteFill,
interpolate,
useCurrentFrame,
useVideoConfig,
} from "remotion";
interface TextSceneProps {
title: string;
narration: string;
imageUrl?: string;
}
const ACCENT = "#7C3AED"; // Signature purple
export const TextScene: React.FC<TextSceneProps> = ({
title,
narration,
}) => {
const frame = useCurrentFrame();
const { durationInFrames } = useVideoConfig();
// Animations
const titleOpacity = interpolate(frame, [0, 20], [0, 1], {
extrapolateRight: "clamp",
});
const titleY = interpolate(frame, [0, 20], [30, 0], {
extrapolateRight: "clamp",
});
const textOpacity = interpolate(frame, [12, 35], [0, 1], {
extrapolateRight: "clamp",
});
const textY = interpolate(frame, [12, 35], [20, 0], {
extrapolateRight: "clamp",
});
// Geometric shape animations
const circleScale = interpolate(frame, [0, 40], [0, 1], {
extrapolateRight: "clamp",
});
const rectWidth = interpolate(frame, [5, 30], [0, 200], {
extrapolateRight: "clamp",
});
const dotOpacity = interpolate(frame, [15, 30], [0, 0.15], {
extrapolateRight: "clamp",
});
const lineHeight = interpolate(frame, [8, 35], [0, 300], {
extrapolateRight: "clamp",
});
return (
<AbsoluteFill
style={{
backgroundColor: "#FFFFFF",
display: "flex",
flexDirection: "column",
justifyContent: "center",
padding: "80px 120px",
}}
>
{/* Background geometric shapes */}
{/* Large circle top-right */}
<div
style={{
position: "absolute",
top: -80,
right: -80,
width: 400,
height: 400,
borderRadius: "50%",
border: `2px solid ${ACCENT}20`,
transform: `scale(${circleScale})`,
}}
/>
{/* Small filled circle */}
<div
style={{
position: "absolute",
top: 120,
right: 200,
width: 12,
height: 12,
borderRadius: "50%",
backgroundColor: ACCENT,
opacity: circleScale * 0.6,
}}
/>
{/* Accent bar top-left */}
<div
style={{
position: "absolute",
top: 80,
left: 120,
width: rectWidth,
height: 4,
backgroundColor: ACCENT,
borderRadius: 2,
}}
/>
{/* Vertical line right side */}
<div
style={{
position: "absolute",
right: 120,
top: "50%",
width: 2,
height: lineHeight,
backgroundColor: "#00000008",
transform: "translateY(-50%)",
}}
/>
{/* Dot grid pattern */}
<div
style={{
position: "absolute",
bottom: 100,
right: 140,
display: "grid",
gridTemplateColumns: "repeat(5, 1fr)",
gap: 20,
opacity: dotOpacity,
}}
>
{Array.from({ length: 15 }).map((_, i) => (
<div
key={i}
style={{
width: 6,
height: 6,
borderRadius: "50%",
backgroundColor: "#000000",
}}
/>
))}
</div>
{/* Content */}
<div style={{ position: "relative", zIndex: 1, maxWidth: 1200 }}>
{/* Title */}
<h1
style={{
color: "#0A0A0A",
fontSize: 56,
fontWeight: 700,
fontFamily: "Inter, system-ui, sans-serif",
opacity: titleOpacity,
transform: `translateY(${titleY}px)`,
marginBottom: 32,
lineHeight: 1.2,
}}
>
{title}
</h1>
{/* Divider */}
<div
style={{
width: 60,
height: 4,
backgroundColor: ACCENT,
borderRadius: 2,
marginBottom: 28,
opacity: titleOpacity,
}}
/>
{/* Narration text */}
<p
style={{
color: "#404040",
fontSize: 28,
fontFamily: "Inter, system-ui, sans-serif",
lineHeight: 1.8,
opacity: textOpacity,
transform: `translateY(${textY}px)`,
maxWidth: 950,
}}
>
{narration}
</p>
</div>
{/* Bottom accent stripe */}
<div
style={{
position: "absolute",
bottom: 0,
left: 0,
width: "100%",
height: 5,
backgroundColor: ACCENT,
}}
/>
</AbsoluteFill>
);
};