TikTok Psychology Explainer Video
End-to-end workflow for producing a narrated, illustrated TikTok video that explains a psychology concept. Invoked by the user with /tiktok-psych-video.
The full method with all implementation details is documented in docs/tiktok-psych-video-method.md. Read that file before starting — it contains exact API calls, voice settings, style prompts, image sizes, Remotion component specs, and lessons learned.
Workflow with Approval Gates
Phase 1: Ideation (→ user approves concept)
The user may invoke this skill in two ways:
- With a content gap target: User passes a screenshot of TikTok's Creator Search Insights "Content gap" tab, or types specific keywords/topics they want to target. This is the preferred approach — it ensures every video fills validated demand.
- Without a target: Claude picks concepts based on keyword map and dedup check.
Dedup Check — Read ALL content/tiktok/*/brief.md files. Don't duplicate concepts, angles, or stories.
Read keyword map — Read docs/tiktok-keyword-map.md for validated search queries, content gaps, and the psych concept → search query mapping table.
Ideation — If the user provided a content gap or target keyword:
- Identify which gap(s) Clarido can credibly fill
- Pick the psych concept that best explains why that topic matters (e.g., "daily tracker journal" → Cognitive Offloading, "share your daily thoughts" → Expressive Writing)
- The hook and script must use the exact search phrase people are typing
If no target provided: Pick 2-3 psychology concepts with compelling origin stories that connect to Clarido's value prop, prioritizing concepts that map to high-demand search queries from the keyword map.
Present concepts to the user and wait for approval before proceeding.
Phase 2: Script (→ user approves script)
Write script — Read docs/writing-style-reference.md first. Target 30-45 seconds (75-110 words at 1.25x speed; ~2.5 words/sec). Every sentence must earn its spot. Cut ruthlessly. Structure is curiosity hook → factoid → personal → landing line:
- Curiosity hook (0-3s): One sentence bridging something unexpected to a relatable problem. Pattern: "[Unexpected subject] [accidentally/proved] why [relatable problem]." E.g., "A waitress accidentally explained why your brain won't shut up at night." This creates a curiosity gap before the story starts.
- Factoid/story (3-15s): The actual study, told as compressed narrative. Concrete, visual, specific.
- Bridge to viewer (15-25s): Make it personal. "That's why you lie awake at 3am."
- Landing line (25-30s): Gut-punch reframe, NO CTA. Video ends on the punch so TikTok auto-loops seamlessly.
Tone is Style B: dry, restrained, trust the viewer to feel the weight. Don't over-explain the emotion. Say search keywords ("overthinking," "brain dump," "journaling," "mental clarity") out loud where natural. Content territory includes psych studies, cognitive biases, and brain quirks — not limited to overthinking/brain dump. See the reference script in the method doc for the exact target format.
Generate caption & hashtags — 3-5 niche hashtags only. Never use #fyp, #viral, #science, #brainhacks. Use: #overthinking, #[concept], #mentalclarity, #braindump, #journaling, #anxietyrelief.
Create content folder (content/tiktok/YYYY-MM-DD_HHMM_slug/) and save brief.md.
Present the full brief to the user and wait for approval before proceeding.
Phase 3: Asset Generation (automated)
After script approval, run these scripts in sequence:
- Voiceover:
pipenv run python3 scripts/tiktok/voiceover.py <content-folder>
- Reads script from brief.md, calls ElevenLabs, speeds up 1.25x, saves to assets/
- Transcribe:
pipenv run python3 scripts/tiktok/transcribe.py <content-folder>
- Calls Deepgram Nova-3, saves transcript.json, prints sentence-level and word-level timestamps
- Plan slides — Use the transcript timestamps to plan ~10 slides at ~3s each (for 30s video) or ~15 slides at ~3s each (for 45s video). Every slide gets a unique illustration. No CTA slide at the end — final slide should be a simple closing image that loops cleanly back to slide 1. Add slide plan to brief.md.
- Write illustrations JSON — Save illustration specs to
assets/illustrations.json:[{"name": "slug-name", "prompt": "Scene description (style prefix added automatically)"}]
- Generate illustrations:
pipenv run python3 scripts/tiktok/illustrations.py <illustrations-json> <output-dir>
- Generates all illustrations with brand style references, portrait 1024x1536, transparent bg
Phase 4: Composition & Render (automated)
- Prepare assets:
pipenv run python3 scripts/tiktok/prepare_assets.py <content-folder>
- Copies illustrations + voiceover to
videos/public/ for Remotion
- Build Remotion composition — Create
videos/src/{ConceptName}TikTok/ with config.ts, Slide.tsx, index.tsx. Register in Root.tsx under <Folder name="TikTok">.
- Render:
cd videos && npx remotion render CompositionId out/output-name.mp4
- Archive: Copy mp4 back to content folder.
Phase 5: Deliver (automated)
- Email: Send the rendered video with caption and hashtags to both
abhinav@jabhi.ca and joieta@jabhi.ca using the Google Workspace MCP. Send two separate emails (one per recipient). Format:
- To:
abhinav@jabhi.ca and joieta@jabhi.ca (use abhinav@jabhi.ca as user_google_email for both sends)
- Subject:
{Concept Name} — TikTok Video
- Body: Caption text followed by hashtags, all on one line. No heading, no formatting — plain text ready to copy-paste into TikTok.
- Attachment: The rendered mp4 file from the content folder (use
path option)
Helper Scripts
| Script |
Purpose |
Input |
Output |
scripts/tiktok/voiceover.py |
ElevenLabs TTS + 1.25x speedup |
Content folder (reads brief.md) |
assets/voiceover-raw.mp3, assets/voiceover.mp3 |
scripts/tiktok/transcribe.py |
Deepgram Nova-3 word timestamps |
Content folder (reads voiceover.mp3) |
assets/transcript.json + printed table |
scripts/tiktok/illustrations.py |
OpenAI gpt-image-1.5 with style refs |
JSON config + output dir |
Portrait PNGs in output dir |
scripts/tiktok/prepare_assets.py |
Copy assets to Remotion public/ |
Content folder |
Files in videos/public/ |
Folder Structure
content/tiktok/YYYY-MM-DD_HHMM_slug/
├── brief.md # Script, caption, hashtags, slide plan
├── assets/
│ ├── illustrations/ # PNGs (portrait, transparent bg)
│ ├── illustrations.json # Illustration specs for regeneration
│ ├── voiceover-raw.mp3
│ ├── voiceover.mp3
│ └── transcript.json
└── slug.mp4 # Final rendered video
Critical Details (common mistakes)
- Image size: Must be
1024x1536 (portrait), NOT 1024x1024 — square images get cropped in vertical frame
- Audio import: Use
<Audio> from @remotion/media, NOT from core remotion
- ElevenLabs stability: Only 0.0, 0.5, or 1.0 — no in-between values. Only pass stability, no other voice_settings.
- Speed: Apply via ffmpeg post-generation, not as an ElevenLabs parameter
- Overflow: Set
overflow: "visible" on slide container to prevent zoom clipping
- No text overlays: TikTok captions + background music provide enough stimulation — don't add text to the video
- Run end-to-end: Generate all assets AND render the final video — don't stop at code
Key Files
- Writing style reference:
docs/writing-style-reference.md (Paul Graham essay + style guide)
- Method doc:
docs/tiktok-psych-video-method.md
- Brand reference images:
assets/illustrations/overwhelmed-filing-cabinet.png, floating-yellow-balloon.png, planting-yellow-seedling.png
- Example composition (new format, 30s):
videos/src/ParadoxOfChoiceTikTok/ (config.ts, Slide.tsx, index.tsx)
- Example brief (new format):
content/tiktok/2026-02-18_1430_paradox-of-choice/brief.md
- Legacy composition (old format, 60s):
videos/src/ZeigarnikTikTok/
1---2name: tiktok-psych-video3description: Produce a narrated, illustrated TikTok psychology explainer video for Clarido — from concept ideation through rendered mp4. Use when creating new TikTok content.4---5
6# TikTok Psychology Explainer Video
7
8End-to-end workflow for producing a narrated, illustrated TikTok video that explains a psychology concept. Invoked by the user with `/tiktok-psych-video`.
9
10The full method with all implementation details is documented in `docs/tiktok-psych-video-method.md`. **Read that file before starting** — it contains exact API calls, voice settings, style prompts, image sizes, Remotion component specs, and lessons learned.
11
12## Workflow with Approval Gates
13
14### Phase 1: Ideation (→ user approves concept)
15
16The user may invoke this skill in two ways:
17- **With a content gap target:** User passes a screenshot of TikTok's Creator Search Insights "Content gap" tab, or types specific keywords/topics they want to target. This is the preferred approach — it ensures every video fills validated demand.
18- **Without a target:** Claude picks concepts based on keyword map and dedup check.
19
201. **Dedup Check** — Read ALL `content/tiktok/*/brief.md` files. Don't duplicate concepts, angles, or stories.
212. **Read keyword map** — Read `docs/tiktok-keyword-map.md` for validated search queries, content gaps, and the psych concept → search query mapping table.
223. **Ideation** — If the user provided a content gap or target keyword:
23 - Identify which gap(s) Clarido can credibly fill
24 - Pick the psych concept that best explains *why* that topic matters (e.g., "daily tracker journal" → Cognitive Offloading, "share your daily thoughts" → Expressive Writing)
25 - The hook and script must use the exact search phrase people are typing
26
27 If no target provided: Pick 2-3 psychology concepts with compelling origin stories that connect to Clarido's value prop, prioritizing concepts that map to high-demand search queries from the keyword map.
284. **Present concepts** to the user and wait for approval before proceeding.
29
30### Phase 2: Script (→ user approves script)
31
324. **Write script** — Read `docs/writing-style-reference.md` first. **Target 30-45 seconds** (75-110 words at 1.25x speed; ~2.5 words/sec). Every sentence must earn its spot. Cut ruthlessly. Structure is **curiosity hook → factoid → personal → landing line**:
33 - **Curiosity hook (0-3s)**: One sentence bridging something unexpected to a relatable problem. Pattern: "[Unexpected subject] [accidentally/proved] why [relatable problem]." E.g., "A waitress accidentally explained why your brain won't shut up at night." This creates a curiosity gap before the story starts.
34 - **Factoid/story (3-15s)**: The actual study, told as compressed narrative. Concrete, visual, specific.
35 - **Bridge to viewer (15-25s)**: Make it personal. "That's why you lie awake at 3am."
36 - **Landing line (25-30s)**: Gut-punch reframe, NO CTA. Video ends on the punch so TikTok auto-loops seamlessly.
37
38 **Tone is Style B**: dry, restrained, trust the viewer to feel the weight. Don't over-explain the emotion. Say search keywords ("overthinking," "brain dump," "journaling," "mental clarity") out loud where natural. Content territory includes psych studies, cognitive biases, and brain quirks — not limited to overthinking/brain dump. See the reference script in the method doc for the exact target format.
395. **Generate caption & hashtags** — 3-5 niche hashtags only. Never use #fyp, #viral, #science, #brainhacks. Use: #overthinking, #[concept], #mentalclarity, #braindump, #journaling, #anxietyrelief.
406. **Create content folder** (`content/tiktok/YYYY-MM-DD_HHMM_slug/`) and save `brief.md`.
417. **Present the full brief** to the user and wait for approval before proceeding.
42
43### Phase 3: Asset Generation (automated)
44
45After script approval, run these scripts in sequence:
46
478. **Voiceover**: `pipenv run python3 scripts/tiktok/voiceover.py <content-folder>`
48 - Reads script from brief.md, calls ElevenLabs, speeds up 1.25x, saves to assets/
499. **Transcribe**: `pipenv run python3 scripts/tiktok/transcribe.py <content-folder>`
50 - Calls Deepgram Nova-3, saves transcript.json, prints sentence-level and word-level timestamps
5110. **Plan slides** — Use the transcript timestamps to plan **~10 slides at ~3s each** (for 30s video) or **~15 slides at ~3s each** (for 45s video). Every slide gets a unique illustration. No CTA slide at the end — final slide should be a simple closing image that loops cleanly back to slide 1. Add slide plan to brief.md.
5211. **Write illustrations JSON** — Save illustration specs to `assets/illustrations.json`:
53 ```json
54 [{"name": "slug-name", "prompt": "Scene description (style prefix added automatically)"}]
55 ```
5612. **Generate illustrations**: `pipenv run python3 scripts/tiktok/illustrations.py <illustrations-json> <output-dir>`
57 - Generates all illustrations with brand style references, portrait 1024x1536, transparent bg
58
59### Phase 4: Composition & Render (automated)
60
6113. **Prepare assets**: `pipenv run python3 scripts/tiktok/prepare_assets.py <content-folder>`
62 - Copies illustrations + voiceover to `videos/public/` for Remotion
6314. **Build Remotion composition** — Create `videos/src/{ConceptName}TikTok/` with config.ts, Slide.tsx, index.tsx. Register in Root.tsx under `<Folder name="TikTok">`.
6415. **Render**: `cd videos && npx remotion render CompositionId out/output-name.mp4`
6516. **Archive**: Copy mp4 back to content folder.
66
67### Phase 5: Deliver (automated)
68
6917. **Email**: Send the rendered video with caption and hashtags to both `abhinav@jabhi.ca` and `joieta@jabhi.ca` using the Google Workspace MCP. Send two separate emails (one per recipient). Format:
70 - **To**: `abhinav@jabhi.ca` and `joieta@jabhi.ca` (use `abhinav@jabhi.ca` as `user_google_email` for both sends)
71 - **Subject**: `{Concept Name} — TikTok Video`
72 - **Body**: Caption text followed by hashtags, all on one line. No heading, no formatting — plain text ready to copy-paste into TikTok.
73 - **Attachment**: The rendered mp4 file from the content folder (use `path` option)
74
75## Helper Scripts
76
77| Script | Purpose | Input | Output |
78|--------|---------|-------|--------|
79| `scripts/tiktok/voiceover.py` | ElevenLabs TTS + 1.25x speedup | Content folder (reads brief.md) | `assets/voiceover-raw.mp3`, `assets/voiceover.mp3` |
80| `scripts/tiktok/transcribe.py` | Deepgram Nova-3 word timestamps | Content folder (reads voiceover.mp3) | `assets/transcript.json` + printed table |
81| `scripts/tiktok/illustrations.py` | OpenAI gpt-image-1.5 with style refs | JSON config + output dir | Portrait PNGs in output dir |
82| `scripts/tiktok/prepare_assets.py` | Copy assets to Remotion public/ | Content folder | Files in `videos/public/` |
83
84## Folder Structure
85
86```
87content/tiktok/YYYY-MM-DD_HHMM_slug/
88├── brief.md # Script, caption, hashtags, slide plan
89├── assets/
90│ ├── illustrations/ # PNGs (portrait, transparent bg)
91│ ├── illustrations.json # Illustration specs for regeneration
92│ ├── voiceover-raw.mp3
93│ ├── voiceover.mp3
94│ └── transcript.json
95└── slug.mp4 # Final rendered video
96```
97
98## Critical Details (common mistakes)
99
100- **Image size**: Must be `1024x1536` (portrait), NOT `1024x1024` — square images get cropped in vertical frame
101- **Audio import**: Use `<Audio>` from `@remotion/media`, NOT from core remotion
102- **ElevenLabs stability**: Only 0.0, 0.5, or 1.0 — no in-between values. Only pass stability, no other voice_settings.
103- **Speed**: Apply via ffmpeg post-generation, not as an ElevenLabs parameter
104- **Overflow**: Set `overflow: "visible"` on slide container to prevent zoom clipping
105- **No text overlays**: TikTok captions + background music provide enough stimulation — don't add text to the video
106- **Run end-to-end**: Generate all assets AND render the final video — don't stop at code
107
108## Key Files
109
110- Writing style reference: `docs/writing-style-reference.md` (Paul Graham essay + style guide)
111- Method doc: `docs/tiktok-psych-video-method.md`
112- Brand reference images: `assets/illustrations/overwhelmed-filing-cabinet.png`, `floating-yellow-balloon.png`, `planting-yellow-seedling.png`
113- Example composition (new format, 30s): `videos/src/ParadoxOfChoiceTikTok/` (config.ts, Slide.tsx, index.tsx)
114- Example brief (new format): `content/tiktok/2026-02-18_1430_paradox-of-choice/brief.md`
115- Legacy composition (old format, 60s): `videos/src/ZeigarnikTikTok/`