-
Notifications
You must be signed in to change notification settings - Fork 1
Record hero GIF demo with OBS #7
Copy link
Copy link
Open
Labels
enhancementNew feature or requestNew feature or requestpriority:mediumNormal priorityNormal priority
Description
Summary
Record a compelling hero GIF for the README that shows off Thoth's voice-to-text workflow. The current hero GIF doesn't show the recording indicator (macOS screen recording skips alwaysOnTop transparent windows). OBS captures all window layers and will show the floating mic icon.
Research
- Ideal length: 10–15 seconds for a hero GIF
- Target file size: Under 5 MB (GitHub renders large GIFs as static first-frame)
- Best practice: One focused hero GIF at the top showing the "aha moment", optionally supplemented by feature-specific GIFs further down
Recording Script
Hero GIF — "Press a key. Speak. Text appears."
Setup before recording
- Open Sublime Text (or any editor) with a file called
Meeting notes — Thursday 25 March - Pre-type lines 1–5:
Meeting notes — Thursday 25 March Attendees: Sarah, Steven Action items: - Cursor on line 7, empty
- Thoth running, hotkey set to F13
- OBS source: Use macOS Screen Capture (not Window Capture) — this captures all window layers including
alwaysOnTopoverlays like the recording indicator. Crop to the editor window in post. - OBS output: native window resolution, 30 fps, Apple VT H264 Hardware Encoder, CRF 18–22, MP4 format
The take (aim for ~15 seconds total)
| Time | Action | What viewer sees |
|---|---|---|
| 0–2s | Pause. Let the viewer read the existing notes. | Static editor with meeting notes |
| 2–3s | Press F13. | Recording indicator (floating mic icon) appears near cursor |
| 3–12s | Speak clearly: "Review the onboarding flow and simplify the permission steps before the next release." | Mic icon visible near cursor |
| 12–13s | Release F13 (or let VAD stop). | Indicator disappears |
| 13–15s | Text appears on line 7. Pause to let viewer read. | Transcribed sentence visible |
Key points
- The recording indicator floating near the cursor is the visual proof this is system-wide
- Keep the window clean — no other apps visible
- Speak at a natural pace, not rushed
- Do multiple takes — pick the cleanest one
Optional: Feature GIF — "Speak like a pirate"
For the Features section of the README. Shows AI enhancement.
Setup
- Open Thoth settings, navigate to Enhancement section
- Have the "Speak like a pirate" prompt visible
- Switch to a text editor
The take
- Dictate something normal like "Please send the report to the team by Friday"
- Text appears as pirate speech (e.g. "Ahoy! Be sendin' that report to the crew by Friday, ye scallywag!")
This is fun and immediately shows the AI enhancement value.
Post-production: Converting to GIF
Step 1: Trim and crop
Watch the OBS recording and note:
TRIM_START: seconds to skip from the beginningTRIM_END: seconds to trim from the end- Crop coordinates if needed (use
ffprobeorffmpeg cropdetect)
Step 2: Generate text overlays (only if the recording indicator STILL doesn't appear)
If OBS captures the mic icon, skip this step — no overlays needed.
If the icon is still missing, generate plain-text caption PNGs with Pillow:
/Users/paul/miniconda3/envs/automator/bin/python3 << 'PYEOF'
from PIL import Image, ImageDraw, ImageFont
font_path = "/System/Library/Fonts/SFCompact.ttf"
font = ImageFont.truetype(font_path, 48)
labels = {
"hotkey_pressed": "Hotkey pressed",
"recording": "Recording…",
"transcribed": "Transcribed ✓",
}
for name, text in labels.items():
tmp = Image.new("RGBA", (1, 1), (0, 0, 0, 0))
d = ImageDraw.Draw(tmp)
bbox = d.textbbox((0, 0), text, font=font)
tw, th = bbox[2] - bbox[0], bbox[3] - bbox[1]
pad = 6
w, h = tw + pad * 2 + 4, th + pad * 2 + 4
img = Image.new("RGBA", (w, h), (0, 0, 0, 0))
d = ImageDraw.Draw(img)
d.text((pad + 2 - bbox[0], pad + 2 - bbox[1]), text, fill=(0, 0, 0, 180), font=font)
d.text((pad - bbox[0], pad - bbox[1]), text, fill=(220, 220, 220, 255), font=font)
img.save(f"/tmp/{name}.png")
print(f"/tmp/{name}.png: {img.size}")
PYEOFStep 3: Convert to GIF
Use the existing script (or manually):
# Without overlays:
FPS=10 TRIM_START=<N> TRIM_END=<N> WIDTH=800 \
./scripts/mov-to-hero-gif.sh recording.mp4 docs/screenshots/hero.gif
# With overlays (two-pass ffmpeg):
INPUT="recording.mp4"
OUTPUT="docs/screenshots/hero.gif"
PALETTE=$(mktemp /tmp/palette-XXXXXX.png)
# Pass 1: palette
ffmpeg -y -ss <START> -to <END> -i "$INPUT" \
-i /tmp/hotkey_pressed.png -i /tmp/recording.png -i /tmp/transcribed.png \
-filter_complex "
[0:v]crop=W:H:X:Y,fps=10[base];
[base][1:v]overlay=x=(W-w)/2:y=H-h-30:enable='between(t,<T1_START>,<T1_END>)'[v1];
[v1][2:v]overlay=x=(W-w)/2:y=H-h-30:enable='between(t,<T2_START>,<T2_END>)'[v2];
[v2][3:v]overlay=x=(W-w)/2:y=H-h-30:enable='between(t,<T3_START>,<T3_END>)'[v3];
[v3]scale=800:-1:flags=lanczos,palettegen=stats_mode=diff[pal]
" -map "[pal]" "$PALETTE"
# Pass 2: render
ffmpeg -y -ss <START> -to <END> -i "$INPUT" \
-i /tmp/hotkey_pressed.png -i /tmp/recording.png -i /tmp/transcribed.png \
-i "$PALETTE" \
-filter_complex "
[0:v]crop=W:H:X:Y,fps=10[base];
[base][1:v]overlay=x=(W-w)/2:y=H-h-30:enable='between(t,<T1_START>,<T1_END>)'[v1];
[v1][2:v]overlay=x=(W-w)/2:y=H-h-30:enable='between(t,<T2_START>,<T2_END>)'[v2];
[v2][3:v]overlay=x=(W-w)/2:y=H-h-30:enable='between(t,<T3_START>,<T3_END>)'[v3];
[v3]scale=800:-1:flags=lanczos[scaled];
[scaled][4:v]paletteuse=dither=bayer:bayer_scale=5[out]
" -map "[out]" "$OUTPUT"Replace <START>, <END>, crop=W:H:X:Y, and overlay timing placeholders with actual values from the recording.
Step 4: Verify
- Check file size: target under 5 MB (ideally under 500 KB)
- Check frame count and duration
- Extract key frames to verify overlays and crop look correct
- Update README.md reference if filename changes
Acceptance criteria
- Hero GIF recorded with OBS showing the floating recording indicator
- GIF converted and optimised (under 5 MB, 800px wide, 10 fps)
- README.md updated with the new GIF
- Optional: pirate mode feature GIF for Features section
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or requestpriority:mediumNormal priorityNormal priority