---
title: "How to add an incoming call screen with Claude (tested prompt and script)"
description: "The video opens as a phone call from \"Your Skin\", with red Decline and green Accept buttons over a blurred, dimmed clip, then the call screen fades away to reveal the shot. Install one skill and ask Claude Code, or run the Python script we tested yourself."
url: https://www.recharm.com/effects/incoming-call-screen
---

# How to add an incoming call screen with Claude

The video opens as a phone call from "Your Skin", with red Decline and green Accept buttons over a blurred, dimmed clip, then the call screen fades away to reveal the 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 an incoming call screen to input.mp4
   Caller: Your Skin
   Status: incoming call...
   ```

## 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 an incoming call screen 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                                                 |
| ----------------- | ------------------------------ | ------------------------------------------------------------ |
| `CALLER`          | `Your Skin`                    | Name on the call screen.                                     |
| `STATUS`          | `incoming call...`             | Small line above the name.                                   |
| `END`             | `2.5`                          | Second the call is answered and the screen starts to fade.   |
| `FADE`            | `0.3`                          | Seconds the fade takes.                                      |
| `DARKEN`          | `0.45`                         | How much the blurred clip behind the call is darkened (0-1). |
| `ACCEPT, DECLINE` | `(52, 199, 89), (255, 59, 48)` | Button colors.                                               |

## Without the skill

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

```
Make input.mp4 open on a fake incoming phone call. From 0 to 2.5 seconds, show the clip blurred (box blur radius 18, 2 passes) and darkened to 55% brightness, with a call screen over it: "incoming call..." in light gray (235, 235, 240) bold text 4.5% of the frame width tall, centered at 14% down; the caller name "Your Skin" in white bold text 11% of the frame width tall, centered at 21% down; a gray (142, 142, 147) circle 30% of the frame width across centered at 36% down with a white "Y" in it; and two round buttons 20% of the frame width across centered at 82% down: a red (255, 59, 48) Decline button at 25% across and a green (52, 199, 89) Accept button at 75% across, each with a white phone handset icon and a white label ("Decline", "Accept", 4% of the frame width tall) just below. A thin green ring pulses out of the Accept button about once a second. At 2.5 seconds the call screen and the blur fade out over 0.3 seconds, and the clip plays on untouched. Use Python with Pillow to draw the call screen (don't rely on ffmpeg's drawtext filter) and ffmpeg for the blur and compositing, keep the audio, and save it as output.mp4.
```

## Run it without Claude

This is the exact script we tested. Save it as `incoming-call-screen.py` and run:

```
python3 incoming-call-screen.py input.mp4 output.mp4
```

```
#!/usr/bin/env python3
"""Incoming call screen: the clip opens as a phone call from "Your Skin", then the call screen fades away.

Usage: python3 incoming-call-screen.py input.mp4 output.mp4
Needs ffmpeg and Pillow (pip install pillow).
"""
import json
import math
import subprocess
import sys
from pathlib import Path

from PIL import Image, ImageDraw, ImageFont

CALLER = "Your Skin"         # name on the call screen
STATUS = "incoming call..."  # small line under the name
END = 2.5                    # second the call is answered and the screen starts to fade
FADE = 0.3                   # seconds the fade takes
DARKEN = 0.45                # how much the blurred clip behind the call screen is darkened (0-1)
ACCEPT = (52, 199, 89)       # answer button color
DECLINE = (255, 59, 48)      # decline button color
FONTS = ["/System/Library/Fonts/Supplemental/Arial Bold.ttf",     # macOS
         "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",  # Linux
         "C:/Windows/Fonts/arialbd.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 font(share):
    return ImageFont.truetype(FONT_FILE, round(w * share))

def handset(draw, cx, cy, r, angle):
    """A phone handset icon: a thick arc with an ear and a mouth piece, turned by `angle` degrees."""
    cx -= r * 0.36 * math.cos(math.radians(270 + angle))  # nudge it so the icon, not the arc's circle, is centered
    cy -= r * 0.36 * math.sin(math.radians(270 + angle))
    draw.arc([cx - r, cy - r, cx + r, cy + r], 200 + angle, 340 + angle, fill="white", width=round(r * 0.38))
    for a in (200 + angle, 340 + angle):
        ex, ey = cx + r * 0.86 * math.cos(math.radians(a)), cy + r * 0.86 * math.sin(math.radians(a))
        draw.ellipse([ex - r * 0.3, ey - r * 0.3, ex + r * 0.3, ey + r * 0.3], fill="white")

def call_screen():
    img = Image.new("RGBA", (w, h))
    draw = ImageDraw.Draw(img)
    draw.text((w / 2, h * 0.14), STATUS, font=font(0.045), anchor="mm", fill=(235, 235, 240))
    draw.text((w / 2, h * 0.21), CALLER, font=font(0.11), anchor="mm", fill="white")
    r = w * 0.15
    draw.ellipse([w / 2 - r, h * 0.36 - r, w / 2 + r, h * 0.36 + r], fill=(142, 142, 147))
    draw.text((w / 2, h * 0.36), CALLER[0], font=font(0.15), anchor="mm", fill="white")
    for x, color, label, angle in ((0.25, DECLINE, "Decline", 0), (0.75, ACCEPT, "Accept", -135)):
        cx, cy, br = w * x, h * 0.82, w * 0.1
        draw.ellipse([cx - br, cy - br, cx + br, cy + br], fill=color)
        handset(draw, cx, cy, br * 0.5, angle)
        draw.text((cx, cy + br + w * 0.05), label, font=font(0.04), anchor="mm", fill="white")
    return img

def overlay(t):
    """The call screen, with a ring pulsing out of the answer button, faded out after END."""
    img = screen.copy()
    pulse = (t * 1.2) % 1
    cx, cy, r = w * 0.75, h * 0.82, w * 0.1 * (1 + 0.45 * pulse)
    ring = Image.new("RGBA", (w, h))
    ImageDraw.Draw(ring).ellipse([cx - r, cy - r, cx + r, cy + r], outline=ACCEPT + (round(200 * (1 - pulse)),),
                                 width=max(2, w // 120))
    img = Image.alpha_composite(ring, img)
    alpha = min(max(1 - (t - END) / FADE, 0), 1)
    if alpha < 1:
        img.putalpha(img.getchannel("A").point(lambda a: round(a * alpha)))
    return img

def probe(path):
    info = json.loads(subprocess.check_output(["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries",
                                               "stream=width,height,r_frame_rate:format=duration", "-of", "json", path]))
    s = info["streams"][0]
    num, den = s["r_frame_rate"].split("/")
    return s["width"], s["height"], s["r_frame_rate"], float(num) / float(den), float(info["format"]["duration"])

def render(src, out):
    """Blur and darken the clip behind the call screen until END, then fade both away, keeping the audio."""
    behind = (f"[0:v]split[clip][b];[b]boxblur=18:2,colorchannelmixer=rr={1 - DARKEN}:gg={1 - DARKEN}:bb={1 - DARKEN},"
              f"format=rgba,fade=t=out:st={END}:d={FADE}:alpha=1[blur];[clip][blur]overlay[bg];")
    ff = subprocess.Popen(["ffmpeg", "-y", "-v", "error", "-i", src,
                           "-f", "rawvideo", "-pix_fmt", "rgba", "-s", f"{w}x{h}", "-r", rate, "-i", "-",
                           "-filter_complex", behind + "[bg][1:v]overlay=shortest=1,format=yuv420p[v]",
                           "-map", "[v]", "-map", "0:a?", "-c:v", "libx264", "-crf", "18", "-c:a", "copy", out],
                          stdin=subprocess.PIPE)
    for i in range(math.ceil(duration * fps)):
        ff.stdin.write(overlay(i / fps).tobytes())
    ff.stdin.close()
    if ff.wait():
        sys.exit("ffmpeg failed")

src, out = sys.argv[1:3]
w, h, rate, fps, duration = probe(src)
screen = call_screen()
render(src, out)
```

## 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)
