creator-editing-studio 1.1.1 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/template/CLAUDE.md +14 -11
- package/template/requirements.txt +23 -17
- package/template/scripts/make_cutout.py +181 -68
- package/template/templates/BRIEF.md +90 -88
package/package.json
CHANGED
package/template/CLAUDE.md
CHANGED
|
@@ -184,16 +184,19 @@ background plate (designed, or the original footage)
|
|
|
184
184
|
|
|
185
185
|
- **The cutout must come from the same clip as its background plate**, frame-aligned. Never
|
|
186
186
|
combine a cutout from one take with footage from another.
|
|
187
|
-
- **
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
187
|
+
- **The matte is built automatically from ordinary footage.** No green screen, and never ask the
|
|
188
|
+
user for one — most people have never shot against green and do not know the term. Segment the
|
|
189
|
+
subject per frame, then **temporally smooth the alpha**, which is not optional: a per-frame matte
|
|
190
|
+
shimmers along the edge, and type sitting against a head is exactly where that shows. Finish with
|
|
191
|
+
spill-free cleanup: ~0.5px choke, 0.5–1px feather.
|
|
192
|
+
- **Quality is worst where it is most visible:** flyaway hair, motion blur, and a hand crossing in
|
|
193
|
+
front of the text. The light wrap below hides a good deal of it. If a shot simply will not hold,
|
|
194
|
+
say so and move the text rather than shipping a halo.
|
|
195
|
+
- **If the user happens to have a background-free or green version, prefer it** — chroma keying
|
|
196
|
+
still beats automatic matting on hair. Use it **only for the alpha** and take the subject's colour
|
|
197
|
+
from the original, so no green ever reaches the edges. Verify the pair first: identical duration,
|
|
198
|
+
fps, resolution and frame count, subject aligned on the same frame (one frame out makes a ghost).
|
|
199
|
+
This is an upgrade for people who already work that way, never a requirement.
|
|
197
200
|
- **Supplied cutouts** must have real transparency (ProRes 4444, WebM with alpha, or PNG sequence).
|
|
198
201
|
An MP4 cannot hold transparency — if one arrives, stop and tell the user.
|
|
199
202
|
- Play transparent video with `<OffthreadVideo transparent src={staticFile(...)} />`.
|
|
@@ -216,7 +219,7 @@ background plate (designed, or the original footage)
|
|
|
216
219
|
force-align that exact text to the audio with WhisperX's aligner. Never use SRT timings
|
|
217
220
|
directly — they are line-level and padded for readability, not word-accurate.
|
|
218
221
|
- With no script, transcribe with WhisperX, then show the transcript for correction before building.
|
|
219
|
-
3. **Cutouts:**
|
|
222
|
+
3. **Cutouts:** build the matte from the footage automatically, or validate a supplied cutout (see above). Only needed for shots that want text behind the subject.
|
|
220
223
|
4. **Beat sheet:** from the script and the user's marked punch lines, write a short plan — which
|
|
221
224
|
moment gets which treatment — and confirm with the user before building.
|
|
222
225
|
- **Read their saved references first** (`editing_os_references`). They are the whole reason
|
|
@@ -1,17 +1,23 @@
|
|
|
1
|
-
# The Python half of the studio: transcription, word alignment, cut detection,
|
|
2
|
-
# green-screen cutouts and colour grading.
|
|
3
|
-
#
|
|
4
|
-
# python -m venv .venv
|
|
5
|
-
# .venv/bin/pip install -r requirements.txt (Windows: .venv\Scripts\pip)
|
|
6
|
-
#
|
|
7
|
-
# Python 3.11 or 3.12. Not 3.13+ — WhisperX's dependencies do not support it yet, and the
|
|
8
|
-
# failure is a wall of build errors rather than a clear message.
|
|
9
|
-
#
|
|
10
|
-
# certifi is not optional on macOS: torch downloads the alignment model with urllib, which
|
|
11
|
-
# on a python.org build has no root certificates at all.
|
|
12
|
-
|
|
13
|
-
whisperx==3.8.6
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
1
|
+
# The Python half of the studio: transcription, word alignment, cut detection,
|
|
2
|
+
# green-screen cutouts and colour grading.
|
|
3
|
+
#
|
|
4
|
+
# python -m venv .venv
|
|
5
|
+
# .venv/bin/pip install -r requirements.txt (Windows: .venv\Scripts\pip)
|
|
6
|
+
#
|
|
7
|
+
# Python 3.11 or 3.12. Not 3.13+ — WhisperX's dependencies do not support it yet, and the
|
|
8
|
+
# failure is a wall of build errors rather than a clear message.
|
|
9
|
+
#
|
|
10
|
+
# certifi is not optional on macOS: torch downloads the alignment model with urllib, which
|
|
11
|
+
# on a python.org build has no root certificates at all.
|
|
12
|
+
|
|
13
|
+
whisperx==3.8.6
|
|
14
|
+
# BiRefNet, for cutting the subject out of ordinary footage so text can sit behind them.
|
|
15
|
+
# MIT licensed and self-hosted: nothing uploads, and there is no per-video cost.
|
|
16
|
+
transformers>=4.44
|
|
17
|
+
timm>=1.0
|
|
18
|
+
einops>=0.8
|
|
19
|
+
kornia>=0.7
|
|
20
|
+
torch>=2.2
|
|
21
|
+
numpy>=1.26
|
|
22
|
+
Pillow>=10.0
|
|
23
|
+
certifi>=2024.2.2
|
|
@@ -1,68 +1,181 @@
|
|
|
1
|
-
"""Build a transparent cutout of the subject for a frame range
|
|
2
|
-
|
|
3
|
-
Usage (from the project root):
|
|
4
|
-
python scripts/make_cutout.py <
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
1
|
+
"""Build a transparent cutout of the subject for a frame range, from ordinary footage.
|
|
2
|
+
|
|
3
|
+
Usage (from the project root):
|
|
4
|
+
python scripts/make_cutout.py <video> <out_dir> <first_frame> <last_frame>
|
|
5
|
+
python scripts/make_cutout.py <video> <out_dir> <first> <last> --alpha-from <clip>
|
|
6
|
+
python scripts/make_cutout.py <video> <out_dir> <first> <last> --model full
|
|
7
|
+
|
|
8
|
+
Writes RGBA PNGs named f<frame>.png (absolute source frame numbers), so a composition can map
|
|
9
|
+
composition frames to cutout frames directly.
|
|
10
|
+
|
|
11
|
+
No green screen. The matte is segmented from the footage itself, because asking a customer to
|
|
12
|
+
shoot against green makes the feature unavailable to almost all of them - most have never done
|
|
13
|
+
it and do not know the term.
|
|
14
|
+
|
|
15
|
+
--alpha-from stays for the case where a background-free or green copy already exists, which is
|
|
16
|
+
faster and still sharper on hair. It is used ONLY for the alpha; colour always comes from the
|
|
17
|
+
original clip, so no green ever reaches the subject's edges.
|
|
18
|
+
|
|
19
|
+
Two things decide whether this reads as real rather than pasted on:
|
|
20
|
+
|
|
21
|
+
* The alpha is smoothed ACROSS frames. A per-frame matte shimmers along the edge, and type
|
|
22
|
+
sitting against someone's head is precisely where the eye catches it. A 3-frame median kills
|
|
23
|
+
single-frame flicker without the lag an average introduces on fast motion.
|
|
24
|
+
* The edge is choked before it is feathered, so the old background cannot leak into the seam.
|
|
25
|
+
|
|
26
|
+
It is worst where it is most visible: flyaway hair, motion blur, a hand crossing the text. If a
|
|
27
|
+
shot will not hold, move the text rather than ship a halo.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
import argparse
|
|
31
|
+
import json
|
|
32
|
+
import subprocess
|
|
33
|
+
import sys
|
|
34
|
+
from pathlib import Path
|
|
35
|
+
|
|
36
|
+
import numpy as np
|
|
37
|
+
from PIL import Image
|
|
38
|
+
import sys as _sys, pathlib as _pl
|
|
39
|
+
_sys.path.insert(0, str(_pl.Path(__file__).resolve().parent / 'lib'))
|
|
40
|
+
from media import FFMPEG, FFPROBE # resolved per platform - never hardcode a tool path
|
|
41
|
+
|
|
42
|
+
MODELS = {"lite": "ZhengPeng7/BiRefNet_lite", "full": "ZhengPeng7/BiRefNet"}
|
|
43
|
+
SEG_SIZE = 1024
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def probe(path: str):
|
|
47
|
+
"""Real dimensions and frame rate. Never assume 1920x1080 at 30 - vertical phone footage is normal."""
|
|
48
|
+
out = subprocess.run(
|
|
49
|
+
[FFPROBE, "-v", "quiet", "-print_format", "json", "-show_streams", "-select_streams", "v:0", path],
|
|
50
|
+
capture_output=True, text=True, check=True,
|
|
51
|
+
).stdout
|
|
52
|
+
s = json.loads(out)["streams"][0]
|
|
53
|
+
num, den = (s.get("r_frame_rate") or "30/1").split("/")
|
|
54
|
+
return int(s["width"]), int(s["height"]), float(num) / float(den or 1)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def read_frames(path: str, first: int, count: int, w: int, h: int, fps: float):
|
|
58
|
+
proc = subprocess.Popen(
|
|
59
|
+
[FFMPEG, "-v", "error", "-ss", f"{first / fps:.6f}", "-i", path, "-frames:v", str(count),
|
|
60
|
+
"-f", "rawvideo", "-pix_fmt", "rgb24", "-"],
|
|
61
|
+
stdout=subprocess.PIPE,
|
|
62
|
+
)
|
|
63
|
+
size = w * h * 3
|
|
64
|
+
for _ in range(count):
|
|
65
|
+
buf = proc.stdout.read(size)
|
|
66
|
+
if len(buf) < size:
|
|
67
|
+
break
|
|
68
|
+
yield np.frombuffer(buf, np.uint8).reshape(h, w, 3)
|
|
69
|
+
proc.stdout.close()
|
|
70
|
+
proc.wait()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def green_matte(green: np.ndarray) -> np.ndarray:
|
|
74
|
+
"""Alpha 0..1 from how green each pixel is, relative to the flat background green."""
|
|
75
|
+
g = green.astype(np.float32)
|
|
76
|
+
greenness = g[..., 1] - np.maximum(g[..., 0], g[..., 2])
|
|
77
|
+
background = np.median(greenness[greenness > 60]) if (greenness > 60).any() else 150.0
|
|
78
|
+
lo, hi = 0.2 * background, 0.7 * background
|
|
79
|
+
t = np.clip((greenness - lo) / (hi - lo), 0, 1)
|
|
80
|
+
return 1 - t * t * (3 - 2 * t) # smoothstep: soft, stable edge
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def load_segmenter(which: str):
|
|
84
|
+
"""BiRefNet, lazily. Importing torch costs seconds; do not pay it on the --alpha-from path."""
|
|
85
|
+
try:
|
|
86
|
+
import torch
|
|
87
|
+
from transformers import AutoModelForImageSegmentation
|
|
88
|
+
except ModuleNotFoundError as exc:
|
|
89
|
+
print(f"Cannot import {exc.name}. The matting model needs the studio's Python environment.", file=sys.stderr)
|
|
90
|
+
print(" see what is installed with: npm run doctor", file=sys.stderr)
|
|
91
|
+
raise SystemExit(2)
|
|
92
|
+
|
|
93
|
+
# trust_remote_code: these repos ship their own model class, which transformers executes.
|
|
94
|
+
model = AutoModelForImageSegmentation.from_pretrained(MODELS[which], trust_remote_code=True)
|
|
95
|
+
model.eval()
|
|
96
|
+
# float32 on CPU: half precision is slower there rather than faster, and can produce NaNs.
|
|
97
|
+
device = "cuda" if torch.cuda.is_available() else "cpu"
|
|
98
|
+
model.to(device)
|
|
99
|
+
return torch, model, device
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def segment(torch, model, device, rgb: np.ndarray) -> np.ndarray:
|
|
103
|
+
"""Alpha 0..1 for one frame, returned at the frame's own resolution."""
|
|
104
|
+
h, w = rgb.shape[:2]
|
|
105
|
+
img = Image.fromarray(rgb).resize((SEG_SIZE, SEG_SIZE), Image.BILINEAR)
|
|
106
|
+
x = np.asarray(img, dtype=np.float32) / 255.0
|
|
107
|
+
x = (x - np.array([0.485, 0.456, 0.406], np.float32)) / np.array([0.229, 0.224, 0.225], np.float32)
|
|
108
|
+
t = torch.from_numpy(x).permute(2, 0, 1).unsqueeze(0).to(device)
|
|
109
|
+
with torch.no_grad():
|
|
110
|
+
pred = model(t)[-1].sigmoid()[0, 0].cpu().numpy()
|
|
111
|
+
return np.asarray(Image.fromarray((pred * 255).astype(np.uint8)).resize((w, h), Image.BILINEAR), np.float32) / 255.0
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def smooth_in_time(alphas):
|
|
115
|
+
"""3-frame median. Removes single-frame flicker without the lag an average would add."""
|
|
116
|
+
if len(alphas) < 3:
|
|
117
|
+
return alphas
|
|
118
|
+
out = [alphas[0]]
|
|
119
|
+
for i in range(1, len(alphas) - 1):
|
|
120
|
+
out.append(np.median(np.stack([alphas[i - 1], alphas[i], alphas[i + 1]]), axis=0))
|
|
121
|
+
out.append(alphas[-1])
|
|
122
|
+
return out
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def clean_edge(alpha: np.ndarray) -> np.ndarray:
|
|
126
|
+
"""Choke by a pixel so the old background cannot leak into the seam, then feather lightly."""
|
|
127
|
+
choked = np.minimum.reduce([alpha, np.roll(alpha, 1, 0), np.roll(alpha, -1, 0), np.roll(alpha, 1, 1), np.roll(alpha, -1, 1)])
|
|
128
|
+
return (choked * 4 + np.roll(choked, 1, 0) + np.roll(choked, -1, 0) + np.roll(choked, 1, 1) + np.roll(choked, -1, 1)) / 8
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def main() -> None:
|
|
132
|
+
ap = argparse.ArgumentParser(description="Transparent cutout of the subject, from ordinary footage.")
|
|
133
|
+
ap.add_argument("video")
|
|
134
|
+
ap.add_argument("out_dir", type=Path)
|
|
135
|
+
ap.add_argument("first", type=int)
|
|
136
|
+
ap.add_argument("last", type=int)
|
|
137
|
+
ap.add_argument("--alpha-from", default=None,
|
|
138
|
+
help="Optional background-free or green copy of the SAME take, used only for the alpha.")
|
|
139
|
+
ap.add_argument("--model", choices=sorted(MODELS), default="lite",
|
|
140
|
+
help="lite is several times faster and good enough for most shots; full is sharper on hair.")
|
|
141
|
+
args = ap.parse_args()
|
|
142
|
+
|
|
143
|
+
w, h, fps = probe(args.video)
|
|
144
|
+
count = args.last - args.first + 1
|
|
145
|
+
args.out_dir.mkdir(parents=True, exist_ok=True)
|
|
146
|
+
|
|
147
|
+
frames = list(read_frames(args.video, args.first, count, w, h, fps))
|
|
148
|
+
if not frames:
|
|
149
|
+
print("No frames read - check the frame range against the clip's length.", file=sys.stderr)
|
|
150
|
+
raise SystemExit(1)
|
|
151
|
+
|
|
152
|
+
if args.alpha_from:
|
|
153
|
+
aw, ah, afps = probe(args.alpha_from)
|
|
154
|
+
if (aw, ah) != (w, h) or abs(afps - fps) > 0.01:
|
|
155
|
+
print(f"The alpha clip does not match: {aw}x{ah}@{afps:.2f} against {w}x{h}@{fps:.2f}.", file=sys.stderr)
|
|
156
|
+
print("A mismatched pair makes a halo or a ghost. Re-export it to match, or drop --alpha-from.", file=sys.stderr)
|
|
157
|
+
raise SystemExit(1)
|
|
158
|
+
print(f"Alpha from the supplied clip, colour from the original - {count} frames.")
|
|
159
|
+
alphas = [green_matte(g) for g in read_frames(args.alpha_from, args.first, count, w, h, fps)]
|
|
160
|
+
else:
|
|
161
|
+
print(f"Segmenting {count} frames at {w}x{h} with BiRefNet ({args.model}).")
|
|
162
|
+
print("The first run downloads the model. On a CPU expect a second or two per frame.")
|
|
163
|
+
torch, model, device = load_segmenter(args.model)
|
|
164
|
+
print(f"Running on {device}.")
|
|
165
|
+
alphas = []
|
|
166
|
+
for i, rgb in enumerate(frames):
|
|
167
|
+
alphas.append(segment(torch, model, device, rgb))
|
|
168
|
+
if (i + 1) % 10 == 0 or i + 1 == count:
|
|
169
|
+
print(f" {i + 1}/{count}", flush=True)
|
|
170
|
+
|
|
171
|
+
for i, a in enumerate(smooth_in_time(alphas)):
|
|
172
|
+
alpha = (clean_edge(a).clip(0, 1) * 255).round().astype(np.uint8)
|
|
173
|
+
Image.fromarray(np.dstack([frames[i], alpha]), "RGBA").save(
|
|
174
|
+
args.out_dir / f"f{args.first + i}.png", compress_level=1
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
print(f"wrote {len(alphas)} frames to {args.out_dir}")
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
if __name__ == "__main__":
|
|
181
|
+
main()
|
|
@@ -1,88 +1,90 @@
|
|
|
1
|
-
# Brief: {{name}}
|
|
2
|
-
|
|
3
|
-
Fill in what you can. Plain words are fine. Leave a line blank if you don't care.
|
|
4
|
-
When done: drop your files in this folder's `footage/` (and `screenshots/`), then run
|
|
5
|
-
`npm run prep -- {{name}}` and start the session with "start {{name}}".
|
|
6
|
-
|
|
7
|
-
## Basics
|
|
8
|
-
Format: 16:9 <!-- 16:9, 9:16, or both -->
|
|
9
|
-
Language: en <!-- en, hi, ar ... the language you speak in the video -->
|
|
10
|
-
Talking head file: <!-- file name in footage/, e.g. —.mp4. Leave blank if there's only one clip. -->
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
|
66
|
-
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
|
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
79
|
-
|
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
-
|
|
|
83
|
-
|
|
|
84
|
-
|
|
|
85
|
-
|
|
|
86
|
-
|
|
|
87
|
-
|
|
|
88
|
-
|
|
|
1
|
+
# Brief: {{name}}
|
|
2
|
+
|
|
3
|
+
Fill in what you can. Plain words are fine. Leave a line blank if you don't care.
|
|
4
|
+
When done: drop your files in this folder's `footage/` (and `screenshots/`), then run
|
|
5
|
+
`npm run prep -- {{name}}` and start the session with "start {{name}}".
|
|
6
|
+
|
|
7
|
+
## Basics
|
|
8
|
+
Format: 16:9 <!-- 16:9, 9:16, or both -->
|
|
9
|
+
Language: en <!-- en, hi, ar ... the language you speak in the video -->
|
|
10
|
+
Talking head file: <!-- file name in footage/, e.g. —.mp4. Leave blank if there's only one clip. -->
|
|
11
|
+
Background-free copy: <!-- Optional. Leave blank. Only fill this in if you already export a
|
|
12
|
+
version with the background removed or replaced by flat green; the
|
|
13
|
+
cutout is built automatically from your normal footage otherwise. -->
|
|
14
|
+
Length target: <!-- e.g. 25s, 90s -->
|
|
15
|
+
|
|
16
|
+
## Script
|
|
17
|
+
<!-- Paste the script exactly as you read it. Numbers as digits: $99, 11 minutes, 3 days. -->
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
## The one thing viewers must remember
|
|
21
|
+
<!-- One sentence. Everything in the edit serves this. -->
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
## Must-have moments
|
|
25
|
+
<!-- By the words you say, not by time. Plain words are fine.
|
|
26
|
+
- When I say "look at this" → my clip shrinks and other creators' clips appear
|
|
27
|
+
- "millions of views" → a counter racing up to 1M+ -->
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## Moments from references
|
|
31
|
+
<!-- You DON'T need the name of the effect. Clip + time + what you like about it.
|
|
32
|
+
Format: - clip-file.mp4 mm:ss-mm:ss — what you like (feel words are fine: snappy, floaty, punchy)
|
|
33
|
+
- a-reel-you-like.mp4 00:02-00:04 — the colour screens flipping with each phrase, feels punchy -->
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
## Effects from the library
|
|
37
|
+
<!-- Optional: pick any by name (see the list at the bottom), and say where.
|
|
38
|
+
- colour flip → "different person, different story" -->
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
## B-roll
|
|
42
|
+
<!-- Which clip where, by the words you say. Mark clips you DON'T want used.
|
|
43
|
+
- creators' clips → "all of these people" -->
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
## Screenshots / things to blur
|
|
47
|
+
<!-- Names, emails, prices, logos that must not be readable. -->
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
## CTA / ending
|
|
51
|
+
<!-- What the viewer should do, and what the last frame shows. -->
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## Sound
|
|
55
|
+
SFX library: audio/ <!-- put sound effects in this folder's audio/, or say "none" -->
|
|
56
|
+
Music: added by me in Premiere / Instagram <!-- or a file name in audio/ -->
|
|
57
|
+
|
|
58
|
+
## Don't want
|
|
59
|
+
<!-- Anything you dislike: e.g. boxes over my footage, huge text, bouncy motion. -->
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
### Effects library (names you can use)
|
|
65
|
+
| Name | What it looks like |
|
|
66
|
+
|---|---|
|
|
67
|
+
| Text behind me | Big headline sits behind your head (works from normal footage) |
|
|
68
|
+
| Card swap | You shrink into a rounded card, turn into another clip mid-shrink, a row of cards slides in and drifts |
|
|
69
|
+
| Colour flip | Hard cuts to solid accent / ink screens on each phrase; a word rolls into the next and the colours swap |
|
|
70
|
+
| Counter race | A number races up from 0 and lands on a value (e.g. 1,000,000+) |
|
|
71
|
+
| Zoom-through cut | A jump cut hidden by a quick push-in that eases back — used on every cut by default |
|
|
72
|
+
| Gradient CTA | Dark gradient rises from the bottom, small label + big word typed on the VO, then ticked pointers |
|
|
73
|
+
| Browser mockup | Screenshots inside a clean browser window that pans and zooms to the detail |
|
|
74
|
+
| Pointer click | An arrow glides to a spot and clicks, with a ripple |
|
|
75
|
+
| Rolling number | Digits roll from one value to another (e.g. $26.50 → $48.94) |
|
|
76
|
+
| Highlight marker | Accent marker wipes behind a key phrase |
|
|
77
|
+
| Side card | You move into a card beside the graphics (16:9) or below them (9:16) |
|
|
78
|
+
| Headline to pill | A big headline shrinks into a small corner tag that stays on screen |
|
|
79
|
+
| Word-by-word captions | On by default (looks: clean, block, highlight, pop) |
|
|
80
|
+
| Whip pan | Fast blurred pan between two unrelated shots |
|
|
81
|
+
| Push | The next scene pushes the last one out |
|
|
82
|
+
| Mask wipe | A soft-edged wipe reveals the next scene |
|
|
83
|
+
| Match cut | Cut hidden inside a shared shape or movement |
|
|
84
|
+
| Dip | Quick dip through the background colour |
|
|
85
|
+
| Speed ramp | Glide into slow-mo (or speed-up) and back out |
|
|
86
|
+
| Beat cut | Cuts land on the beat of your music |
|
|
87
|
+
| Tighten it | Silence and filler words removed, every join hidden as a punch-in |
|
|
88
|
+
| Cut to the music | Whole edit built off the track: slow intro, faster build, hardest on the drop |
|
|
89
|
+
| Film look | Grain, halation, light leak, gate weave (looks: clean, film, super8, cinema) |
|
|
90
|
+
| Sound pass | Whooshes, impacts and risers placed off the cut list, ducked under the voice |
|