← back to Prestige Car Wash Video
src/scenes/CamScene.tsx
53 lines
import { AbsoluteFill, OffthreadVideo, Audio, staticFile, useCurrentFrame, interpolate } from 'remotion';
import type { Scene } from '../story';
const FONT = 'Inter, "SF Pro Display", system-ui, -apple-system, sans-serif';
const MONO = '"SF Mono", ui-monospace, Menlo, monospace';
export const CamScene: React.FC<{ s: Scene }> = ({ s }) => {
const f = useCurrentFrame();
const blink = Math.floor(f / 15) % 2 === 0;
const secs = 8 + Math.floor(f / 30); // fake ticking clock
const clock = `10:${String(24 + Math.floor(secs / 60)).padStart(2, '0')}:${String(secs % 60).padStart(2, '0')} AM`;
const inO = interpolate(f, [0, 14], [0, 1], { extrapolateRight: 'clamp' });
return (
<AbsoluteFill style={{ backgroundColor: '#05090f', alignItems: 'center', justifyContent: 'center' }}>
{s.narr && <Audio src={staticFile(`audio/${s.narr}.wav`)} />}
{/* webcam bezel */}
<div style={{ width: 1580, height: 890, borderRadius: 18, overflow: 'hidden', position: 'relative',
border: '3px solid #1b2b44', boxShadow: '0 40px 120px rgba(0,0,0,0.6)', opacity: inO }}>
<OffthreadVideo src={staticFile('media/real-lot-tour.mp4')} muted loop
style={{ width: '100%', height: '100%', objectFit: 'cover', filter: 'saturate(1.05) contrast(1.03)' }} />
{/* subtle scanlines */}
<AbsoluteFill style={{ background: 'repeating-linear-gradient(0deg, rgba(0,0,0,0.10) 0px, rgba(0,0,0,0.10) 1px, transparent 2px, transparent 4px)' }} />
<AbsoluteFill style={{ background: 'radial-gradient(120% 120% at 50% 50%, transparent 60%, rgba(0,0,0,0.4) 100%)' }} />
{/* LIVE badge */}
<div style={{ position: 'absolute', top: 24, left: 26, display: 'flex', alignItems: 'center', gap: 12,
background: 'rgba(4,8,15,0.6)', backdropFilter: 'blur(4px)', padding: '10px 18px', borderRadius: 10 }}>
<span style={{ width: 16, height: 16, borderRadius: 16, background: blink ? '#ff3b3b' : '#7a1414', boxShadow: blink ? '0 0 18px #ff3b3b' : 'none' }} />
<span style={{ fontFamily: FONT, fontWeight: 900, fontSize: 26, color: '#fff', letterSpacing: 3 }}>LIVE</span>
</div>
{/* label + clock */}
<div style={{ position: 'absolute', top: 26, right: 28, fontFamily: MONO, fontSize: 26, color: '#dbe7f6', textShadow: '0 2px 8px #000' }}>
{clock}
</div>
<div style={{ position: 'absolute', bottom: 26, left: 28, fontFamily: FONT, fontWeight: 800, fontSize: 30, color: '#fff', textShadow: '0 2px 12px #000' }}>
🚗 Prestige Car Wash — Lot Cam
</div>
{/* lines-open indicator */}
<div style={{ position: 'absolute', bottom: 26, right: 28, display: 'flex', alignItems: 'center', gap: 12,
background: 'rgba(4,8,15,0.6)', backdropFilter: 'blur(4px)', padding: '10px 18px', borderRadius: 10,
fontFamily: FONT, fontWeight: 800, fontSize: 26, color: s.accent }}>
<span style={{ width: 11, height: 11, borderRadius: 11, background: s.accent, boxShadow: `0 0 14px ${s.accent}` }} />
6 LINES OPEN · SHORT WAIT
</div>
</div>
<div style={{ marginTop: 30, fontFamily: FONT, fontWeight: 700, fontSize: 34, color: '#c2d2e8', opacity: inO }}>
See the wait before you drive over.
</div>
</AbsoluteFill>
);
};