PTENES
MODULE 4.4

📱 Reels / Shorts

Vertical video 1080×1920 for Instagram Reels and YouTube Shorts. Fast pacing, impactful text with typewriter e bounce-text, glitch on the highlight, visual sound wave, bokeh background, and subscribe reminder in the last 5 seconds.

6
Topics
45
Minutes
Advanced
Level
Project
Type
bokeh-circles (z=0) sound-wave (z=1) typewriter (z=2) glitch-text (z=3) subscribe (z=4, final) 9:16 1080×1920 Reel / Short ready 30–60 s · fast-paced · 85% without sound
1

📐 Vertical format — 1080×1920 with useVideoConfig

The Reel starts with the definition of the Composition: width: 1080, height: 1920. Everything inside the component reads these dimensions via useVideoConfig() to adapt — larger fonts, smaller margins, and content vertically centered in the upper third (where the user’s thumb is).

Vertical composition + hook Root.tsx + Reel.tsx
// Root.tsx — declaração do formato
<Composition
  id="Reel"
  component={ReelVideo}
  width={1080}
  height={1920}
  fps={30}
  durationInFrames={900}  // 30 s
/>

// Reel.tsx — layout responsivo
const { width, height } = useVideoConfig();

// fonte escala com a largura
const baseFontSize = width * 0.055; // ~60px em 1080px

// conteúdo no terço superior (fora da área do polegar)
const contentTop = height * 0.15;

📱 9:16 layout rules

  • Top third (0–30%): title and main text — most visible area
  • Middle third (30–70%): visual/image — eye’s focal area
  • Bottom third (70–100%): CTA and subscribe — thumb zone, interaction
  • Minimum font: 60px at 1080px (width * 0.055) — legible on a small phone
1080×1920
9:16 resolution
width*0.055
Scalable base font
30 s = 900f
Ideal duration
Thirds
3-zone layout
2

💬 Animated caption — typewriter and bounce-text

85% of Reels are watched without sound. This means the text is the audio of the video. The typewriter-subtitle.tsx reveals the text letter by letter, while the bounce-text.tsx makes each word enter with a small bounce — both create the feeling that someone is "writing live".

Word-by-word typewriter typewriter-subtitle.tsx
const words = text.split(" ");
const FRAMES_PER_WORD = 8;  // ritmo: 1 palavra a cada 8 frames

{words.map((word, i) => {
  const startFrame = i * FRAMES_PER_WORD;
  const opacity = interpolate(
    frame, [startFrame, startFrame + 6], [0, 1],
    { extrapolateLeft: "clamp", extrapolateRight: "clamp" }
  );
  // bounce: entra de baixo
  const y = interpolate(
    frame, [startFrame, startFrame + 10], [20, 0],
    { easing: Easing.out(Easing.back(1.5)), extrapolateLeft: "clamp", extrapolateRight: "clamp" }
  );
  return <span key={i} style={{ opacity, transform: `translateY(${y}px)`, display: "inline-block", margin: "0 4px" }}>{word}</span>;
})}

💡 Pacing: 8 frames per word = 0.27 s

At 30fps, 8 frames per word produces natural, fluid reading. For impactful phrases that need more emphasis, use 12–15 frames per word. For quick lists (“easy · fast · cheap”), use 5–6 frames. The text rhythm should mimic the rhythm of speech.

Pacing
8f per word
Bounce
Easing.back(1.5)
Display
inline-block per word
Font
≥60px at 1080px
3

⚡ Highlight glitch — visual impact in the first frames

The Reels algorithm measures retention in the first 3 seconds. The glitch-text.tsx creates an "interference" effect on the video's keyword: rapid color shifts (channel offset) for 2–4 frames, creating visual impact that immediately grabs attention.

✓ A glitch that works

  • ✓Glitch in the first 0–15 frames — grabs attention before the scroll.
  • ✓Small offset (3–8px) — noticeable without being nauseating.
  • ✓random("glitch-N") with a seed — same glitch in every render.

✗ A glitch that drives people away

  • ✗Glitch throughout the video — tiring and looks like a bug, not an effect.
  • ✗Large offset (20px+) — makes the text unreadable.
  • ✗Math.random() without a seed — text "flashes" uncontrollably during rendering.
1

Frame 0–3: intense glitch

Three text layers randomly offset in X and Y (but seeded). Colors: amber, cyan, and white, separated by 3–6px.

2

Frame 4–6: residual glitch

Offset drops to 1–2px. The glitch's “cure” is just as important as the glitch — stabilization reinforces the word in memory.

3

Frame 7+: stable text

The main text stays steady for the rest of the scene. The glitch effect can briefly reappear when a new phrase appears.

Frames 0–6
Glitch window
3 layers
Color separated by offset
random seed
Deterministic
3–8px
Maximum offset
4

🎵 Sound-wave visual — rhythm without audio

O sound-wave.tsx renders a row of bars that oscillate with Math.sin(), simulating an audio visualization. In a Reel without sound, this element signals “this video has energy”—it’s the visual equivalent of a music beat.

Oscillating bars with Math.sin sound-wave.tsx
const frame = useCurrentFrame();
const BAR_COUNT = 32;
const MAX_H = 80; // px, relativo ao height do container

{Array.from({ length: BAR_COUNT }).map((_, i) => {
  const seed = random(`wave-${i}`); // fase aleatória por barra
  const barH = Math.abs(
    Math.sin(frame * 0.15 + seed * Math.PI * 2)
  ) * MAX_H + 4;  // mínimo 4px para não sumir

  return <div key={i} style={{
    width: 4, height: barH,
    background: i % 3 === 0 ? "#38bdf8" : "#fbbf24",
    borderRadius: 2
  }} />;
})}
Math.sin
frame * 0.15 + seed
32 bars
Visual density
random seed
Single phase per bar
Minimum 4px
Never disappears
5

🫧 Bokeh Background — Synthetic Depth of Field

O bokeh-circles.tsx generates blurred circles floating in the background — the bokeh effect of a real camera, but 100% computational. Each circle has a random (seeded) size, position, opacity, and vertical speed, creating depth of field without a physical camera.

🫧 How bokeh is generated

  • Position: random("bokeh-x-N") and random("bokeh-y-N") — fixed, deterministic
  • Size: random("bokeh-r-N") * 80 + 20 — between 20 and 100px in radius
  • Floating: translateY = -frame * random("bokeh-speed-N") * 0.3 — moves up slowly
  • Reappearance: when y < -r, reposition to height + r (loop)
  • Blur: filter: blur(Npx) — between 8 and 20px to look out of focus
blur
8–20px per circle
opacity
0.15–0.45
Loop
Reappears at the bottom
z=0
Base AbsoluteFill
6

🔔 Subscribe reminder — CTA in the last 5 s

O subscribe-reminder.tsx appears in the last 150 frames (5 s) of the Reel — a bell + “Subscribe” text animation that doesn’t compete with the main content but is there when the viewer is most engaged (because they watched to the end).

Subscribe with timing relative to the end subscribe-reminder.tsx
const { durationInFrames } = useVideoConfig();
const frame = useCurrentFrame();

// aparece nos últimos 150 frames
return (
  <Sequence from={durationInFrames - 150}>
    <SubscribeWidget />
  </Sequence>
);

// SubscribeWidget — sino com shake e texto
const bellFrame = useCurrentFrame(); // local frame (0–150)
const scale = spring({ frame: bellFrame, fps,
  config: { damping: 10, stiffness: 200 }
});
// shake: oscila 3x por segundo
const shakeX = Math.sin(bellFrame * 0.5) *
  interpolate(bellFrame, [0, 10], [8, 0], { extrapolateRight: "clamp" });

💡 Why the last fifth?

Viewers who make it to the Reel’s last 5 s are already “warm”—they approved the content. That’s the best time to ask them to take action. Asking them to subscribe before then feels like spam; after that, there’s no time to react. The right timing is what separates an effective CTA from an intrusion.

Timing
durationInFrames - 150
Local frame
Resets to 0
Spring
Bell entrance
Shake
Math.sin × 8px → 0

🏆 Module Summary — and Course Summary

✓
Composition 1080×1920 — width/height read via useVideoConfig for responsive layout.
✓
Text is the audio — typewriter at 8f/word + bounce with Easing.back(1.5).
✓
Glitch in the first 3 seconds — 3 layers, 3–8px offset, seeded random, heals in 6 frames.
✓
Sound-wave visual — Math.sin(frame * 0.15 + seed) with 32 oscillating bars.
✓
Computational bokeh — circles with 8–20px blur floating in a seeded loop.
✓
Subscribe in the last 5 s — Sequence from=durationInFrames-150, bell's local frame.

🎓 You completed Track 4 — and the course!

You’ve completed all 4 tracks: Fundamentals (T1), Assets and Templates (T2), Combining and Composition (T3), and now Complete Projects (T4). With the library’s 81 templates and the techniques you’ve learned, you’re equipped to create any programmatic video — from channel openers to viral Reels.