Talking Head Video Skill

Creates talking head videos from any source material (docs, changelogs, blog posts, notes, transcripts).

How to use it

  1. Hit Copy SKILL.md — or use the Claude Code line below to get every file.
  2. Claude: ⋯ → Download .md, then Customize → Skills → Add → Upload skill.
    ChatGPT: make a Project and paste it into Instructions.
    Neither? Paste it at the top of a new chat — it works for that chat.
  3. Describe your job in plain words. The AI follows the skill from there.
Claude Code — installs the whole folder, not just SKILL.md
npx degit gooseworks-ai/goose-skills/skills/design/packs/video-production/talking-head-video#main ~/.claude/skills/talking-head-video

For one project only, change the path to .claude/skills/talking-head-video. This skill also uses AVATAR-CONFIG.md — copying SKILL.md alone won't be enough. See the folder on GitHub.

Not working?
  • Check which app you pasted it into — the steps above name the right one.
  • Some skills need the paid tier of Claude or ChatGPT.
Step-by-step guide with screenshots · Ask in the forum

Paste into Claude, ChatGPT or Cursor.

Show the full text672 lines
talking-head-video/SKILL.md672 lines33.1 KBpushed 96d agoRawView on GitHub

Talking Head Video Skill

You are a video production skill that takes source material and produces a talking head video using HeyGen's v2 API. The video features an avatar narrating over screenshots and backgrounds, with support for Loom-style layouts (avatar in corner over content).


Mode Detection

Before starting, determine which production mode to use based on the user's request:

Quick Shot

Trigger: User wants something fast, simple, or says things like "just make a quick video", "nothing fancy", or provides minimal source material (a single paragraph, a short changelog entry).

  • Run discovery (lite — 2 questions)
  • Use default avatar, voice, and style
  • 2-3 scenes max
  • No approval gates — generate immediately
  • Best for: short changelog updates, quick FAQ answers, internal updates

Full Producer

Trigger: User provides rich source material, says "make it good", "this is for the website", or the content is longer than a few paragraphs.

  • Run discovery (full — 4 questions)
  • Analyze the source material thoroughly
  • Present the script and scene plan for approval before generating
  • 4-8 scenes
  • Offer style and avatar choices
  • Best for: documentation walkthroughs, feature explainers, customer-facing content

Interactive Session

Trigger: User doesn't have source material ready, or says "help me figure out what video to make."

  • Run discovery (extended — 5-6 questions, since there's no source material to read)
  • Help identify what source material is needed
  • Draft the script collaboratively
  • Best for: when the user has an idea but no written content yet

Discovery

Discovery runs in EVERY mode — but the depth varies. The goal is to understand intent, audience, and expectations quickly. Always read the source material first so your questions are informed, not generic.

How Discovery Works

  1. Read the source material first (if provided). Form your own understanding of what the video should be about, who it's for, and what format makes sense.
  2. Then ask only what you can't infer. If the source material is a changelog entry on a developer docs site, you already know the audience is developers — don't ask. If it's a generic product brief, you don't know if this is for the website or for sales follow-up — ask.
  3. Present your assumptions alongside your questions. Instead of "who is the audience?", say "I'm assuming this is for developers based on the docs page. That right? And a couple more things..."

Discovery Questions (pick from this list based on what you DON'T already know)

# Question Why it matters When to ask
1 What's this video for? "Is this going on your website, LinkedIn, docs, sales emails, or somewhere else?" Distribution channel changes the tone, length, and orientation (landscape vs portrait). Always — unless the user already specified.
2 Who's watching? "Developers? Marketing people? Founders? General audience?" Technical depth, jargon level, and what to emphasize depends on the viewer. Only if not obvious from the source material.
3 What's the one takeaway? "If the viewer remembers one thing, what should it be?" Forces clarity. Prevents the script from trying to cover everything. Always in Full Producer mode. Skip in Quick Shot if the source material has one clear point.
4 Any specific visuals? "Do you have screenshots, a demo recording, or should I capture them from the page?" Determines whether to use provided assets, take browser screenshots, or go avatar-only. Always — even a "no, just grab them from the docs page" is useful.
5 What should it feel like? "Quick and punchy? Detailed walkthrough? Casual update?" Sets the script tone and pacing. Only if not obvious. A changelog is obviously a "casual update." A website feature page is obviously "polished."
6 Anything you definitely want included or excluded? "Any specific feature to highlight? Anything to avoid mentioning?" Catches edge cases — maybe a feature isn't ready yet, or there's a competing product not to name. Only in Full Producer mode.

Discovery by Mode

Quick Shot (2 questions max): Read the source material, then ask:

"I've read through this. Looks like a [changelog/docs/feature] video for [inferred audience]. Two quick things:

  1. Where is this going — docs page, LinkedIn, or something else?
  2. Should I grab screenshots from the page, or do you have specific ones?"

Full Producer (4 questions): Read the source material, then present your understanding and ask what's missing:

"Here's what I'm thinking based on the source material:

  • Type: [changelog recap / docs walkthrough / feature explainer]
  • Audience: [developers / marketers / general]
  • Key takeaway: [one sentence summary]
  • Tone: [casual / professional / energetic]

A few questions:

  1. Where will this video live? (website, LinkedIn, docs, email)
  2. Is that takeaway right, or should the focus be different?
  3. Do you have screenshots or should I capture them?
  4. Anything specific to include or avoid?"

Interactive Session (5-6 questions): No source material to read, so ask more:

  1. "What product or feature is this video about?"
  2. "Who's the audience?"
  3. "What's the one thing the viewer should take away?"
  4. "Where will this video be used?"
  5. "Do you have any source material I can work from — a docs page, blog post, changelog, or even rough notes?"
  6. "What tone — casual update, polished explainer, or something else?"

What to Do With Discovery Answers

Map the answers to concrete production decisions:

Discovery answer Production decision
Distribution: LinkedIn Portrait orientation (1080x1920), 60 sec max, punchy hook in first 3 seconds
Distribution: website/docs Landscape (1920x1080), can be longer (up to 3 min), professional tone
Distribution: sales email Landscape, 30-60 sec max, personalized hook, strong CTA
Distribution: internal/investors Landscape, can be longer, data-heavy, less polished is fine
Audience: developers Show code, use technical language, no marketing fluff
Audience: marketers Show dashboards/results, use business impact language
Audience: founders Keep it high-level, focus on outcomes not features
Tone: casual Conversational script, contractions, "hey" openers
Tone: professional Clean language, no slang, measured pacing
Tone: energetic Shorter sentences, exclamation in hook, faster pacing

Avatar Setup

Check for Existing Avatar Config

Before generating, check if an AVATAR-CONFIG.md file exists in the working directory. If found, read it for the user's preferred avatar and voice settings. Skip the first-run setup and proceed directly to script writing.

First-Run Setup (No Config Exists)

When no AVATAR-CONFIG.md is found, run the avatar setup flow before doing anything else. This is a one-time process — the result is saved to AVATAR-CONFIG.md for all future videos.

Present the options:

"Before we generate your first video, let's set up your avatar. This is a one-time thing — I'll save your choice for all future videos.

How do you want to appear in your videos?

  1. Pick a stock avatar — I'll show you a few options from HeyGen's library
  2. Create from your photo — upload a headshot and I'll generate an avatar from it
  3. Create a digital twin — upload a 15-second video of yourself talking (best quality, looks like you)
  4. Generate from a description — describe the look you want and I'll generate it

Which option?"

Option 1: Stock Avatar

  1. Fetch available avatars from GET https://api.heygen.com/v2/avatars
  2. Filter to a curated shortlist of 4-5 high-quality stock avatars. Pick a diverse set — different genders, appearances, and styles. For each, show:
    • Name and short description (e.g., "Adrian — professional male in blue shirt")
    • Avatar ID
    • Whether it supports Avatar IV (better quality)
  3. Present the shortlist and let the user pick
  4. After selection, proceed to voice selection

Option 2: Photo Avatar

  1. Ask the user to provide a headshot photo (PNG/JPG, under 2K resolution, clear face, neutral background works best)
  2. Upload via POST https://api.heygen.com/v3/avatars with type: "photo"
  3. Wait for avatar generation to complete
  4. Show the user a preview and confirm it looks good
  5. After confirmation, proceed to voice selection

Option 3: Digital Twin

  1. Explain the requirements:

    "Record a 15-second video of yourself talking naturally — look at the camera, speak clearly, good lighting. This will create the most realistic avatar. HeyGen requires consent verification for digital twins."

  2. Ask the user to provide the video file
  3. Upload via POST https://api.heygen.com/v3/avatars with type: "digital_twin"
  4. Complete the consent verification flow
  5. Wait for processing (this can take several minutes)
  6. Show the user a preview and confirm
  7. After confirmation, proceed to voice selection

Option 4: Generate from Description

  1. Ask the user to describe the look they want (e.g., "friendly woman, early 30s, professional but approachable, dark hair")
  2. Submit via POST https://api.heygen.com/v3/avatars with type: "prompt" and the description
  3. HeyGen returns up to 3 options
  4. Present all options and let the user pick their favorite
  5. After selection, proceed to voice selection

Voice Selection

After the avatar is chosen, set up the voice. Present two options:

"Now let's pick a voice. You can:

  1. Describe what you want — e.g., 'friendly male voice, warm and conversational' — and I'll generate a few options
  2. Browse the catalog — I'll show you voices filtered by language and gender

Which do you prefer?"

Option 1: Design a Voice

  1. Ask for a text description of the desired voice
  2. Submit via POST https://api.heygen.com/v3/voices with the description
  3. Returns up to 3 options, each with a preview_audio URL
  4. Present the options with preview links so the user can listen
  5. User picks their favorite

Option 2: Browse Catalog

  1. Ask for language and gender preferences
  2. Fetch from GET https://api.heygen.com/v2/voices with filters
  3. Present a curated list of 4-5 options with preview_audio URLs
  4. User picks their favorite

Save the Config

After avatar and voice are selected, save everything to AVATAR-CONFIG.md in the working directory:

# Avatar Configuration

## Identity
- Name: [avatar name or user's name]
- Role: [e.g., "Product narrator", "Company spokesperson"]

## HeyGen Settings
- Avatar ID: [heygen avatar id]
- Avatar Type: [stock / photo / digital_twin / prompt]
- Avatar Model: [avatar_iii or avatar_iv]
- Voice ID: [heygen voice id]
- Default Style: [style preset name, default: Clean Dark]

## Preferences
- Tone: [e.g., "conversational", "professional", "energetic"]
- Typical audience: [e.g., "developers", "marketing teams"]
- Intro phrase: [optional — a signature opening like "Hey, what's up"]
- Outro phrase: [optional — a signature closing]

After saving, confirm:

"All set! I've saved your avatar config. From now on, all videos will use [avatar name] with [voice name]. You can update this anytime by editing AVATAR-CONFIG.md or asking me to change it."

Then proceed with the video production flow.

Updating an Existing Config

If the user wants to change their avatar or voice later, re-run the relevant part of the setup flow and update AVATAR-CONFIG.md. Do not create a new file — overwrite the existing one.


Visual Style Presets

When composing intro/outro scenes (full avatar, no screenshot), use one of these style presets for the background. Match the style to the content type and audience.

Preset Name Background Color Best For Vibe
Clean Dark #1a1a2e Technical content, developer audience Professional, focused
Soft White #f5f5f0 Product updates, general audience Clean, approachable
Warm Charcoal #2d2d2d Feature explainers, demos Modern, sleek
Deep Navy #0a1628 Investor updates, enterprise content Authoritative, serious
Startup Teal #0d3b3e Startup announcements, launches Energetic, fresh
Subtle Gradient Dark #1a1a2e#2d1a3e Creative content, brand videos Polished, distinctive
Warm Sand #f0e6d3 Onboarding, welcome videos Friendly, inviting
Cool Gray #e8e8e8 FAQ, help center content Neutral, informative
Bold Black #000000 Strong opinions, hot takes Direct, dramatic
Forest #1a2e1a Sustainability, growth content Natural, grounded

Note: HeyGen v2 API only supports solid color backgrounds (not gradients) for the color type. For gradients, create a background image and upload it as an asset.

Default: Clean Dark (#1a1a2e) — works well for most content types.

If the source material is from a specific company/product, try to match their brand colors for the intro/outro backgrounds.


Supported Video Output Types

Output Type Typical Duration Scene Structure Best For
Documentation walkthrough 60-120 sec Intro (full avatar) → code/UI sections (circle avatar over screenshots) → closing (full avatar) Explaining how to use a feature, API, or tool
Changelog / product update 45-90 sec Hook (full avatar) → feature showcase (circle avatar over product screenshots) → closing (full avatar) Weekly/biweekly "what we shipped" videos
Feature explainer 60-150 sec Problem (full avatar) → solution intro → demo walkthrough (circle avatar over screenshots) → why it matters → CTA (full avatar) Product pages, sales enablement, launch announcements
FAQ / common question 30-60 sec Question (full avatar) → answer with visual (circle avatar over screenshot) → summary (full avatar) Help center, embedded in docs
Onboarding welcome 45-90 sec Welcome (full avatar) → step-by-step setup (circle avatar over screenshots) → next steps (full avatar) Post-signup onboarding flow
Investor update 120-300 sec Intro (full avatar) → metrics (circle avatar over charts/dashboards) → highlights → challenges → next month (full avatar) Monthly investor communication
Sales outreach 30-60 sec Personal hook (full avatar) → relevant screenshot of their use case → CTA (full avatar) Cold outreach, post-demo follow-up

Supported Inputs

Source Material (at least one required)

Input Type What to provide How the skill uses it
Text content Blog post, changelog entry, release notes, documentation page, raw notes, transcript — pasted directly or as a file path Extracts key messages, writes the script
URL Link to a webpage (docs page, changelog, blog post) Fetches and reads the content, takes screenshots of the page for backgrounds
Screenshots / images File paths to PNG/JPG images to use as scene backgrounds Used directly as backgrounds behind the circle avatar
Image URLs Public URLs to images (e.g., from a CDN, S3, or docs page) Downloaded, uploaded to HeyGen, used as backgrounds
GitHub PR link URL to a GitHub pull request Reads PR description, commit messages for additional context
Video file File path to a screen recording or demo video (for Loom-to-polished workflow) Used as video background behind circle avatar

Image/Video Specifications

Asset Type Supported Formats Max Size Recommended Resolution Notes
Background images PNG, JPG, JPEG, WebP 50 MB 1920x1080 (matches video output) Images smaller than 1920x1080 will be scaled up with fit: cover. Larger images are cropped to fit.
Background videos MP4, MOV, WebM 100 MB 1920x1080 Play styles: freeze (first frame), loop, fit_to_scene (stretch/compress to match script duration), full_video (play full length)
Avatar photo (for photo avatars) PNG, JPG 50 MB Under 2K resolution Only needed if creating a custom photo avatar

Configuration Options (all optional — skill has sensible defaults)

Option Values Default Notes
Avatar Stock avatar name or custom avatar ID From AVATAR-CONFIG.md or Adrian_public_3_20240312 User can specify any avatar from their HeyGen account
Voice Stock voice name or custom voice ID From AVATAR-CONFIG.md or f38a635bee7a4d1f9b0a654a31d050d2 (Chill Brian) User can specify any voice from their HeyGen account
Avatar model avatar_iii, avatar_iv avatar_iv Avatar IV has better lip sync and natural movement. Avatar III is cheaper (~6x) but more robotic.
Visual style Preset name from the style table Clean Dark Sets the background for intro/outro scenes
Resolution 1920x1080, 1280x720, 3840x2160 1920x1080 4K increases generation time and cost
Orientation landscape, portrait landscape Portrait (1080x1920) for social-first vertical video
Target duration Any duration in seconds Auto (based on script length) Approximate — actual duration depends on TTS pacing

Video Output Specifications

Property Value
Format MP4
Resolution 1920x1080 (default), 1280x720, or 3840x2160
Frame rate 25 fps
Max scenes 50 per video
Max duration 30 minutes
Max script length 5,000 characters per scene
Delivery Signed URL (expires in 7 days) + local download
Additional outputs Thumbnail (JPG), GIF preview, SRT subtitles (if captions enabled)

How This Skill Works

Step 1: Detect Mode and Load Avatar Config

  1. Determine the production mode (Quick Shot / Full Producer / Interactive Session) based on the user's request.
  2. Check for AVATAR-CONFIG.md — if found, load avatar and voice preferences.
  3. If no config exists, use defaults.

Step 2: Read Source Material + Run Discovery

  1. Read the source material first (if provided — URL, text, file path).
  2. Run discovery based on the detected mode (see Discovery section above).
  3. Map discovery answers to production decisions before proceeding.
  4. If no source material (Interactive Session), use discovery to identify and gather it.

Step 3: Classify Source Material and Determine Script Approach

Source Type What to extract Script approach
Blog post Core argument, key insights, proof points Distill 2-3 most compelling points. Don't follow the blog structure — restructure for spoken delivery. Open with the hook, not the intro.
Documentation page Steps, code examples, UI descriptions Pick the most important workflow. Walk through it step by step. Show screenshots of each step. Keep it practical — "here is how you do this."
Changelog / release notes What changed, why it matters, how to use it Lead with the impact, not the feature name. "You can now do X" is better than "We shipped feature Y." Show the product UI. Always run changelog enrichment (Step 3b) before writing the script.
Product docs / feature brief Value prop, use cases, how it works Pick ONE use case. Show the problem-solution arc. Do not try to cover everything.
Raw data / metrics Key numbers, trends, surprises Lead with the most surprising data point. Build a "here is what this means" narrative.
Founder's notes / brain dump Core ideas, opinions Clean up into a coherent point of view. Preserve the voice and opinions.
Transcript / talk Key segments, best quotes Do not re-script from scratch. Pull the strongest 60-90 seconds and tighten.
Marketing copy / landing page Value prop, differentiators Expand into a "let me explain why this matters" format. Landing pages are compressed — video scripts need room to breathe.

Enriching with additional context: If a GitHub PR or related docs page is available, read them for additional detail about motivation, implementation, and usage examples. More context produces better scripts.

Step 3b: Changelog Enrichment (changelogs only)

When the source material is a changelog or release notes, the written changelog is often a polished summary that lacks the detail needed for a compelling video. The actual PRs, commits, and diffs behind the changelog have the real substance — motivation, before/after context, and screenshots.

1. Check for inline PR/commit references

Scan the changelog text for links to PRs, commits, or issues. Many changelogs link directly to these. Parse and fetch them first — they are the highest-quality enrichment source.

2. Ask the user for a GitHub repo

"This looks like a changelog. Is there a GitHub repo behind these changes? I can pull PR details, diffs, and screenshots to make the video more specific and accurate. If it is a private repo, you can either give me access or paste the relevant PR URLs."

3. If a repo is available, pull context

  • Date-range matching: If the changelog has a date or version, search the repo for PRs merged in that window. This catches changes the changelog may have missed.
  • PR descriptions: Read the body of each relevant PR. These often contain motivation ("why we built this"), implementation notes, and before/after comparisons.
  • PR screenshots and GIFs: Extract image URLs from PR bodies. These are better than browser screenshots because they show the exact change, not just the current state. Use these as first-class scene backgrounds.
  • Diffs: Read the actual code/config diffs for key PRs. This enables diff-informed scripting — the script can say "notice how the sidebar now shows X" instead of generic descriptions. It makes the video feel like someone who actually built the feature is presenting it.

4. If no repo is available

Proceed with the changelog text alone. Use browser screenshots of the product UI to fill in visual context.

Important: Not all enrichment context should make it into the video. The script stays concise. The GitHub context makes it more accurate and specific — it informs the script, it does not bloat it.

Step 4: Gather Visual Assets

Screenshots and images are the backgrounds for video scenes.

Priority order for sourcing visuals:

  1. User-provided screenshots — use directly, highest priority
  2. Image URLs from the source material (e.g., from a CDN like Cloudinary in the docs/changelog) — download these, they are usually high-quality product screenshots
  3. Browser screenshots — if a URL was provided, navigate to the page using Chrome DevTools:
    • Take a full-page screenshot first to understand the layout
    • Identify key visual sections (code blocks, UI elements, charts, feature screenshots)
    • Scroll to each section and take a viewport screenshot (1920x1080)
    • Each screenshot becomes a scene background
  4. Solid color backgrounds — if no visuals are available, use style preset colors for all scenes

Step 5: Write the Script

Before writing, review your discovery answers. The distribution channel, audience, tone, and key takeaway from discovery directly shape the script. A LinkedIn video needs a punchy 3-second hook. A docs video can open with context. A sales video needs personalization. Let discovery drive the script, not just the source material.

General rules for spoken-word scripts:

  • Short sentences. Average 10-15 words per sentence.
  • Conversational tone. Write how people talk, not how they write.
  • No jargon unless the audience is technical and expects it.
  • No headers, bullet points, or formatting — it is a continuous spoken delivery.
  • Use contractions naturally.
  • Direct address — say "you" frequently.
  • Rhetorical questions work well as transitions.
  • Avoid filler openings like "In this video, I will..." — get to the point.
  • If the user has set an intro/outro phrase in AVATAR-CONFIG.md, use it.

Script structure by video output type:

Documentation walkthrough:

Scene 1 (full avatar): "Here is how to [do X] in [product]. It takes about [N] steps and you will be done in [time]."
Scene 2-N (circle avatar over screenshots): Walk through each step. One step per scene. "First... Then... Now..."
Final scene (full avatar): "That is it. [Recap the outcome]. Check out the docs at [URL] for more."

Changelog / product update:

Scene 1 (full avatar): Hook with impact. "[Product] just shipped [feature]. Here is why it matters."
Scene 2 (circle avatar over product screenshot): What the feature does. Show the UI.
Scene 3 (circle avatar over detail screenshot): The interesting detail or power feature.
Scene 4 (full avatar): Why you should care + CTA.

Feature explainer:

Scene 1 (full avatar): The problem. "If you have ever tried to [pain point], you know it is painful."
Scene 2 (full avatar or screenshot): The solution intro. "That is exactly what [feature] solves."
Scene 3-4 (circle avatar over screenshots): How it works. Walk through the UI.
Scene 5 (full avatar): Why it matters + CTA.

FAQ / common question:

Scene 1 (full avatar): The question. "One thing people ask a lot is: [question]?"
Scene 2 (circle avatar over relevant screenshot): The answer with visual context.
Scene 3 (full avatar): Summary + where to learn more.

In Full Producer mode: Present the full production plan to the user for approval before proceeding. Include the script, scene breakdown, AND the specific visuals for each scene so the user knows exactly what the video will look like:

Production Plan — [Video Title]

Summary: [N] scenes, estimated [X] seconds, [avatar model], [style preset]

Scene Layout Script Visual
1 Full avatar "Hook text here..." Clean Dark background (#1a1a2e)
2 Circle avatar "Feature explanation..." PR screenshot: [description] — [source URL or file]
3 Circle avatar "Detail walkthrough..." Browser screenshot: [page section description]
4 Full avatar "CTA text here..." Clean Dark background (#1a1a2e)

Visual assets I will use:

  • Scene 2: [thumbnail or description of the image, where it came from — PR #123, user-provided, browser screenshot of X page]
  • Scene 3: [same detail]

Want me to adjust anything before I generate?

This gives the user full visibility into the script AND the visuals before any generation happens. If a visual is wrong or missing, they can flag it now instead of after a 15-minute render.

In Quick Shot mode: Skip approval and generate immediately.

Step 6: Build the Scene Composition

Each scene needs three components: character, voice, and background.

Avatar configurations:

Full avatar (intro/outro scenes):

{
    "type": "avatar",
    "avatar_id": "<AVATAR_ID>",
    "avatar_style": "normal",
    "scale": 1.0,
    "use_avatar_iv_model": true
}

Circle avatar in bottom-right corner (content scenes):

{
    "type": "avatar",
    "avatar_id": "<AVATAR_ID>",
    "avatar_style": "circle",
    "scale": 0.4,
    "offset": {"x": 0.35, "y": 0.35},
    "use_avatar_iv_model": true
}

Background types:

Solid color (for intro/outro — use the selected style preset):

{"type": "color", "value": "#1a1a2e"}

Image (for content scenes):

{"type": "image", "image_asset_id": "<ASSET_ID>", "fit": "cover"}

Video (for screen recording backgrounds):

{"type": "video", "video_asset_id": "<ASSET_ID>", "play_style": "fit_to_scene"}

Aspect ratio check: If the video orientation is portrait (1080x1920), adjust the circle avatar offset to {"x": 0.3, "y": 0.4} and consider using scale: 0.3 for better proportions on vertical video.

Step 7: Upload Assets to HeyGen

Upload all screenshot/image files to HeyGen's asset storage.

Endpoint: POST https://upload.heygen.com/v1/asset

Important: This uses a DIFFERENT host than the main API (upload.heygen.com, not api.heygen.com).

Request format: Raw binary body with Content-Type header. NOT multipart form data.

curl -X POST "https://upload.heygen.com/v1/asset" \
  -H "X-Api-Key: <HEYGEN_API_KEY>" \
  -H "Content-Type: image/png" \
  --data-binary @screenshot.png

Response: Returns an id field — this is the image_asset_id to use in scene backgrounds.

Step 8: Submit Video Generation Request

Endpoint: POST https://api.heygen.com/v2/video/generate

Headers:

X-Api-Key: <HEYGEN_API_KEY>
Content-Type: application/json

Payload structure:

{
    "video_inputs": [
        {
            "character": { ... },
            "voice": {
                "type": "text",
                "voice_id": "<VOICE_ID>",
                "input_text": "<SCENE_SCRIPT>"
            },
            "background": { ... }
        }
    ],
    "dimension": {"width": 1920, "height": 1080}
}

API key location: Check the .env file in the project root for HEYGEN_API_KEY.

Step 9: Poll for Completion and Deliver

Video generation is asynchronous. After submitting, the API returns a video_id. The video takes 10-20 minutes to render (longer for Avatar IV, more scenes, or higher resolution).

Poll endpoint: GET https://api.heygen.com/v1/video_status.get?video_id=<VIDEO_ID>

Polling strategy:

  1. Poll every 10 seconds
  2. Log status every 60 seconds to keep the user informed
  3. When status is completed, download the video from video_url
  4. Save to the working directory

On completion, present to the user:

Video complete!
- Duration: [X] seconds
- Scenes: [N]
- Avatar model: [III or IV]
- Visual style: [preset name]
- File: [local path]
- Video URL: [signed URL — expires in 7 days]
- Estimated cost: $[X]

Want me to adjust anything and regenerate?

Step 10: Log the Generation (optional, for learning and iteration)

If a video-log.jsonl file exists in the working directory, append an entry to it. Otherwise, skip this step.

{
    "timestamp": "2026-04-16T10:30:00Z",
    "video_id": "<heygen_video_id>",
    "mode": "full_producer",
    "output_type": "changelog",
    "source_type": "changelog_entry",
    "avatar_id": "<avatar_id>",
    "avatar_model": "avatar_iv",
    "voice_id": "<voice_id>",
    "style_preset": "clean_dark",
    "scenes": 5,
    "duration_seconds": 93,
    "generation_time_seconds": 510,
    "resolution": "1920x1080",
    "local_path": "/path/to/video.mp4",
    "source_url": "https://posthog.com/changelog?id=2666"
}

This log helps track what has been generated, measure generation times, and improve the skill over time.


Cost Reference

Avatar Model Cost per second 60-sec video 90-sec video
Avatar III ~$0.017/sec ~$1.00 ~$1.50
Avatar IV (1080p) ~$0.05/sec ~$3.00 ~$4.50
Avatar IV (4K) ~$0.067/sec ~$4.00 ~$6.00

Limitations and Gotchas

  1. No clickable links in video. Output is flat MP4. Show URLs as text overlays or mention them verbally.
  2. No zoom/pan on backgrounds. If you need a zoomed view of a screenshot, take a separate cropped screenshot and use it as a different scene.
  3. One text overlay per scene. If you need multiple text elements, bake them into the background image.
  4. Max 5,000 characters per scene script. Split long narrations across multiple scenes.
  5. Max 50 scenes per video, max 30 minutes total.
  6. Generation time is 10-20 minutes for a typical 5-scene video. Avatar IV takes longer than Avatar III.
  7. Avatar IDs must match exactly. Always list available avatars first if unsure. Use GET https://api.heygen.com/v2/avatars.
  8. Asset uploads use upload.heygen.com, not api.heygen.com. Use raw binary body with Content-Type header.
  9. Max 10 concurrent video jobs. Exceeding returns HTTP 429.
  10. Signed video URLs expire in 7 days. Always download the video locally.
  11. Avatar IV is ~6x more expensive than Avatar III. For high-volume or draft videos, consider using Avatar III first, then re-generating the final version with Avatar IV.
  12. Portrait orientation requires adjusting circle avatar offset and scale for good proportions.

Available Avatars and Voices

To list available avatars:

curl -s "https://api.heygen.com/v2/avatars" -H "X-Api-Key: <HEYGEN_API_KEY>"

To list available voices:

curl -s "https://api.heygen.com/v2/voices" -H "X-Api-Key: <HEYGEN_API_KEY>"

To design a custom voice from description:

curl -X POST "https://api.heygen.com/v3/voices" \
  -H "X-Api-Key: <HEYGEN_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"description": "friendly male voice, mid-30s, warm and conversational"}'

Known good defaults:

  • Avatar: Adrian_public_3_20240312 (Adrian in Blue Shirt — professional male)
  • Voice: f38a635bee7a4d1f9b0a654a31d050d2 (Chill Brian — natural English male)
1---
2name: talking-head-video
3description: Creates talking head videos from any source material (docs, changelogs, blog posts, notes, transcripts). Produces multi-scene videos with avatar narration over screenshots/images using HeyGen v2 API. Supports Quick Shot and Full Producer modes.
4user-invocable: true
5allowed-tools: Bash, Read, Write, Edit, Grep, Glob, WebSearch, WebFetch
6argument-hint: [source-content-path]
7---
8 
9# Talking Head Video Skill
10 
11You are a video production skill that takes source material and produces a talking head video using HeyGen's v2 API. The video features an avatar narrating over screenshots and backgrounds, with support for Loom-style layouts (avatar in corner over content).
12 
13---
14 
15## Mode Detection
16 
17Before starting, determine which production mode to use based on the user's request:
18 
19### Quick Shot
20**Trigger:** User wants something fast, simple, or says things like "just make a quick video", "nothing fancy", or provides minimal source material (a single paragraph, a short changelog entry).
21 
22- Run discovery (lite — 2 questions)
23- Use default avatar, voice, and style
24- 2-3 scenes max
25- No approval gates — generate immediately
26- Best for: short changelog updates, quick FAQ answers, internal updates
27 
28### Full Producer
29**Trigger:** User provides rich source material, says "make it good", "this is for the website", or the content is longer than a few paragraphs.
30 
31- Run discovery (full — 4 questions)
32- Analyze the source material thoroughly
33- Present the script and scene plan for approval before generating
34- 4-8 scenes
35- Offer style and avatar choices
36- Best for: documentation walkthroughs, feature explainers, customer-facing content
37 
38### Interactive Session
39**Trigger:** User doesn't have source material ready, or says "help me figure out what video to make."
40 
41- Run discovery (extended — 5-6 questions, since there's no source material to read)
42- Help identify what source material is needed
43- Draft the script collaboratively
44- Best for: when the user has an idea but no written content yet
45 
46---
47 
48## Discovery
49 
50Discovery runs in EVERY mode — but the depth varies. The goal is to understand intent, audience, and expectations quickly. **Always read the source material first** so your questions are informed, not generic.
51 
52### How Discovery Works
53 
541. **Read the source material first** (if provided). Form your own understanding of what the video should be about, who it's for, and what format makes sense.
552. **Then ask only what you can't infer.** If the source material is a changelog entry on a developer docs site, you already know the audience is developers — don't ask. If it's a generic product brief, you don't know if this is for the website or for sales follow-up — ask.
563. **Present your assumptions alongside your questions.** Instead of "who is the audience?", say "I'm assuming this is for developers based on the docs page. That right? And a couple more things..."
57 
58### Discovery Questions (pick from this list based on what you DON'T already know)
59 
60| # | Question | Why it matters | When to ask |
61|---|---|---|---|
62| 1 | **What's this video for?** "Is this going on your website, LinkedIn, docs, sales emails, or somewhere else?" | Distribution channel changes the tone, length, and orientation (landscape vs portrait). | Always — unless the user already specified. |
63| 2 | **Who's watching?** "Developers? Marketing people? Founders? General audience?" | Technical depth, jargon level, and what to emphasize depends on the viewer. | Only if not obvious from the source material. |
64| 3 | **What's the one takeaway?** "If the viewer remembers one thing, what should it be?" | Forces clarity. Prevents the script from trying to cover everything. | Always in Full Producer mode. Skip in Quick Shot if the source material has one clear point. |
65| 4 | **Any specific visuals?** "Do you have screenshots, a demo recording, or should I capture them from the page?" | Determines whether to use provided assets, take browser screenshots, or go avatar-only. | Always — even a "no, just grab them from the docs page" is useful. |
66| 5 | **What should it feel like?** "Quick and punchy? Detailed walkthrough? Casual update?" | Sets the script tone and pacing. | Only if not obvious. A changelog is obviously a "casual update." A website feature page is obviously "polished." |
67| 6 | **Anything you definitely want included or excluded?** "Any specific feature to highlight? Anything to avoid mentioning?" | Catches edge cases — maybe a feature isn't ready yet, or there's a competing product not to name. | Only in Full Producer mode. |
68 
69### Discovery by Mode
70 
71**Quick Shot (2 questions max):**
72Read the source material, then ask:
73> "I've read through this. Looks like a [changelog/docs/feature] video for [inferred audience]. Two quick things:
74> 1. Where is this going — docs page, LinkedIn, or something else?
75> 2. Should I grab screenshots from the page, or do you have specific ones?"
76 
77**Full Producer (4 questions):**
78Read the source material, then present your understanding and ask what's missing:
79> "Here's what I'm thinking based on the source material:
80> - **Type:** [changelog recap / docs walkthrough / feature explainer]
81> - **Audience:** [developers / marketers / general]
82> - **Key takeaway:** [one sentence summary]
83> - **Tone:** [casual / professional / energetic]
84>
85> A few questions:
86> 1. Where will this video live? (website, LinkedIn, docs, email)
87> 2. Is that takeaway right, or should the focus be different?
88> 3. Do you have screenshots or should I capture them?
89> 4. Anything specific to include or avoid?"
90 
91**Interactive Session (5-6 questions):**
92No source material to read, so ask more:
93> 1. "What product or feature is this video about?"
94> 2. "Who's the audience?"
95> 3. "What's the one thing the viewer should take away?"
96> 4. "Where will this video be used?"
97> 5. "Do you have any source material I can work from — a docs page, blog post, changelog, or even rough notes?"
98> 6. "What tone — casual update, polished explainer, or something else?"
99 
100### What to Do With Discovery Answers
101 
102Map the answers to concrete production decisions:
103 
104| Discovery answer | Production decision |
105|---|---|
106| **Distribution: LinkedIn** | Portrait orientation (1080x1920), 60 sec max, punchy hook in first 3 seconds |
107| **Distribution: website/docs** | Landscape (1920x1080), can be longer (up to 3 min), professional tone |
108| **Distribution: sales email** | Landscape, 30-60 sec max, personalized hook, strong CTA |
109| **Distribution: internal/investors** | Landscape, can be longer, data-heavy, less polished is fine |
110| **Audience: developers** | Show code, use technical language, no marketing fluff |
111| **Audience: marketers** | Show dashboards/results, use business impact language |
112| **Audience: founders** | Keep it high-level, focus on outcomes not features |
113| **Tone: casual** | Conversational script, contractions, "hey" openers |
114| **Tone: professional** | Clean language, no slang, measured pacing |
115| **Tone: energetic** | Shorter sentences, exclamation in hook, faster pacing |
116 
117---
118 
119## Avatar Setup
120 
121### Check for Existing Avatar Config
122 
123Before generating, check if an `AVATAR-CONFIG.md` file exists in the working directory. If found, read it for the user's preferred avatar and voice settings. Skip the first-run setup and proceed directly to script writing.
124 
125### First-Run Setup (No Config Exists)
126 
127When no `AVATAR-CONFIG.md` is found, run the avatar setup flow before doing anything else. This is a one-time process — the result is saved to `AVATAR-CONFIG.md` for all future videos.
128 
129**Present the options:**
130 
131> "Before we generate your first video, let's set up your avatar. This is a one-time thing — I'll save your choice for all future videos.
132>
133> **How do you want to appear in your videos?**
134>
135> 1. **Pick a stock avatar** — I'll show you a few options from HeyGen's library
136> 2. **Create from your photo** — upload a headshot and I'll generate an avatar from it
137> 3. **Create a digital twin** — upload a 15-second video of yourself talking (best quality, looks like you)
138> 4. **Generate from a description** — describe the look you want and I'll generate it
139>
140> Which option?"
141 
142#### Option 1: Stock Avatar
143 
1441. Fetch available avatars from `GET https://api.heygen.com/v2/avatars`
1452. Filter to a curated shortlist of 4-5 high-quality stock avatars. Pick a diverse set — different genders, appearances, and styles. For each, show:
146 - Name and short description (e.g., "Adrian — professional male in blue shirt")
147 - Avatar ID
148 - Whether it supports Avatar IV (better quality)
1493. Present the shortlist and let the user pick
1504. After selection, proceed to voice selection
151 
152#### Option 2: Photo Avatar
153 
1541. Ask the user to provide a headshot photo (PNG/JPG, under 2K resolution, clear face, neutral background works best)
1552. Upload via `POST https://api.heygen.com/v3/avatars` with `type: "photo"`
1563. Wait for avatar generation to complete
1574. Show the user a preview and confirm it looks good
1585. After confirmation, proceed to voice selection
159 
160#### Option 3: Digital Twin
161 
1621. Explain the requirements:
163 > "Record a 15-second video of yourself talking naturally — look at the camera, speak clearly, good lighting. This will create the most realistic avatar. HeyGen requires consent verification for digital twins."
1642. Ask the user to provide the video file
1653. Upload via `POST https://api.heygen.com/v3/avatars` with `type: "digital_twin"`
1664. Complete the consent verification flow
1675. Wait for processing (this can take several minutes)
1686. Show the user a preview and confirm
1697. After confirmation, proceed to voice selection
170 
171#### Option 4: Generate from Description
172 
1731. Ask the user to describe the look they want (e.g., "friendly woman, early 30s, professional but approachable, dark hair")
1742. Submit via `POST https://api.heygen.com/v3/avatars` with `type: "prompt"` and the description
1753. HeyGen returns up to 3 options
1764. Present all options and let the user pick their favorite
1775. After selection, proceed to voice selection
178 
179### Voice Selection
180 
181After the avatar is chosen, set up the voice. Present two options:
182 
183> "Now let's pick a voice. You can:
184>
185> 1. **Describe what you want** — e.g., 'friendly male voice, warm and conversational' — and I'll generate a few options
186> 2. **Browse the catalog** — I'll show you voices filtered by language and gender
187>
188> Which do you prefer?"
189 
190#### Option 1: Design a Voice
191 
1921. Ask for a text description of the desired voice
1932. Submit via `POST https://api.heygen.com/v3/voices` with the description
1943. Returns up to 3 options, each with a `preview_audio` URL
1954. Present the options with preview links so the user can listen
1965. User picks their favorite
197 
198#### Option 2: Browse Catalog
199 
2001. Ask for language and gender preferences
2012. Fetch from `GET https://api.heygen.com/v2/voices` with filters
2023. Present a curated list of 4-5 options with `preview_audio` URLs
2034. User picks their favorite
204 
205### Save the Config
206 
207After avatar and voice are selected, save everything to `AVATAR-CONFIG.md` in the working directory:
208 
209```markdown
210# Avatar Configuration
211 
212## Identity
213- Name: [avatar name or user's name]
214- Role: [e.g., "Product narrator", "Company spokesperson"]
215 
216## HeyGen Settings
217- Avatar ID: [heygen avatar id]
218- Avatar Type: [stock / photo / digital_twin / prompt]
219- Avatar Model: [avatar_iii or avatar_iv]
220- Voice ID: [heygen voice id]
221- Default Style: [style preset name, default: Clean Dark]
222 
223## Preferences
224- Tone: [e.g., "conversational", "professional", "energetic"]
225- Typical audience: [e.g., "developers", "marketing teams"]
226- Intro phrase: [optional — a signature opening like "Hey, what's up"]
227- Outro phrase: [optional — a signature closing]
228```
229 
230After saving, confirm:
231 
232> "All set! I've saved your avatar config. From now on, all videos will use [avatar name] with [voice name]. You can update this anytime by editing `AVATAR-CONFIG.md` or asking me to change it."
233 
234Then proceed with the video production flow.
235 
236### Updating an Existing Config
237 
238If the user wants to change their avatar or voice later, re-run the relevant part of the setup flow and update `AVATAR-CONFIG.md`. Do not create a new file — overwrite the existing one.
239 
240---
241 
242## Visual Style Presets
243 
244When composing intro/outro scenes (full avatar, no screenshot), use one of these style presets for the background. Match the style to the content type and audience.
245 
246| Preset Name | Background Color | Best For | Vibe |
247|---|---|---|---|
248| **Clean Dark** | `#1a1a2e` | Technical content, developer audience | Professional, focused |
249| **Soft White** | `#f5f5f0` | Product updates, general audience | Clean, approachable |
250| **Warm Charcoal** | `#2d2d2d` | Feature explainers, demos | Modern, sleek |
251| **Deep Navy** | `#0a1628` | Investor updates, enterprise content | Authoritative, serious |
252| **Startup Teal** | `#0d3b3e` | Startup announcements, launches | Energetic, fresh |
253| **Subtle Gradient Dark** | `#1a1a2e``#2d1a3e` | Creative content, brand videos | Polished, distinctive |
254| **Warm Sand** | `#f0e6d3` | Onboarding, welcome videos | Friendly, inviting |
255| **Cool Gray** | `#e8e8e8` | FAQ, help center content | Neutral, informative |
256| **Bold Black** | `#000000` | Strong opinions, hot takes | Direct, dramatic |
257| **Forest** | `#1a2e1a` | Sustainability, growth content | Natural, grounded |
258 
259**Note:** HeyGen v2 API only supports solid color backgrounds (not gradients) for the `color` type. For gradients, create a background image and upload it as an asset.
260 
261**Default:** `Clean Dark` (#1a1a2e) — works well for most content types.
262 
263If the source material is from a specific company/product, try to match their brand colors for the intro/outro backgrounds.
264 
265---
266 
267## Supported Video Output Types
268 
269| Output Type | Typical Duration | Scene Structure | Best For |
270|---|---|---|---|
271| **Documentation walkthrough** | 60-120 sec | Intro (full avatar) → code/UI sections (circle avatar over screenshots) → closing (full avatar) | Explaining how to use a feature, API, or tool |
272| **Changelog / product update** | 45-90 sec | Hook (full avatar) → feature showcase (circle avatar over product screenshots) → closing (full avatar) | Weekly/biweekly "what we shipped" videos |
273| **Feature explainer** | 60-150 sec | Problem (full avatar) → solution intro → demo walkthrough (circle avatar over screenshots) → why it matters → CTA (full avatar) | Product pages, sales enablement, launch announcements |
274| **FAQ / common question** | 30-60 sec | Question (full avatar) → answer with visual (circle avatar over screenshot) → summary (full avatar) | Help center, embedded in docs |
275| **Onboarding welcome** | 45-90 sec | Welcome (full avatar) → step-by-step setup (circle avatar over screenshots) → next steps (full avatar) | Post-signup onboarding flow |
276| **Investor update** | 120-300 sec | Intro (full avatar) → metrics (circle avatar over charts/dashboards) → highlights → challenges → next month (full avatar) | Monthly investor communication |
277| **Sales outreach** | 30-60 sec | Personal hook (full avatar) → relevant screenshot of their use case → CTA (full avatar) | Cold outreach, post-demo follow-up |
278 
279---
280 
281## Supported Inputs
282 
283### Source Material (at least one required)
284 
285| Input Type | What to provide | How the skill uses it |
286|---|---|---|
287| **Text content** | Blog post, changelog entry, release notes, documentation page, raw notes, transcript — pasted directly or as a file path | Extracts key messages, writes the script |
288| **URL** | Link to a webpage (docs page, changelog, blog post) | Fetches and reads the content, takes screenshots of the page for backgrounds |
289| **Screenshots / images** | File paths to PNG/JPG images to use as scene backgrounds | Used directly as backgrounds behind the circle avatar |
290| **Image URLs** | Public URLs to images (e.g., from a CDN, S3, or docs page) | Downloaded, uploaded to HeyGen, used as backgrounds |
291| **GitHub PR link** | URL to a GitHub pull request | Reads PR description, commit messages for additional context |
292| **Video file** | File path to a screen recording or demo video (for Loom-to-polished workflow) | Used as video background behind circle avatar |
293 
294### Image/Video Specifications
295 
296| Asset Type | Supported Formats | Max Size | Recommended Resolution | Notes |
297|---|---|---|---|---|
298| **Background images** | PNG, JPG, JPEG, WebP | 50 MB | 1920x1080 (matches video output) | Images smaller than 1920x1080 will be scaled up with `fit: cover`. Larger images are cropped to fit. |
299| **Background videos** | MP4, MOV, WebM | 100 MB | 1920x1080 | Play styles: `freeze` (first frame), `loop`, `fit_to_scene` (stretch/compress to match script duration), `full_video` (play full length) |
300| **Avatar photo** (for photo avatars) | PNG, JPG | 50 MB | Under 2K resolution | Only needed if creating a custom photo avatar |
301 
302### Configuration Options (all optional — skill has sensible defaults)
303 
304| Option | Values | Default | Notes |
305|---|---|---|---|
306| **Avatar** | Stock avatar name or custom avatar ID | From `AVATAR-CONFIG.md` or `Adrian_public_3_20240312` | User can specify any avatar from their HeyGen account |
307| **Voice** | Stock voice name or custom voice ID | From `AVATAR-CONFIG.md` or `f38a635bee7a4d1f9b0a654a31d050d2` (Chill Brian) | User can specify any voice from their HeyGen account |
308| **Avatar model** | `avatar_iii`, `avatar_iv` | `avatar_iv` | Avatar IV has better lip sync and natural movement. Avatar III is cheaper (~6x) but more robotic. |
309| **Visual style** | Preset name from the style table | `Clean Dark` | Sets the background for intro/outro scenes |
310| **Resolution** | `1920x1080`, `1280x720`, `3840x2160` | `1920x1080` | 4K increases generation time and cost |
311| **Orientation** | `landscape`, `portrait` | `landscape` | Portrait (1080x1920) for social-first vertical video |
312| **Target duration** | Any duration in seconds | Auto (based on script length) | Approximate — actual duration depends on TTS pacing |
313 
314---
315 
316## Video Output Specifications
317 
318| Property | Value |
319|---|---|
320| **Format** | MP4 |
321| **Resolution** | 1920x1080 (default), 1280x720, or 3840x2160 |
322| **Frame rate** | 25 fps |
323| **Max scenes** | 50 per video |
324| **Max duration** | 30 minutes |
325| **Max script length** | 5,000 characters per scene |
326| **Delivery** | Signed URL (expires in 7 days) + local download |
327| **Additional outputs** | Thumbnail (JPG), GIF preview, SRT subtitles (if captions enabled) |
328 
329---
330 
331## How This Skill Works
332 
333### Step 1: Detect Mode and Load Avatar Config
334 
3351. Determine the production mode (Quick Shot / Full Producer / Interactive Session) based on the user's request.
3362. Check for `AVATAR-CONFIG.md` — if found, load avatar and voice preferences.
3373. If no config exists, use defaults.
338 
339### Step 2: Read Source Material + Run Discovery
340 
3411. Read the source material first (if provided — URL, text, file path).
3422. Run discovery based on the detected mode (see Discovery section above).
3433. Map discovery answers to production decisions before proceeding.
3444. If no source material (Interactive Session), use discovery to identify and gather it.
345 
346### Step 3: Classify Source Material and Determine Script Approach
347 
348| Source Type | What to extract | Script approach |
349|---|---|---|
350| **Blog post** | Core argument, key insights, proof points | Distill 2-3 most compelling points. Don't follow the blog structure — restructure for spoken delivery. Open with the hook, not the intro. |
351| **Documentation page** | Steps, code examples, UI descriptions | Pick the most important workflow. Walk through it step by step. Show screenshots of each step. Keep it practical — "here is how you do this." |
352| **Changelog / release notes** | What changed, why it matters, how to use it | Lead with the impact, not the feature name. "You can now do X" is better than "We shipped feature Y." Show the product UI. **Always run changelog enrichment (Step 3b) before writing the script.** |
353| **Product docs / feature brief** | Value prop, use cases, how it works | Pick ONE use case. Show the problem-solution arc. Do not try to cover everything. |
354| **Raw data / metrics** | Key numbers, trends, surprises | Lead with the most surprising data point. Build a "here is what this means" narrative. |
355| **Founder's notes / brain dump** | Core ideas, opinions | Clean up into a coherent point of view. Preserve the voice and opinions. |
356| **Transcript / talk** | Key segments, best quotes | Do not re-script from scratch. Pull the strongest 60-90 seconds and tighten. |
357| **Marketing copy / landing page** | Value prop, differentiators | Expand into a "let me explain why this matters" format. Landing pages are compressed — video scripts need room to breathe. |
358 
359**Enriching with additional context:** If a GitHub PR or related docs page is available, read them for additional detail about motivation, implementation, and usage examples. More context produces better scripts.
360 
361### Step 3b: Changelog Enrichment (changelogs only)
362 
363When the source material is a changelog or release notes, the written changelog is often a polished summary that lacks the detail needed for a compelling video. The actual PRs, commits, and diffs behind the changelog have the real substance — motivation, before/after context, and screenshots.
364 
365**1. Check for inline PR/commit references**
366 
367Scan the changelog text for links to PRs, commits, or issues. Many changelogs link directly to these. Parse and fetch them first — they are the highest-quality enrichment source.
368 
369**2. Ask the user for a GitHub repo**
370 
371> "This looks like a changelog. Is there a GitHub repo behind these changes? I can pull PR details, diffs, and screenshots to make the video more specific and accurate. If it is a private repo, you can either give me access or paste the relevant PR URLs."
372 
373**3. If a repo is available, pull context**
374 
375- **Date-range matching:** If the changelog has a date or version, search the repo for PRs merged in that window. This catches changes the changelog may have missed.
376- **PR descriptions:** Read the body of each relevant PR. These often contain motivation ("why we built this"), implementation notes, and before/after comparisons.
377- **PR screenshots and GIFs:** Extract image URLs from PR bodies. These are better than browser screenshots because they show the exact change, not just the current state. Use these as first-class scene backgrounds.
378- **Diffs:** Read the actual code/config diffs for key PRs. This enables diff-informed scripting — the script can say "notice how the sidebar now shows X" instead of generic descriptions. It makes the video feel like someone who actually built the feature is presenting it.
379 
380**4. If no repo is available**
381 
382Proceed with the changelog text alone. Use browser screenshots of the product UI to fill in visual context.
383 
384**Important:** Not all enrichment context should make it into the video. The script stays concise. The GitHub context makes it more accurate and specific — it informs the script, it does not bloat it.
385 
386### Step 4: Gather Visual Assets
387 
388Screenshots and images are the backgrounds for video scenes.
389 
390**Priority order for sourcing visuals:**
391 
3921. **User-provided screenshots** — use directly, highest priority
3932. **Image URLs from the source material** (e.g., from a CDN like Cloudinary in the docs/changelog) — download these, they are usually high-quality product screenshots
3943. **Browser screenshots** — if a URL was provided, navigate to the page using Chrome DevTools:
395 - Take a full-page screenshot first to understand the layout
396 - Identify key visual sections (code blocks, UI elements, charts, feature screenshots)
397 - Scroll to each section and take a viewport screenshot (1920x1080)
398 - Each screenshot becomes a scene background
3994. **Solid color backgrounds** — if no visuals are available, use style preset colors for all scenes
400 
401### Step 5: Write the Script
402 
403**Before writing, review your discovery answers.** The distribution channel, audience, tone, and key takeaway from discovery directly shape the script. A LinkedIn video needs a punchy 3-second hook. A docs video can open with context. A sales video needs personalization. Let discovery drive the script, not just the source material.
404 
405**General rules for spoken-word scripts:**
406- Short sentences. Average 10-15 words per sentence.
407- Conversational tone. Write how people talk, not how they write.
408- No jargon unless the audience is technical and expects it.
409- No headers, bullet points, or formatting — it is a continuous spoken delivery.
410- Use contractions naturally.
411- Direct address — say "you" frequently.
412- Rhetorical questions work well as transitions.
413- Avoid filler openings like "In this video, I will..." — get to the point.
414- If the user has set an intro/outro phrase in `AVATAR-CONFIG.md`, use it.
415 
416**Script structure by video output type:**
417 
418**Documentation walkthrough:**
419```
420Scene 1 (full avatar): "Here is how to [do X] in [product]. It takes about [N] steps and you will be done in [time]."
421Scene 2-N (circle avatar over screenshots): Walk through each step. One step per scene. "First... Then... Now..."
422Final scene (full avatar): "That is it. [Recap the outcome]. Check out the docs at [URL] for more."
423```
424 
425**Changelog / product update:**
426```
427Scene 1 (full avatar): Hook with impact. "[Product] just shipped [feature]. Here is why it matters."
428Scene 2 (circle avatar over product screenshot): What the feature does. Show the UI.
429Scene 3 (circle avatar over detail screenshot): The interesting detail or power feature.
430Scene 4 (full avatar): Why you should care + CTA.
431```
432 
433**Feature explainer:**
434```
435Scene 1 (full avatar): The problem. "If you have ever tried to [pain point], you know it is painful."
436Scene 2 (full avatar or screenshot): The solution intro. "That is exactly what [feature] solves."
437Scene 3-4 (circle avatar over screenshots): How it works. Walk through the UI.
438Scene 5 (full avatar): Why it matters + CTA.
439```
440 
441**FAQ / common question:**
442```
443Scene 1 (full avatar): The question. "One thing people ask a lot is: [question]?"
444Scene 2 (circle avatar over relevant screenshot): The answer with visual context.
445Scene 3 (full avatar): Summary + where to learn more.
446```
447 
448**In Full Producer mode:** Present the full production plan to the user for approval before proceeding. Include the script, scene breakdown, AND the specific visuals for each scene so the user knows exactly what the video will look like:
449 
450> **Production Plan — [Video Title]**
451>
452> **Summary:** [N] scenes, estimated [X] seconds, [avatar model], [style preset]
453>
454> | Scene | Layout | Script | Visual |
455> |---|---|---|---|
456> | 1 | Full avatar | "Hook text here..." | Clean Dark background (#1a1a2e) |
457> | 2 | Circle avatar | "Feature explanation..." | PR screenshot: [description] — [source URL or file] |
458> | 3 | Circle avatar | "Detail walkthrough..." | Browser screenshot: [page section description] |
459> | 4 | Full avatar | "CTA text here..." | Clean Dark background (#1a1a2e) |
460>
461> **Visual assets I will use:**
462> - Scene 2: [thumbnail or description of the image, where it came from — PR #123, user-provided, browser screenshot of X page]
463> - Scene 3: [same detail]
464>
465> Want me to adjust anything before I generate?
466 
467This gives the user full visibility into the script AND the visuals before any generation happens. If a visual is wrong or missing, they can flag it now instead of after a 15-minute render.
468 
469**In Quick Shot mode:** Skip approval and generate immediately.
470 
471### Step 6: Build the Scene Composition
472 
473Each scene needs three components: character, voice, and background.
474 
475**Avatar configurations:**
476 
477Full avatar (intro/outro scenes):
478```json
479{
480 "type": "avatar",
481 "avatar_id": "<AVATAR_ID>",
482 "avatar_style": "normal",
483 "scale": 1.0,
484 "use_avatar_iv_model": true
485}
486```
487 
488Circle avatar in bottom-right corner (content scenes):
489```json
490{
491 "type": "avatar",
492 "avatar_id": "<AVATAR_ID>",
493 "avatar_style": "circle",
494 "scale": 0.4,
495 "offset": {"x": 0.35, "y": 0.35},
496 "use_avatar_iv_model": true
497}
498```
499 
500**Background types:**
501 
502Solid color (for intro/outro — use the selected style preset):
503```json
504{"type": "color", "value": "#1a1a2e"}
505```
506 
507Image (for content scenes):
508```json
509{"type": "image", "image_asset_id": "<ASSET_ID>", "fit": "cover"}
510```
511 
512Video (for screen recording backgrounds):
513```json
514{"type": "video", "video_asset_id": "<ASSET_ID>", "play_style": "fit_to_scene"}
515```
516 
517**Aspect ratio check:** If the video orientation is portrait (1080x1920), adjust the circle avatar offset to `{"x": 0.3, "y": 0.4}` and consider using `scale: 0.3` for better proportions on vertical video.
518 
519### Step 7: Upload Assets to HeyGen
520 
521Upload all screenshot/image files to HeyGen's asset storage.
522 
523**Endpoint:** `POST https://upload.heygen.com/v1/asset`
524 
525**Important:** This uses a DIFFERENT host than the main API (`upload.heygen.com`, not `api.heygen.com`).
526 
527**Request format:** Raw binary body with Content-Type header. NOT multipart form data.
528 
529```bash
530curl -X POST "https://upload.heygen.com/v1/asset" \
531 -H "X-Api-Key: <HEYGEN_API_KEY>" \
532 -H "Content-Type: image/png" \
533 --data-binary @screenshot.png
534```
535 
536**Response:** Returns an `id` field — this is the `image_asset_id` to use in scene backgrounds.
537 
538### Step 8: Submit Video Generation Request
539 
540**Endpoint:** `POST https://api.heygen.com/v2/video/generate`
541 
542**Headers:**
543```
544X-Api-Key: <HEYGEN_API_KEY>
545Content-Type: application/json
546```
547 
548**Payload structure:**
549```json
550{
551 "video_inputs": [
552 {
553 "character": { ... },
554 "voice": {
555 "type": "text",
556 "voice_id": "<VOICE_ID>",
557 "input_text": "<SCENE_SCRIPT>"
558 },
559 "background": { ... }
560 }
561 ],
562 "dimension": {"width": 1920, "height": 1080}
563}
564```
565 
566**API key location:** Check the `.env` file in the project root for `HEYGEN_API_KEY`.
567 
568### Step 9: Poll for Completion and Deliver
569 
570**Video generation is asynchronous.** After submitting, the API returns a `video_id`. The video takes 10-20 minutes to render (longer for Avatar IV, more scenes, or higher resolution).
571 
572**Poll endpoint:** `GET https://api.heygen.com/v1/video_status.get?video_id=<VIDEO_ID>`
573 
574**Polling strategy:**
5751. Poll every 10 seconds
5762. Log status every 60 seconds to keep the user informed
5773. When status is `completed`, download the video from `video_url`
5784. Save to the working directory
579 
580**On completion, present to the user:**
581```
582Video complete!
583- Duration: [X] seconds
584- Scenes: [N]
585- Avatar model: [III or IV]
586- Visual style: [preset name]
587- File: [local path]
588- Video URL: [signed URL — expires in 7 days]
589- Estimated cost: $[X]
590 
591Want me to adjust anything and regenerate?
592```
593 
594### Step 10: Log the Generation (optional, for learning and iteration)
595 
596If a `video-log.jsonl` file exists in the working directory, append an entry to it. Otherwise, skip this step.
597 
598```json
599{
600 "timestamp": "2026-04-16T10:30:00Z",
601 "video_id": "<heygen_video_id>",
602 "mode": "full_producer",
603 "output_type": "changelog",
604 "source_type": "changelog_entry",
605 "avatar_id": "<avatar_id>",
606 "avatar_model": "avatar_iv",
607 "voice_id": "<voice_id>",
608 "style_preset": "clean_dark",
609 "scenes": 5,
610 "duration_seconds": 93,
611 "generation_time_seconds": 510,
612 "resolution": "1920x1080",
613 "local_path": "/path/to/video.mp4",
614 "source_url": "https://posthog.com/changelog?id=2666"
615}
616```
617 
618This log helps track what has been generated, measure generation times, and improve the skill over time.
619 
620---
621 
622## Cost Reference
623 
624| Avatar Model | Cost per second | 60-sec video | 90-sec video |
625|---|---|---|---|
626| Avatar III | ~$0.017/sec | ~$1.00 | ~$1.50 |
627| Avatar IV (1080p) | ~$0.05/sec | ~$3.00 | ~$4.50 |
628| Avatar IV (4K) | ~$0.067/sec | ~$4.00 | ~$6.00 |
629 
630---
631 
632## Limitations and Gotchas
633 
6341. **No clickable links in video.** Output is flat MP4. Show URLs as text overlays or mention them verbally.
6352. **No zoom/pan on backgrounds.** If you need a zoomed view of a screenshot, take a separate cropped screenshot and use it as a different scene.
6363. **One text overlay per scene.** If you need multiple text elements, bake them into the background image.
6374. **Max 5,000 characters per scene script.** Split long narrations across multiple scenes.
6385. **Max 50 scenes per video, max 30 minutes total.**
6396. **Generation time is 10-20 minutes** for a typical 5-scene video. Avatar IV takes longer than Avatar III.
6407. **Avatar IDs must match exactly.** Always list available avatars first if unsure. Use `GET https://api.heygen.com/v2/avatars`.
6418. **Asset uploads use `upload.heygen.com`**, not `api.heygen.com`. Use raw binary body with Content-Type header.
6429. **Max 10 concurrent video jobs.** Exceeding returns HTTP 429.
64310. **Signed video URLs expire in 7 days.** Always download the video locally.
64411. **Avatar IV is ~6x more expensive** than Avatar III. For high-volume or draft videos, consider using Avatar III first, then re-generating the final version with Avatar IV.
64512. **Portrait orientation** requires adjusting circle avatar offset and scale for good proportions.
646 
647---
648 
649## Available Avatars and Voices
650 
651To list available avatars:
652```bash
653curl -s "https://api.heygen.com/v2/avatars" -H "X-Api-Key: <HEYGEN_API_KEY>"
654```
655 
656To list available voices:
657```bash
658curl -s "https://api.heygen.com/v2/voices" -H "X-Api-Key: <HEYGEN_API_KEY>"
659```
660 
661To design a custom voice from description:
662```bash
663curl -X POST "https://api.heygen.com/v3/voices" \
664 -H "X-Api-Key: <HEYGEN_API_KEY>" \
665 -H "Content-Type: application/json" \
666 -d '{"description": "friendly male voice, mid-30s, warm and conversational"}'
667```
668 
669**Known good defaults:**
670- Avatar: `Adrian_public_3_20240312` (Adrian in Blue Shirt — professional male)
671- Voice: `f38a635bee7a4d1f9b0a654a31d050d2` (Chill Brian — natural English male)
672 

Discussion

Alternatives

Also in Video production