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-zoom

Usage

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:

PropTypeDefaultDescription
inScaleFrom / inScaleTo
number100 / 150Scale ramp of the outgoing half, in percent
inFovFrom / inFovTo
number0 / 160Lens distortion FOV ramp of the outgoing half, in degrees
inBlurFrom / inBlurTo
number0 / 60Zoom blur amount ramp of the outgoing half
inRotationFrom / inRotationTo
number0 / -15Rotation ramp of the outgoing half, in degrees
outScaleFrom / outScaleTo
number135 / 100Scale ramp of the incoming half — starts below the outgoing peak so the energy steps down at the cut
outFovFrom / outFovTo
number135 / 0Lens distortion FOV ramp of the incoming half
outBlurFrom / outBlurTo
number45 / 0Zoom blur amount ramp of the incoming half
outRotationFrom / outRotationTo
number345 / 360Rotation ramp of the incoming half — unwinds the outgoing twist
anticipateScale
number100Scale 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
number0.35Portion of the outgoing half spent on the squeeze. 0 disables it
lensSteps
number9Concentric rings approximating the barrel warp. Nearly free — the rings are disjoint
blurSamples
number7Scaled copies approximating the zoom blur. The expensive knob — higher is smoother
blurScaleGain
number1Scale span one unit of blur amount buys
blurFade
number1.5Higher keeps the sharp copy dominant over the smear
shakeAmount
number50Peak of the shake envelope around the cut. 0 disables the shake
shakeFrequency
number1.4Shake noise frequency
shakeCyclesPerUnit
number8Noise cycles per second one unit of frequency is worth
shakeTranslatePx
number73Peak shake translation in pixels
shakeRotateDeg
number1.1Peak shake rotation in degrees
redScale / greenScale / blueScale
number1.01 / 1.0 / 0.99Per-channel scales for the chromatic aberration. Set all three equal to skip the split
letterboxAspect
number0Cinematic bars aspect ratio (e.g. 2.39). 0 disables them
width / height
numbercomposition sizeStage size in pixels
distortionCenterX / distortionCenterY
numberstage centerCenter of the lens distortion, blur and shake

Inspired by After Effects: Lens Zoom Transition Tutorial by Creative Dojo.