PTENES
MODULE 4.1

📺 Channel Intro

A complete 10–15-second bumper combining a starfield background, spring-based logo animation, a cinematic title entrance, and an iris exit transition — all within a single Series.

6
Topics
45
Minutes
Advanced
Level
Project
Type
starfieldanimated background logo-spinspring cinematic-titlestagger by letter iris-transitionclip-path opening 10–15 s Series orchestrates the order — without calculating offsets manually
1

🎯 The project and its scene structure

A channel intro is a video of identity: introduces the brand before the content. In Remotion, we model this as a sequence of scenes in Series — each scene is an independent component with its own timing, stacked by Series without manual offset arithmetic.

🎬 The 4 opening scenes

  • 1.Background — starfield or gradient-shift running from frame 0 to the end, always on the bottom layer.
  • 2.Logo — springs into the center, stays for ~2 s, then recedes slightly.
  • 3.Title — channel name and tagline come in staggered right after the logo settles.
  • 4.Output — iris or fade-through-black closes the opening before the main content.
Root component skeleton ChannelOpening.tsx
import { Series, AbsoluteFill } from "remotion";
import { Starfield }       from "./templates/starfield";
import { LogoSpinReveal }  from "./templates/logo-spin-reveal";
import { CinematicTitle }  from "./templates/cinematic-title-intro";
import { IrisTransition }  from "./templates/iris-transition";

export const ChannelOpening = () => (
  <AbsoluteFill>
    <Starfield />          {/* sempre ativo — z=0 */}
    <Series>
      <Series.Sequence durationInFrames={60}>
        <LogoSpinReveal logo="./logo.svg" />
      </Series.Sequence>
      <Series.Sequence durationInFrames={75}>
        <CinematicTitle title="Meu Canal" tagline="Design em Movimento" />
      </Series.Sequence>
      <Series.Sequence durationInFrames={30}>
        <IrisTransition />
      </Series.Sequence>
    </Series>
  </AbsoluteFill>
);
Total
~165 frames = 5.5 s
Background
Parallel to Series
Series
No manual offset
Props
logo, title, tagline
2

✨ Background scene — starfield and gradient-shift

The background is not part of the Series—it lives in a AbsoluteFill separate that exists throughout the video. The starfield generates stars with random() seeded and shifts them slightly per frame, creating depth without the cost of a camera.

🌌 How the starfield works

  • random("star-x-N") — generates a deterministic X position for star N
  • random("star-y-N") — Y position also seeded — always the same per frame
  • translateY via interpolate — star moves down 20px throughout the entire video
  • pulsing opacity — Math.sin(frame * 0.05 + seed) creates a soft shimmer

✓ What to DO

  • ✓Use random() from Remotion with a seed—never Math.random().
  • ✓Keep the background in AbsoluteFill, independent of the Series.
  • ✓Keep star opacity between 0.3–0.9 so they don't compete with the logo.

✗ What NOT to do

  • ✗Use Math.random() — stars "blink" between frames in the render.
  • ✗Put the background inside the Series — it will disappear when the scene ends.
  • ✗Use a star color that matches the logo—you lose contrast in the critical frame.
random()
Seeded, deterministic
AbsoluteFill
z=0, always active
Parallax
slow translateY
Sparkle
Math.sin + seed
3

🔵 Logo Scene — spin-reveal and stroke-draw

The logo is the most impactful scene: it appears with a spring tuned to create that “pop” without overdoing it. You can use logo-spin-reveal.tsx (rotates and scales) or logo-stroke-draw.tsx (progressively traces the SVG outline).

Logo with tuned spring logo-spin-reveal.tsx
const frame = useCurrentFrame();
const { fps } = useVideoConfig();

// spring: pop rápido, sem bounce excessivo
const progress = spring({ frame, fps,
  config: { damping: 14, stiffness: 180, mass: 1 }
});

const scale   = interpolate(progress, [0,1], [0.3,1]);
const rotate  = interpolate(progress, [0,1], [-180,0]);
const opacity = interpolate(progress, [0,0.3], [0,1],
  { extrapolateRight: "clamp" });

return <AbsoluteFill style={{ display:"flex", alignItems:"center", justifyContent:"center" }}>
  <img src={logo} style={{ transform: `scale(${scale}) rotate(${rotate}deg)`, opacity }} />
</AbsoluteFill>;

💡 Spring vs. interpolate for the logo

Use spring for scale and rotation — the spring's natural overshoot adds personality. Use interpolate with clamp for opacity — you need exact control over when the logo appears. The combination of the two is what makes the animation feel alive.

damping 14
Slight overshoot
stiffness 180
Fast animation
-180° → 0°
Half-turn entrance
Timing
~0–30 frames
4

🔤 Title Scene — cinematic-title and title-split

The title appears right after the logo stabilizes. cinematic-title-intro.tsx uses animated letter-spacing (letter expansion) while title-split.tsx splits the text into two halves that converge from the center. The per-letter/word stagger is what makes the title visually rich.

1

Frame 0–10: container fade-in

The background behind the title (a semi-transparent dark box) animates opacity from 0→1. This establishes contrast before the letters appear.

2

Frame 5–35: staggered letters

Each letter has a Sequence from={i * 2} — letter 0 starts at frame 5, letter 1 at frame 7, and so on. The cascade effect is automatic.

3

Frame 35–75: static title

The title stays fully visible for ~1.3 s — enough time for viewers to read and absorb the channel name.

4

Frame 75–90: smooth exit

Opacity 1→0 over the last 15 frames of the scene. The exit transition (iris) begins while the title is still exiting — they overlap gracefully.

Stagger
from={i * 2}
Plateau
~1.3 s visible
Output
15-frame fade-out
Overlap
With an iris transition
5

🌀 Exit scene — iris-transition and fade-through-black

The exit transition is what makes the opening professional. iris-transition.tsx uses a circular clip-path that opens or closes — from the center or a corner. fade-through-black.tsx is simpler: fade to black before reaching the content.

Iris via animated clip-path iris-transition.tsx
const frame = useCurrentFrame();
const { width, height } = useVideoConfig();

// raio máximo = diagonal da tela
const maxR = Math.sqrt(width**2 + height**2) / 2;
const radius = interpolate(frame, [0,30], [maxR, 0],
  { extrapolateRight: "clamp" });

return <AbsoluteFill style={{
  clipPath: `circle(${radius}px at center)`,
  background: "black"
}} />;

💡 Choose the transition based on the channel's tone

Closing iris = classic/cinematic style. Fade-through-black = clean and modern. For tech channels, prefer the fade. For lifestyle or culture channels, the iris adds more personality.

clip-path
circle(r px at cx cy)
Diagonal
Maximum frame radius
30 frames
Transition duration
Origin
center or logo pos.
6

🎛️ Final assembly — timing and rhythm

With all scenes ready, the final task is tune the rhythm. A channel opener should feel fast but not anxious — long enough for the logo to register, and the title to be read. The rule of thumb: never less than 5 s, never more than 15 s.

✓ Recommended timing (30fps)

  • ✓Logo: 60 frames (2 s) — time to recognize the brand.
  • ✓Title: 75 frames (2.5 s) — time to read the name + tagline.
  • ✓Transition: 30 frames (1 s) — fast enough to avoid fatigue.

✗ Common pacing mistakes

  • ✗Logo stays on screen for more than 3 s before the title appears — it looks like it froze.
  • ✗Title exits before it’s fully legible — a hard cut.
  • ✗Transition is too long — the opening competes with the content itself.
Ideal total
5–10 s
Logo
2 s = 60 frames
Title
2.5 s = 75 frames
Output
1 s = 30 frames

🏁 Module Summary

✓
Series orchestrates the scenes — no need to calculate offsets; each scene declares its duration.
✓
Background in a parallel AbsoluteFill — starfield/gradient-shift aren't part of the Series.
✓
Spring for the logo — damping 14, stiffness 180 give the perfect pop.
✓
Letter stagger — Sequence from={i*2} inside the title component.
✓
Iris via clip-path — circle(r px at center) with r interpolated from maxR to 0.
✓
Timing: 5–10 s total — logo 2 s + title 2.5 s + transition 1 s.

Next Module:

4.2 — Product Video: ken-burns + lower-third + stat-counter + end-card.