SuperAPI AI Directory

video-hosting-draft

Design & creation

View repository

Updated 10-15 19:58

About this skill

video-hosting-draft

Code drafts. A human decides. Code publishes. This skill owns the draft step. It never publishes anywhere — the publish step is a separate skill (/video-hosting-publish) that runs only after a human has approved a row.

What this skill does (one paragraph)

For every raw clip in the input folder that is not already represented in the editorial Google Sheet, this skill produces exactly three title variants, three description variants, and three different PNG thumbnails (one thumbnail per title) and appends a single row for that clip to the editorial sheet. It does not call the video hosting API. It does not mark anything as approved. Its only job is to give the editor three principled options to choose from, in the place where the editor already works.

Inputs

  • videos/ — folder of raw .mp4 clips from the production team. Each file is named arbitrarily (e.g. clip_2026-05-03_v3.mp4) — filenames are not trusted for content/category signal.
  • transcripts/ — optional .txt next to each .mp4. If absent, the skill runs Whisper locally to produce one before any LLM call.
  • thumbnails/case/template.png and thumbnails/educational/template.png — design-provided template files. The skill renders text on top of the matching template; it never publishes a bare template.
  • Editorial Google Sheet (id in config.yaml). The sheet is the single source of truth for what has been drafted, what is approved, and what has been published.

Output: one row per video in the editorial Google Sheet

Sheet columns (in this exact order — /video-hosting-publish reads the same columns):

Column Type Written by Notes
video_id string (sha256[:12]) draft Stable id derived from the file content hash. Used for dedup.
source_path string draft Path to the source .mp4.
category enum: case / educational draft Detected from transcript content (see below).
title_1 string draft First title variant.
title_2 string draft Second title variant.
title_3 string draft Third title variant.
description_1 string draft First description variant.
description_2 string draft Second description variant.
description_3 string draft Third description variant.
thumbnail_1_url string (Drive link) draft PNG rendered with title_1 on top of the category template.
thumbnail_2_url string (Drive link) draft PNG rendered with title_2.
thumbnail_3_url string (Drive link) draft PNG rendered with title_3.
final_title string editor The title to actually publish. Editor pastes/edits here. May be a copy of title_N or freely edited.
final_description string editor The description to publish.
final_thumbnail_url string (Drive link) editor The thumbnail PNG to publish.
approved checkbox (boolean) editor The approval mechanism. Publish reads only rows where approved = TRUE.
published_clip_id string /video-hosting-publish Marker written after a successful publish. Empty until then.
published_at ISO timestamp /video-hosting-publish Marker written after a successful publish.

The approval element is a Google Sheets checkbox in column approved (data validation: checkbox, default unchecked). It is the only signal of human consent. A row with approved = FALSE is invisible to the publish step, no matter how complete it looks.

Three principled variants — what "principled" means

Three random rephrasings of the same headline are useless to the editor: she'd still have to write the title herself. The three variants must differ along an explicit axis so each one gives the editor a real choice. The skill picks three different angles per clip and asks the LLM to write one variant for each angle:

For case videos (customer story / before-and-after):

  1. Outcome-first — leads with the measurable result. ("We cut onboarding from 14 days to 3.")
  2. Protagonist-first — leads with who did it and at what company. ("How Acme's ops team killed their busywork.")
  3. Tension-first — leads with the problem that triggered the change. ("87 clips in the queue and no one to package them — until…")

For educational videos (explainer / how-to):

  1. Question-as-title — frames the lesson as the question it answers. ("What is human in the loop, actually?")
  2. Tactic-first — names the concrete technique. ("Three variants beat one prompt, every time.")
  3. Anti-pattern-first — leads with the mistake the lesson cures. ("Stop letting your script auto-publish.")

The same axes drive the description variants (matched 1↔1↔1 with the titles so each row in the sheet — title_N + description_N + thumbnail_N — is internally coherent). The thumbnails are three different PNGs, one per title (see Rendering below). The skill records the chosen axis for each variant in the prompt log so the editor can see why each option exists.

Category detection from content (not filename)

The skill never reads category from the file name. The flow is:

  1. Get the transcript (either the supplied .txt, or run Whisper on the audio track).
  2. Send the first ~600 tokens of the transcript to the LLM with a two-label classifier prompt: case vs educational, with a one-sentence definition of each.
  3. Use the returned label to pick thumbnails/{category}/template.png for rendering.
  4. Persist the label to the category column. The editor can override by editing the cell — the publish step does not re-read category from the transcript.

This is deliberate: the same clip should land on the same template regardless of how the file is named, and regardless of what folder it sat in.

Thumbnail rendering (code, not just the template)

For each variant, the skill renders a fresh PNG using Pillow (PIL):

  1. Image.open("thumbnails/<category>/template.png").copy() — load the design template.
  2. ImageDraw.Draw with the design-system font (assets/fonts/Inter-Bold.ttf), font size from the design spec, color from the spec.
  3. Use textbbox to measure the title and shrink the font size until the title fits the design's safe area; wrap onto two lines if needed.
  4. Draw the title in the spec's text box. Do not touch the template's graphics.
  5. img.save(out_path, "PNG", optimize=True).
  6. Upload out_path to the Drive thumbnails folder and put the share link in thumbnail_N_url.

The skill never uploads a bare template — every cell in thumbnail_N_url points to a PNG that has the corresponding title drawn on it. The three PNGs for one video differ because the three titles differ.

Dedup on re-run (idempotency)

The skill must be safe to re-run after new clips drop into videos/. The dedup mechanism is:

  1. Compute video_id = sha256(<file bytes>)[:12] for each .mp4 in the input folder.
  2. Read the existing sheet (one API call). Build the set of video_ids already present in the video_id column.
  3. For each input clip whose video_id is not in that set, run the full pipeline and append one row.
  4. For each clip whose video_id is already in that set, skip it entirely. The skill does not regenerate variants, does not overwrite a row, does not touch what the editor has typed.

Why content-hash rather than filename: the production team renames clips constantly. Hash is stable across rename. Why a column rather than a separate state file: the sheet is the single source of truth — if the row exists, the row exists; no out-of-band state can lie about it.

Failure modes the skill handles explicitly

  • No transcript and Whisper fails — log the file, skip the row, exit non-zero so it shows up in scheduling.
  • LLM returns 2 variants instead of 3 — retry once; if still wrong, write [draft-incomplete] placeholder so the editor sees the row is broken rather than silently dropping the clip.
  • Drive upload fails for a thumbnail — leave that thumbnail_N_url empty; the editor sees a missing thumb and knows to nudge.
  • Sheet write conflict — exponential backoff up to 30s.

What this skill never does

  • Never publishes to the video hosting (that is /video-hosting-publish).
  • Never writes to final_title, final_description, final_thumbnail_url, approved, published_clip_id, published_at — those are editor or publish-skill territory.
  • Never reads approved.
  • Never re-runs on a video_id that already has a row.