agentleFS
Marky-TeamMarky-Team/marky-skills/skills/create-post-clips/SKILL.md

create-post-clips

Skill5 starsChanged 4 months agoApache-2.0View on GitHub

Turn an existing long-form video (a YouTube link, a local file, or one from your Marky library — webinar, podcast episode, talk, sermon) into 2-5 short vertical clips: find the strongest 30-60 second moments, cut them, crop to 9:16, add captions, upload to Marky, caption each in your brand voice, and schedule them across the week after your approval. Use when you already have the footage and want it repurposed. Also triggers on "turn my YouTube video into clips", "cut this webinar into shorts", "repurpose my podcast", "make reels from this video". To author a new video from scratch, see create-post-video; caption STYLE questions are about copy — the humanize skill covers copy, not subtitles.

  • Installs packages
  • Sends data out

The file

Show its rules and text

We split this skill into the rules it gives an agent

15 rules. About 0 are common, 4 are distinctive, and 11 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈4

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 11

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Workspace: put everything in ~/.marky/clips/<business_id>/<slug>/ — not the current working directory.

    line 39
  2. Very specific:

    Check the duration with ffprobe.

    line 60
  3. Distinctive:

    Read the timestamped transcript and pick the 2-5 strongest 30-60s segments.

    line 77
  4. Distinctive:

    Avoid: segments starting mid-sentence, meandering setup, references to earlier content ("as I mentioned..."), multiple unrelated ideas.

    line 87
  5. Distinctive:

    Verify each output is 1080x1920 before moving on:

    line 154
  6. Very specific:

    Path A — HyperFrames: If the hyperframes skill (and its embedded-captions workflow) is available in your session, use it — it produces the …

    line 173
  7. Very specific:

    Keep the returned URL. Uploads cap at 50 MB.

    line 221
  8. Very specific:

    Write the caption in the brand voice: Start from the clip's hook_sentence — it already earned its place — then rewrite per the workspace's …

    line 222
  9. Very specific:

    Create the post as a draft with metadata: {"media_type": "video", "format": "clip", "hook": "<pattern>", "topic": "...", "created_by": …

    line 227
  10. Very specific:

    After the scheduled times pass, check publish_results per post shows success.

    line 245
  11. Very specific:

    FFmpeg filter_complex error: don't use -c:v copy with -filter_complex.

    line 249
  12. Very specific:

    Wrong output resolution: always crop before scaling.

    line 251
  13. Distinctive:

    Caption sync issues: run Whisper on the cut clip, not the source episode.

    line 253
  14. Very specific:

    TikTok upload fails: ensure H.264 + AAC encoding.

    line 254
  15. Very specific:

    Marky wants your feedback: If anything breaks or is confusing while you run this skill — and again once the clips are scheduled — send …

    line 261

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Create Post: Clips

Most businesses already have hours of long-form video doing nothing — webinars, podcast episodes, talks. The short-form versions are the highest-reach posts they never make. This skill mines a long video for its best moments and ships them as scheduled posts.

Pipeline shape and hard-won ffmpeg/Whisper details adapted from ericosiu/ai-marketing-skills (MIT).

Read the marky-api skill first for auth, endpoints, and the brand cache. Base URL https://api.mymarky.ai/api, header Authorization: Bearer mk_live_YOUR_KEY.

Prerequisites

command -v yt-dlp ffmpeg whisper
  • yt-dlp and ffmpeg are required. If missing, ask the user before installing, then offer: brew install yt-dlp ffmpeg (macOS) or their package manager's equivalent.
  • whisper (OpenAI's CLI, pip install -U openai-whisper) gives word-level timestamps for tight caption sync. It is optional for YouTube sources — auto-captions work as a transcript fallback — but burned-in captions look best with it. Offer the install; if the user declines, continue with the fallback and say captions will be line-level.

Workspace: put everything in ~/.marky/clips/<business_id>/<slug>/ — not the current working directory. Video work is big and cwd may be inside someone's repo. Delete the source download when the run is done.

Stage 1 — Get the source video

  • YouTube link (also grabs auto-captions as the transcript fallback):

    yt-dlp \
      --write-auto-sub --sub-lang en --convert-subs vtt \
      -f "bestvideo[height<=1080]+bestaudio/best[height<=1080]" \
      --merge-output-format mp4 \
      -o "source/%(title)s.%(ext)s" \
      "https://www.youtube.com/watch?v=VIDEO_ID"
  • Local file: copy or symlink it into the workspace.
  • Marky library: search_media_library (or GET /businesses/BIZ_ID/media) to find it, then download the returned URL.

Check the duration with ffprobe. Under ~10 minutes there may only be 1-2 good clips; tell the user and lower the target instead of forcing five.

Stage 2 — Transcribe with timestamps

Preferred — Whisper on the source (word timestamps power everything downstream):

whisper source/video.mp4 --model small --language en \
  --word_timestamps True --output_format json --output_dir transcript/

Fallback — parse the downloaded .vtt auto-captions into [MM:SS] line entries. Dedupe repeated lines (YouTube VTTs overlap heavily).

Stage 3 — Find the best moments (you are the segmenter)

Read the timestamped transcript and pick the 2-5 strongest 30-60s segments. Criteria:

  • Hook in the first 3 seconds — the opening line must grab: surprising stat, bold claim, counterintuitive take, or a story that starts mid-action. Score each candidate's hook 1-10; only keep clips scoring 7 or higher. The clip must OPEN on the hook line — never on setup.
  • One complete idea — one framework, one stat, one story. Not a summary.
  • Emotional punch — surprise, humor, a strong opinion, or data that shocks.
  • Ends on a takeaway or cliffhanger.
  • Ideal 30-45s, hard max 60s. Skip anything under 30s.
  • Avoid: segments starting mid-sentence, meandering setup, references to earlier content ("as I mentioned..."), multiple unrelated ideas.

For each clip record: start_time, end_time, title, hook_sentence (exact first line), payoff_sentence, hook pattern (stat / contrarian / story / question / bold claim — see plan-social-content's hook palette), and a layout guess: talking_head (one presenter), screen_share (slides/screen with a webcam bubble), or side_by_side.

Stage 4 — Verify every cut (do not skip)

Second pass, one clip at a time: re-read the transcript ±10 seconds around each proposed end time and ask: does the thought actually complete there? A clip must end on a complete thought or reaction — never mid-sentence, never mid-idea. If it runs on, move end_time to where the thought resolves. This pass catches the single most common failure (a clip that cuts off the punchline) and is cheap. If a corrected clip now exceeds 90s, trim the end back to about 75s at the nearest sentence boundary instead.

Show the user the clip list (timestamps, titles, hooks) before cutting — a 10-second sanity check here beats re-rendering later.

Stage 5 — Cut and crop to 9:16

Cut each clip (re-encode; stream-copy lands on the wrong keyframe):

ffmpeg -y -ss START_SECONDS -i source/video.mp4 -t DURATION_SECONDS \
  -c:v libx264 -c:a aac -avoid_negative_ts make_zero clips/clip-1.mp4

Look before you crop. Extract a frame and view it to confirm the layout guess and where the speaker sits:

ffmpeg -y -ss 2 -i clips/clip-1.mp4 -frames:v 1 clips/clip-1-frame.png
  • Talking head — center crop to 9:16, then scale. Crop BEFORE scaling. If the speaker is off-center, shift the crop x-offset toward them (read the frame you extracted):

    ffmpeg -y -i clips/clip-1.mp4 \
      -vf "crop=ih*9/16:ih,scale=1080:1920" \
      -c:v libx264 -preset medium -crf 20 -c:a copy clips/clip-1-v.mp4
  • Screen share / side by side — do not center-crop (you lose the content). Stack: screen region on top, speaker region below. Take the two regions from the frame you extracted and adjust the crop coordinates to match:

    ffmpeg -y -i clips/clip-1.mp4 -filter_complex \
      "[0:v]crop=iw:ih*3/4:0:0,scale=1080:1150[top];\
       [0:v]crop=ih*3/4:ih*3/4:iw-ih*3/4:ih/4,scale=1080:770[face];\
       [top][face]vstack=inputs=2[v]" \
      -map "[v]" -map 0:a -c:v libx264 -crf 20 -c:a copy clips/clip-1-v.mp4
  • Anything unclear — safe fallback is letterbox: full frame scaled onto a 1080x1920 canvas with black bars:

    ffmpeg -y -i clips/clip-1.mp4 \
      -vf "scale=1080:-2,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:black" \
      -c:v libx264 -c:a copy clips/clip-1-v.mp4

Verify each output is 1080x1920 before moving on:

ffprobe -v error -show_entries stream=width,height -of csv=p=0 clips/clip-1-v.mp4

Stage 6 — Burn in captions

Silent-scroll viewers are most of the audience; clips without captions underperform. Re-run Whisper on each CUT clip — never reuse source-video timestamps, the offsets drift and captions desync:

whisper clips/clip-1-v.mp4 --model small --language en \
  --word_timestamps True --output_format srt --output_dir clips/

Two burn-in paths:

  • Path A — HyperFrames. If the hyperframes skill (and its embedded-captions workflow) is available in your session, use it — it produces the word-highlight style natively and handles brand fonts/colors. Hand it the cut vertical clip.
  • Path B — ffmpeg + ASS. First confirm the local ffmpeg was built with libass (some minimal builds are not):

    ffmpeg -hide_banner -filters 2>/dev/null | grep subtitles

    Then write an .ass file from the SRT (3-4 words per Dialogue line, timed from the word timestamps) with this style block, and burn:

    [Script Info]
    PlayResX: 1080
    PlayResY: 1920
    WrapStyle: 0
    
    [V4+ Styles]
    Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
    Style: Default,Arial Black,64,&H00FFFFFF,&H0000FFFF,&H00000000,&H80000000,-1,0,0,0,100,100,0,0,1,4,0,2,40,40,270,1
    
    [Events]
    Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
    Dialogue: 0,0:00:00.00,0:00:01.20,Default,,0,0,0,,THE HOOK WORDS
    ffmpeg -y -i clips/clip-1-v.mp4 -vf "subtitles=clips/clip-1.ass" \
      -c:v libx264 -crf 20 -c:a copy clips/clip-1-final.mp4

Colors: ASS uses &HAABBGGRR (blue-green-red, not RGB). Swap the highlight color for a brand accent from the brand cache if it stays readable on video.

Stage 7 — Upload and draft one post per clip

For each final clip:

  1. Upload:

    curl -X POST "https://api.mymarky.ai/api/businesses/BIZ_ID/media" \
      -H "Authorization: Bearer mk_live_YOUR_KEY" \
      -F "file=@clips/clip-1-final.mp4"

    Keep the returned URL. Uploads cap at 50 MB; if over, raise -crf to 23 and re-encode.

  2. Write the caption in the brand voice. Start from the clip's hook_sentence — it already earned its place — then rewrite per the workspace's strategy doc (voice, caption rules, the closing line; see "Write like the business" in the marky-api skill). Run every caption through the humanize skill's pattern check (score 90+, fix silently) before showing the user.
  3. Create the post as a draft with metadata: {"media_type": "video", "format": "clip", "hook": "<pattern>", "topic": "...", "created_by": "create-post-clips"} — per "Tag every post" in the marky-api skill.

Stage 8 — Approve, then schedule (hard gate)

  1. Present all clips on the review board in approve mode — exactly the plan-social-content Stage 6 flow: write items.json (one item per clip, media_url pointing at the local final file or uploaded URL, meta like "Clip 2 - 0:42 - stat hook"), run ${CLAUDE_PLUGIN_ROOT}/scripts/review-board.py items.json in the background, parse BOARD_URL:, AskUserQuestion with the URL, then read feedback.json. Apply edits verbatim; append the feedback to ~/.marky/feedback-log.jsonl with context: "clips".
  2. Nothing is scheduled until the user approves. Rejected clips are dropped; edited captions use the user's wording.
  3. Schedule approved clips via the schedule-posts skill, spaced across the week (for example Tue/Thu/Sat at the same hour) — never all on one day. Video is supported everywhere: target every connected platform whose integration status is valid.
  4. After the scheduled times pass, check publish_results per post shows success.

Troubleshooting

  • FFmpeg filter_complex error: don't use -c:v copy with -filter_complex. Only -c:a copy is safe.
  • Wrong output resolution: always crop before scaling. Verify with ffprobe -show_entries stream=width,height.
  • Caption sync issues: run Whisper on the cut clip, not the source episode.
  • TikTok upload fails: ensure H.264 + AAC encoding. Add -c:v libx264 -c:a aac.
  • Clip too long: segmentation sometimes overshoots. Auto-trim anything over 90s back to ~75s at a sentence boundary.
  • "Unknown filter 'subtitles'": that ffmpeg was built without libass. Use Path A (HyperFrames) for the caption burn, or install a full ffmpeg build.
  • No auto-captions on the YouTube video: Whisper becomes required; install it or stop.

Marky wants your feedback. If anything breaks or is confusing while you run this skill — and again once the clips are scheduled — send Marky a quick note with the submit_feedback MCP tool. See "Marky wants your feedback" in the marky-api skill.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.