| name | video-repurposer |
| description | Take a published YouTube video URL, extract clips per the social calendar's Clip Release Schedule, write platform-native captions with comment-to-DM CTAs, and publish to connected platforms (LinkedIn, Instagram, TikTok, Twitter/X, Facebook) via Zernio at the scheduled times. |
| allowed-tools | Read, Grep, Glob, Bash |
| area | Marketing |
| use_for | Repurpose a YouTube video into platform-specific clips with captions for all connected platforms. Run after the weekly YouTube video is uploaded. |
| deps | {"mcp":["Notion","Slack"],"gateway":["Zernio (publishing)","FiveAgents (logging)"],"files":["brand.md","audience.md"],"env":["`${BRAND}_LATE_LI`","`${BRAND}_LATE_IG`","`${BRAND}_LATE_TT`","`${BRAND}_LATE_TW`","`${BRAND}_LATE_FB`","`${BRAND}_NOTION_DB`"]} |
Maintenance
| Agent | Version | Last Changed |
|---|
| Link | v2.14.0 | May 29, 2026 |
Change Log
v2.14.0 — May 29, 2026
- New skill. Phase 4–5 of the YouTube-First content pipeline. Downloads the week's YouTube video via yt-dlp, reads the Clip Release Schedule from the Notion social calendar, extracts clips via ffmpeg, writes platform-native captions, and publishes to connected platforms via Zernio at the times specified in the schedule.
SKILL.md — Video Repurposer
Before Executing
Read agents/link.md and brands/{brand}/brand.md before starting. Load credentials from .claude/settings.local.json.
Role
Take the week's published YouTube video, extract clips per the Clip Release Schedule in the social calendar, write platform-native captions, and publish each clip to the correct platform at the scheduled time.
Step 0 — Load credentials + validate
import os, json
from pathlib import Path
def load_credentials():
search = Path(os.getcwd())
for p in [search] + list(search.parents):
settings_file = p / ".claude" / "settings.local.json"
if settings_file.exists():
data = json.loads(settings_file.read_text())
for k, v in data.get("env", {}).items():
if not os.environ.get(k):
os.environ[k] = v
return True
return False
load_credentials()
Get the YouTube video URL from the user or from this week's social calendar page in ${BRAND}_NOTION_DB.
Step 1 — Read the Clip Release Schedule from Notion
Fetch this week's social calendar page from ${BRAND}_NOTION_DB (search for SocialCalendar_[DDMon]-[DDMonYYYY]). Read the Clip Release Schedule table:
- Clip #, Platform, Publish Day, Publish Time, Duration, Moment to Clip, Caption Angle, Hook Archetype, CTA
Only process clips for platforms where the matching env var is set (${BRAND}_LATE_LI, ${BRAND}_LATE_IG, ${BRAND}_LATE_TT, ${BRAND}_LATE_TW, ${BRAND}_LATE_FB). Skip platforms with missing env vars and log the gap.
Step 2 — Download video
python3 -m pip install yt-dlp --break-system-packages -q
python3 -m yt_dlp -o "tmp/{brand}/source_video.%(ext)s" "{youtube_url}"
Step 3 — Extract clips
For each clip in the schedule:
pip install ffmpeg-python --break-system-packages -q
ffmpeg -i tmp/{brand}/source_video.mp4 -ss {start_time} -to {end_time} -c copy tmp/{brand}/clip_{n}_{platform}.mp4
If exact timestamps are not in the schedule, use the Moment to Clip description to identify the segment. Use Whisper transcription if needed:
python3 -m pip install openai-whisper --break-system-packages -q
python3 -m whisper tmp/{brand}/source_video.mp4 --output_dir tmp/{brand}/ --output_format srt
Match the described moment against the transcript to find the timestamp.
Step 4 — Write captions
For each clip, the caption is already written in the Notion calendar Captions section. Read it verbatim. If absent, write a new caption using:
- Voice and tone from
brand.md
- Caption angle and hook archetype from the Clip Release Schedule
- Comment-to-DM CTA from the schedule
- Platform-native format (length, hashtag count per platform guidelines)
Step 5 — Publish via Zernio
For each clip:
late_presign_upload → get presigned S3 URL
- Upload clip via
requests.put to the presigned URL
late_create_post with video asset + caption + platform account ID + scheduled time
platform_ids = {
"LinkedIn": os.environ.get(f"{brand_upper}_LATE_LI"),
"Instagram": os.environ.get(f"{brand_upper}_LATE_IG"),
"TikTok": os.environ.get(f"{brand_upper}_LATE_TT"),
"Twitter/X": os.environ.get(f"{brand_upper}_LATE_TW"),
"Facebook": os.environ.get(f"{brand_upper}_LATE_FB"),
}
Schedule each clip at the Publish Time from the Clip Release Schedule (convert to UTC for the API). If scheduling is not supported, publish immediately and note the actual publish time.
Step 6 — Update Notion + PublishLog
- Update each clip row in the Notion calendar page:
Status = Published, add post URL
- Append to
outputs/{brand}/published/PublishLog_[DDMonYYYY].md — use the exact same columns as social-publisher so content-performance-analyst can join on Late ID:
| Date | Platform | Topic | Late ID | Post URL | Status | Published At |
|---|---|---|---|---|---|---|
| {date} | {platform} | {clip moment} | {late_id} | {url} | Published | {publish_time} |
Step 7 — Slack notification
Load slack_send_message via ToolSearch before calling. DM $SLACK_NOTIFY_USER:
🎬 [{brand}] Video repurposed — {YouTube title}
• {N} clips published/scheduled
• {one line per connected platform: Platform: {publish_time}}
• Notion calendar updated
Step 8 — Log to dashboard
fiveagents_log_run:
- skill: "video-repurposer"
- brand: {brand}
- status: success | partial | failed
- summary: "{N} clips published to {platforms} from: {YouTube title}"
- metrics: {
"youtube_url": "{url}",
"clips_published": N,
"platforms": ["LinkedIn", "Instagram", ...],
"publish_times": { "LinkedIn": "...", ... },
"skipped_platforms": [] // any planned platform whose _LATE_ env var is unset
}
Quality Checklist
Part of the pipeline
Phase 4–5 of the YouTube-First content loop. Runs after the YouTube video is uploaded.
social-calendar (Clip Release Schedule) → video-repurposer (download → extract → publish) → PublishLog (feeds content-performance-analyst Phase 1)