---
title: "How to add a title card intro with Claude (tested prompt and script)"
description: "A bright yellow screen slides up a big black two-line headline for 1.5 seconds, then cuts straight to the first shot. Install one skill and ask Claude Code, or run the Python script we tested yourself."
url: https://www.recharm.com/effects/title-card-intro
---

# How to add a title card intro with Claude

A bright yellow screen slides up a big black two-line headline for 1.5 seconds, then cuts straight to the first shot.

Made by the script on this page, from our own test clip.

## Get this effect

1. ### Switch to Code in your [Claude Desktop App](https://claude.com/download)

2. ### Install the skill (once)

   ```
   Install the Recharm video effects skill: download https://recharm-growth-staging.s3.us-east-2.amazonaws.com/website/downloads/recharm-video-effects.zip and unzip it into ~/.claude/skills
   ```

3. ### Ask for the effect

   ```
   Add a title card intro to input.mp4
   Lines: ["Your skin,", "but brighter"]
   ```

## Several videos, several effects, one ask

Put your clips in the folder, mention them with @, and ask for everything at once. Claude runs one tested script after another on each clip, then joins them.

Add a title card intro to **@clip1.mp4**, put a sale badge on **@clip2.mp4**, give **@clip3.mp4** a VHS look, then join all three with crossfades.

## Settings you can change

Ask Claude to change any of these, or edit them at the top of the script.

| Setting      | Default                          | What it does                                     |
| ------------ | -------------------------------- | ------------------------------------------------ |
| `LINES`      | `["Your skin,", "but brighter"]` | The headline, one entry per line.                |
| `CARD`       | `1.5`                            | Seconds the card plays before the footage.       |
| `BACKGROUND` | `(255, 210, 0)`                  | Card color.                                      |
| `INK`        | `(20, 20, 20)`                   | Text color.                                      |
| `SIZE`       | `0.13`                           | Text height as a share of the frame width.       |
| `STAGGER`    | `0.3`                            | Seconds between one line arriving and the next.  |
| `RISE`       | `0.25`                           | Seconds each line takes to slide up and fade in. |

## Without the skill

Don’t want to install the skill? Paste this prompt into Claude Code and Claude writes the script itself.

```
Put a 1.5 second title card in front of input.mp4: a solid yellow (255, 210, 0) 540x960 screen with "Your skin," over "but brighter" in black (20, 20, 20) Arial Black, text 70 pixels tall, the two lines 1.25 line heights apart and centered on the middle of the frame. The first line slides up 38 pixels into place and fades in from 0.1 to 0.35 seconds, the second from 0.4 to 0.65 seconds, both easing out. At 1.5 seconds cut straight to the clip, which plays from its start, so the output is 7.5 seconds at 30fps. Delay the audio by 1.5 seconds so it stays in sync. Use Python with Pillow to draw the card (don't rely on ffmpeg's drawtext filter) and ffmpeg to join it to the clip, and save it as output.mp4.
```

## Run it without Claude

This is the exact script we tested. Save it as `title-card-intro.py` and run:

```
python3 title-card-intro.py input.mp4 output.mp4
```

```
#!/usr/bin/env python3
"""Title card intro: a yellow screen with a big black two-line headline plays for 1.5 seconds before the clip.

Usage: python3 title-card-intro.py input.mp4 output.mp4
The output is 1.5 seconds longer than the input; the sound waits for the card so it stays in sync.
Needs ffmpeg and Pillow (pip install pillow).
"""
import json
import subprocess
import sys
from pathlib import Path

from PIL import Image, ImageDraw, ImageFont

LINES = ["Your skin,", "but brighter"]  # headline, one entry per line
CARD = 1.5                # seconds the title card plays before the footage
BACKGROUND = (255, 210, 0)  # card color
INK = (20, 20, 20)        # text color
SIZE = 0.13               # text height as a share of the frame width
STAGGER = 0.3             # seconds between one line arriving and the next
RISE = 0.25               # seconds each line takes to slide up and fade in
FONTS = ["/System/Library/Fonts/Supplemental/Arial Black.ttf",    # macOS
         "/System/Library/Fonts/Supplemental/Arial Bold.ttf",     # macOS
         "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",  # Linux
         "C:/Windows/Fonts/ariblk.ttf"]                           # Windows
FONT_FILE = next((f for f in FONTS if Path(f).exists()), None) or sys.exit("No bold font found: add one to FONTS")

def card(t):
    """The card at t seconds: each line slides up 4% of the frame and fades in, STAGGER seconds after the last."""
    img = Image.new("RGB", (w, h), BACKGROUND)
    font = ImageFont.truetype(FONT_FILE, round(w * SIZE))
    step = font.size * 1.25
    for i, line in enumerate(LINES):
        p = min(max((t - 0.1 - i * STAGGER) / RISE, 0), 1)
        if p == 0:
            continue
        p = 1 - (1 - p) ** 3  # ease out
        layer = Image.new("RGBA", (w, h))
        y = h / 2 + (i - (len(LINES) - 1) / 2) * step + (1 - p) * h * 0.04
        ImageDraw.Draw(layer).text((w / 2, y), line, font=font, anchor="mm", fill=INK + (round(255 * p),))
        img.paste(layer, mask=layer)
    return img

src, out = sys.argv[1:3]
info = json.loads(subprocess.check_output(["ffprobe", "-v", "error", "-show_entries", "stream=codec_type,width,height",
                                           "-of", "json", src]))
video = next(s for s in info["streams"] if s["codec_type"] == "video")
w, h = video["width"], video["height"]
has_audio = any(s["codec_type"] == "audio" for s in info["streams"])

# the card frames come in on stdin, then the clip is joined on after them
graph = "[1:v]format=yuv420p,setsar=1[c];[0:v]fps=30,format=yuv420p,setsar=1[v];[c][v]concat=n=2:v=1:a=0[out]"
maps = ["-map", "[out]"]
if has_audio:
    graph += f";[0:a]adelay={round(CARD * 1000)}:all=1[a]"
    maps += ["-map", "[a]"]
ff = subprocess.Popen(["ffmpeg", "-y", "-v", "error", "-i", src,
                       "-f", "rawvideo", "-pix_fmt", "rgb24", "-s", f"{w}x{h}", "-r", "30", "-i", "-",
                       "-filter_complex", graph, *maps, "-c:v", "libx264", "-crf", "18", "-c:a", "aac", out],
                      stdin=subprocess.PIPE)
for i in range(round(CARD * 30)):
    ff.stdin.write(card(i / 30).tobytes())
ff.stdin.close()
if ff.wait():
    sys.exit("ffmpeg failed")
```

## More hook openers

- [Blur-to-focus reveal **Blur-to-focus reveal**](https://www.recharm.com/effects/blur-to-focus-reveal)
- [Breaking news banner **Breaking news banner**](https://www.recharm.com/effects/breaking-news-banner)
- [Camera shake **Camera shake**](https://www.recharm.com/effects/camera-shake)
- [Color reveal **Color reveal**](https://www.recharm.com/effects/color-reveal)
- [Countdown intro **Countdown intro**](https://www.recharm.com/effects/countdown-intro)

## Find 3x _winning ads_

Recharm cuts your ad footage into tagged, searchable clips: hooks, testimonials, product shots. Find the shots that win, add the effect with Claude, and ship 3x more ad edits.

[Start 14-day free trial](https://www.recharm.com/get-started)
