feat(film): live-interaction product film foundation
Capture pipeline (Playwright recordVideo + injected synthetic cursor + ffmpeg webm->mp4) and a Remotion LiveFilm composition driven by a 20-clip manifest with caption/zoom overlays and a music bed. Includes the capture orchestrator, storm-intel reference scene, pre-render smoke check, and VO script. Pure logic is unit-tested (28 passing). Remaining scene scripts are authored during live capture.
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import { Series, AbsoluteFill } from "remotion";
|
||||
import manifest from "./clips.manifest.json";
|
||||
import { totalLiveFrames, type ClipsManifest } from "./clips";
|
||||
import { DURATIONS } from "./timing";
|
||||
import { ClipStage } from "./components/ClipStage";
|
||||
import { AudioTrack } from "./components/AudioTrack";
|
||||
import { Promise as PromiseSeq } from "./sequences/Promise";
|
||||
|
||||
const m = manifest as ClipsManifest;
|
||||
export const LIVE_TOTAL = totalLiveFrames(m) + DURATIONS.promise;
|
||||
|
||||
export const LiveFilm: React.FC = () => {
|
||||
const [hero, ...rest] = m.clips; // landing-hero is first in the manifest
|
||||
return (
|
||||
<AbsoluteFill>
|
||||
<AudioTrack totalFrames={LIVE_TOTAL} />
|
||||
<Series>
|
||||
<Series.Sequence durationInFrames={hero.durationFrames}>
|
||||
<ClipStage clip={hero} />
|
||||
</Series.Sequence>
|
||||
<Series.Sequence durationInFrames={DURATIONS.promise}>
|
||||
<PromiseSeq />
|
||||
</Series.Sequence>
|
||||
{rest.map((clip) => (
|
||||
<Series.Sequence key={clip.id} durationInFrames={clip.durationFrames}>
|
||||
<ClipStage clip={clip} />
|
||||
</Series.Sequence>
|
||||
))}
|
||||
</Series>
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user