---
title: "How to add a TV turn off with Claude (tested prompt and script)"
description: "At 4 seconds the picture squeezes from top and bottom into a glowing white line across the middle, the line pulls in to a dot, and the dot fades to a black screen. Install one skill and ask Claude Code, or run the Python script we tested yourself."
url: https://www.recharm.com/effects/tv-turn-off
---

# How to add a TV turn off with Claude

At 4 seconds the picture squeezes from top and bottom into a glowing white line across the middle, the line pulls in to a dot, and the dot fades to a black screen.

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 TV turn off to input.mp4
   Second the picture starts to collapse: 4.0
   Seconds for the picture to squash into a line: 0.25
   ```

## 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 tv turn off 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                                     |
| -------- | ------- | ------------------------------------------------ |
| `START`  | `4.0`   | Second the picture starts to collapse.           |
| `SQUASH` | `0.25`  | Seconds for the picture to squash into a line.   |
| `SHRINK` | `0.30`  | Seconds for the line to shrink into a dot.       |
| `FADE`   | `0.45`  | Seconds for the dot to fade out.                 |
| `LINE`   | `6`     | Thickness of the white line in pixels.           |
| `DOT`    | `14`    | Diameter of the dot in pixels.                   |
| `GLOW`   | `10`    | Blur radius of the glow around the line and dot. |

## Without the skill

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

```
Add an old CRT TV turn-off to input.mp4 at 4 seconds. From 4.0 to 4.25 seconds, squeeze the picture vertically toward the center line (height eases from 100% down to a 6-pixel line, scaling with progress squared) while blending it toward pure white (255, 255, 255), with black above and below. From 4.25 to 4.55 seconds, show a pure white horizontal line 6 pixels thick centered vertically, shrinking from the full frame width to a 14-pixel dot in the center, with a soft white glow around it (Gaussian blur radius 10). From 4.55 to 5.0 seconds, the dot shrinks to half its size and fades out. After 5.0 seconds, the screen stays black to the end. Leave everything before 4 seconds untouched. Use Python with Pillow and numpy to draw the frames (don't use ffmpeg's drawtext filter), keep the audio but fade it out from 4.0 to 4.55 seconds, keep the size and frame rate, and save it as output.mp4.
```

## Run it without Claude

This is the exact script we tested. Save it as `tv-turn-off.py` and run:

```
python3 tv-turn-off.py input.mp4 output.mp4
```

```
#!/usr/bin/env python3
"""TV turn off: the picture squashes into a glowing white line, shrinks to a dot, and the screen goes black.

Usage: python3 tv-turn-off.py input.mp4 output.mp4
Needs ffmpeg, Pillow and numpy (pip install pillow numpy).
"""
import json
import subprocess
import sys

import numpy as np
from PIL import Image, ImageDraw, ImageFilter

START = 4.0       # second the picture starts to collapse
SQUASH = 0.25     # seconds for the picture to squash into a line
SHRINK = 0.30     # seconds for the line to shrink into a dot
FADE = 0.45       # seconds for the dot to fade out
LINE = 6          # thickness of the white line in pixels
DOT = 14          # diameter of the dot in pixels
GLOW = 10         # blur radius of the glow around the line and dot

def ease_in(p):
    return min(max(p, 0), 1) ** 2

def squashed(img, p):
    """The picture squeezed to (1 - p) of its height and washed toward white, centered on black."""
    rows = max(LINE, round(h * (1 - ease_in(p))))
    washed = Image.blend(img, Image.new("RGB", (w, h), "white"), ease_in(p) ** 0.5)
    screen = Image.new("RGB", (w, h))
    screen.paste(washed.resize((w, rows), Image.BILINEAR), (0, (h - rows) // 2))
    return screen

def glowing(draw_shape, strength=1.0):
    """A white shape on black with a soft glow around it, dimmed by strength."""
    shape = Image.new("L", (w, h))
    draw_shape(ImageDraw.Draw(shape))
    glow = np.asarray(shape.filter(ImageFilter.GaussianBlur(GLOW)), np.float32) * 1.6
    light = np.maximum(np.asarray(shape, np.float32), glow) * strength
    return Image.fromarray(np.repeat(np.clip(light, 0, 255).astype(np.uint8)[:, :, None], 3, axis=2))

def line(p):
    half = max(DOT / 2, w / 2 * (1 - ease_in(p)))
    return glowing(lambda d: d.rectangle([w / 2 - half, (h - LINE) / 2, w / 2 + half, (h + LINE) / 2], fill=255))

def dot(p):
    r = DOT / 2 * (1 - 0.5 * p)
    return glowing(lambda d: d.ellipse([w / 2 - r, h / 2 - r, w / 2 + r, h / 2 + r], fill=255), 1 - p)

def screen(img, t):
    if t < START:
        return img
    t -= START
    if t < SQUASH:
        return squashed(img, t / SQUASH)
    t -= SQUASH
    if t < SHRINK:
        return line(t / SHRINK)
    t -= SHRINK
    if t < FADE:
        return dot(t / FADE)
    return Image.new("RGB", (w, h))

def probe(path):
    info = json.loads(subprocess.check_output(["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries",
                                               "stream=width,height,r_frame_rate", "-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)

src, out = sys.argv[1:3]
w, h, rate, fps = probe(src)
reader = subprocess.Popen(["ffmpeg", "-v", "error", "-i", src, "-f", "rawvideo", "-pix_fmt", "rgb24", "-"],
                          stdout=subprocess.PIPE)
writer = subprocess.Popen(["ffmpeg", "-y", "-v", "error", "-f", "rawvideo", "-pix_fmt", "rgb24", "-s", f"{w}x{h}",
                           "-r", rate, "-i", "-", "-i", src, "-map", "0:v", "-map", "1:a?",
                           "-af", f"afade=t=out:st={START}:d={SQUASH + SHRINK}",
                           "-c:v", "libx264", "-crf", "18", "-pix_fmt", "yuv420p", "-c:a", "aac", "-shortest", out],
                          stdin=subprocess.PIPE)
i = 0
while raw := reader.stdout.read(w * h * 3):
    writer.stdin.write(screen(Image.frombytes("RGB", (w, h), raw), i / fps).tobytes())
    i += 1
writer.stdin.close()
if reader.wait() or writer.wait():
    sys.exit("ffmpeg failed")
```

## More retro and film

- [1950s color film look **1950s color film look**](https://www.recharm.com/effects/1950s-color-film-look)
- [35mm film look **35mm film look**](https://www.recharm.com/effects/35mm-film-look)
- [70s film look **70s film look**](https://www.recharm.com/effects/70s-film-look)
- [Camcorder date stamp **Camcorder date stamp**](https://www.recharm.com/effects/camcorder-date-stamp)
- [Camcorder viewfinder **Camcorder viewfinder**](https://www.recharm.com/effects/camcorder-viewfinder)

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