feat(film): screen frame (with placeholder fallback) + ken burns

This commit is contained in:
Satyam Rastogi
2026-05-30 02:30:14 +05:30
parent e3f708e73f
commit ba7186fe7b
2 changed files with 63 additions and 0 deletions
@@ -0,0 +1,15 @@
import { useCurrentFrame, useVideoConfig, interpolate } from "remotion";
// Slow zoom/pan over its children across the whole sequence the component lives in.
export const KenBurns: React.FC<{
children: React.ReactNode;
from?: number;
to?: number;
durationInFrames: number;
}> = ({ children, from = 1.0, to = 1.08, durationInFrames }) => {
const frame = useCurrentFrame();
const scale = interpolate(frame, [0, durationInFrames], [from, to], {
extrapolateRight: "clamp",
});
return <div style={{ width: "100%", height: "100%", transform: `scale(${scale})` }}>{children}</div>;
};
@@ -0,0 +1,48 @@
import { useState } from "react";
import { AbsoluteFill, staticFile } from "remotion";
import { theme } from "../theme";
export const ScreenFrame: React.FC<{
captureId: string;
scale?: number;
}> = ({ captureId, scale = 0.86 }) => {
const [errored, setErrored] = useState(false);
const src = staticFile(`captures/${captureId}.png`);
return (
<AbsoluteFill style={{ alignItems: "center", justifyContent: "center", backgroundColor: theme.bg }}>
<div
style={{
width: `${scale * 100}%`,
aspectRatio: "16 / 9",
borderRadius: 16,
overflow: "hidden",
border: `1px solid ${theme.border}`,
boxShadow: "0 40px 120px rgba(0,0,0,0.55)",
backgroundColor: "#0c0c0e",
position: "relative",
}}
>
<div style={{ height: 34, display: "flex", alignItems: "center", gap: 8, padding: "0 14px", background: "rgba(255,255,255,0.04)", borderBottom: `1px solid ${theme.border}` }}>
<span style={{ width: 11, height: 11, borderRadius: 999, background: "#ef4444" }} />
<span style={{ width: 11, height: 11, borderRadius: 999, background: "#f59e0b" }} />
<span style={{ width: 11, height: 11, borderRadius: 999, background: "#10b981" }} />
<span style={{ marginLeft: 14, color: theme.textDim, fontFamily: theme.mono, fontSize: 13 }}>app.lynkeduppro.com</span>
</div>
<div style={{ position: "absolute", top: 34, left: 0, right: 0, bottom: 0 }}>
{errored ? (
<div style={{ width: "100%", height: "100%", display: "flex", alignItems: "center", justifyContent: "center", color: theme.textDim, fontFamily: theme.mono, fontSize: 22, background: "#0c0c0e" }}>
[capture missing: {captureId}]
</div>
) : (
<img
src={src}
onError={() => setErrored(true)}
style={{ width: "100%", height: "100%", objectFit: "cover", objectPosition: "top center", display: "block" }}
/>
)}
</div>
</div>
</AbsoluteFill>
);
};