Lens Zoom
A hard cut disguised as a lens punch-in — barrel distortion, zoom blur, chromatic split and camera shake around the splice
Installation
$ pnpm dlx shadcn@latest add @remocn/lens-zoomUsage
lensZoom() is a Remotion transition presentation. The transition is a hard
cut, not a dissolve: the outgoing half owns progress 0–0.5 and the incoming
half owns 0.5–1, so the splice lands exactly halfway through the transition.
Use LENS_ZOOM_DURATION_IN_FRAMES (28) with linearTiming for the tutorial's
pacing — two equal 14-frame ramps either side of the cut.
import { TransitionSeries, linearTiming } from "@remotion/transitions";
import {
lensZoom,
LENS_ZOOM_DURATION_IN_FRAMES,
} from "@/components/remocn/lens-zoom";
export const MyVideo = () => (
<TransitionSeries>
<TransitionSeries.Sequence durationInFrames={70}>
<SceneA />
</TransitionSeries.Sequence>
<TransitionSeries.Transition
timing={linearTiming({ durationInFrames: LENS_ZOOM_DURATION_IN_FRAMES })}
presentation={lensZoom()}
/>
<TransitionSeries.Sequence durationInFrames={70}>
<SceneB />
</TransitionSeries.Sequence>
</TransitionSeries>
);Performance scales with blurSamples × (lensSteps + 1) painted copies of each
scene per frame, tripled when the three channel scales differ. Setting
redScale, greenScale and blueScale equal skips the chromatic split
entirely — the single biggest thing to turn off while dialling the transition
in.
Props
lensZoom(props) accepts:
| Prop | Type | Default | Description |
|---|---|---|---|
inScaleFrom / inScaleTo | number | 100 / 150 | Scale ramp of the outgoing half, in percent |
inFovFrom / inFovTo | number | 0 / 160 | Lens distortion FOV ramp of the outgoing half, in degrees |
inBlurFrom / inBlurTo | number | 0 / 60 | Zoom blur amount ramp of the outgoing half |
inRotationFrom / inRotationTo | number | 0 / -15 | Rotation ramp of the outgoing half, in degrees |
outScaleFrom / outScaleTo | number | 135 / 100 | Scale ramp of the incoming half — starts below the outgoing peak so the energy steps down at the cut |
outFovFrom / outFovTo | number | 135 / 0 | Lens distortion FOV ramp of the incoming half |
outBlurFrom / outBlurTo | number | 45 / 0 | Zoom blur amount ramp of the incoming half |
outRotationFrom / outRotationTo | number | 345 / 360 | Rotation ramp of the incoming half — unwinds the outgoing twist |
anticipateScale | number | 100 | Scale the outgoing scene squeezes down to before the punch — the wind-up before the jump. The lens, blur and rotation ramps hold until the squeeze ends. Disabled by default (scaling the full frame below 100 reveals the backdrop behind it) — prefer squeezing the subject inside the scene; set below `inScaleFrom` to enable the frame squeeze |
anticipatePortion | number | 0.35 | Portion of the outgoing half spent on the squeeze. 0 disables it |
lensSteps | number | 9 | Concentric rings approximating the barrel warp. Nearly free — the rings are disjoint |
blurSamples | number | 7 | Scaled copies approximating the zoom blur. The expensive knob — higher is smoother |
blurScaleGain | number | 1 | Scale span one unit of blur amount buys |
blurFade | number | 1.5 | Higher keeps the sharp copy dominant over the smear |
shakeAmount | number | 50 | Peak of the shake envelope around the cut. 0 disables the shake |
shakeFrequency | number | 1.4 | Shake noise frequency |
shakeCyclesPerUnit | number | 8 | Noise cycles per second one unit of frequency is worth |
shakeTranslatePx | number | 73 | Peak shake translation in pixels |
shakeRotateDeg | number | 1.1 | Peak shake rotation in degrees |
redScale / greenScale / blueScale | number | 1.01 / 1.0 / 0.99 | Per-channel scales for the chromatic aberration. Set all three equal to skip the split |
letterboxAspect | number | 0 | Cinematic bars aspect ratio (e.g. 2.39). 0 disables them |
width / height | number | composition size | Stage size in pixels |
distortionCenterX / distortionCenterY | number | stage center | Center of the lens distortion, blur and shake |
Inspired by After Effects: Lens Zoom Transition Tutorial by Creative Dojo.