yt-to-blog
Full content pipeline: YouTube URL → transcript → blog post → Substack draft → X/Twitter thread → vertical video clips via HeyGen AI avatar. One URL in, entire content suite out. Use when asked to: "turn this video into content", "create a content suite from this YouTube video", "write a blog from this video", "repurpose this video", or any video-to-multi-platform content request. Can run the full pipeline or individual steps.
安装 / 下载方式
TotalClaw CLI推荐
totalclaw install github:LeoYeAI~openclaw-master-skills~yt-to-blogcURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/github%3ALeoYeAI~openclaw-master-skills~yt-to-blog/file -o yt-to-blog.md# YT-to-Blog Content Engine
YouTube URL → blog post + Substack + tweets + vertical video clips. The whole content machine.
## Pipeline Overview
```
YouTube URL
↓
① Transcript (summarize CLI)
↓
② Blog Draft (AI-written in your voice)
↓
③ Substack Publish (browser automation)
↓
④ X/Twitter Post (bird CLI)
↓
④b Facebook Group (optional reminder)
↓
⑤ Script Splitter (extract hook moments)
↓
⑥ HeyGen Videos (AI avatar vertical clips)
↓
⑦ Post-Processing (ffmpeg crop/scale)
↓
📁 Output Folder (blog.md, videos, tweet.txt, URLs)
```
**One URL in → Five platforms out.** Run the whole thing or any step individually.
---
## First-Time Setup Wizard
Walk the user through this on first use. It takes ~10 minutes once, then never again.
### Step 1: Check Dependencies
Run the setup script to check what's installed:
```bash
bash skills/yt-content-engine/setup.sh
```
Required CLIs:
| Tool | Purpose | Install |
|------|---------|---------|
| `summarize` | YouTube transcript extraction | `brew install steipete/tap/summarize` |
| `bird` | X/Twitter posting | `brew install steipete/tap/bird` |
| `ffmpeg` | Video post-processing | `brew install ffmpeg` |
| `curl` | API calls to HeyGen | Usually pre-installed on macOS |
| `python3` | Helper scripts | Usually pre-installed on macOS |
If anything is missing, tell the user what to install and wait for confirmation.
### Step 2: HeyGen API Key
1. Tell the user: "Go to https://app.heygen.com/settings — grab your API key from the API section."
2. If they don't have a HeyGen account: "Sign up at https://heygen.com — the free tier gives you a few credits to test with."
3. Save the key to `config.json` (see config schema below).
4. Test it:
```bash
curl -s -H "X-Api-Key: API_KEY_HERE" https://api.heygen.com/v2/avatars | python3 -c "import sys,json; d=json.load(sys.stdin); print('✅ API key works!' if 'data' in d else '❌ Invalid key')"
```
### Step 3: HeyGen Avatar Setup
Tell the user:
> "For vertical video clips, you need a HeyGen avatar. Here's what matters:
>
> **Record in PORTRAIT mode** (hold your phone vertically). This is critical — if you record landscape, the avatar will be a small strip in the center of a 9:16 frame and we'll need to crop/scale it (which works but loses quality).
>
> Go to https://app.heygen.com/avatars → Create Instant Avatar → follow their recording guide. Stand in good lighting, look at camera, speak naturally for 2+ minutes.
>
> Once created, grab your Avatar ID from the avatar details page."
List their existing avatars to help them pick. Note: the avatars endpoint returns both custom and stock avatars — filter for the user's custom ones (they typically appear first and have personal names):
```bash
curl -s -H "X-Api-Key: API_KEY" https://api.heygen.com/v2/avatars | python3 -c "
import sys, json
data = json.load(sys.stdin)
for a in data.get('data', {}).get('avatars', []):
print(f\" {a['avatar_id']} — {a.get('avatar_name', 'unnamed')}\")
"
```
### Step 4: HeyGen Voice Clone
Tell the user:
> "Go to https://app.heygen.com/voice-clone → Clone your voice. Upload a clean audio sample (1-2 min of you speaking naturally). HeyGen will create a voice ID.
>
> Once done, grab your Voice ID from the voice settings."
List their voices. User's cloned voices typically appear first; stock voices come after:
```bash
curl -s -H "X-Api-Key: API_KEY" https://api.heygen.com/v2/voices | python3 -c "
import sys, json
data = json.load(sys.stdin)
for v in data.get('data', {}).get('voices', []):
print(f\" {v['voice_id']} — {v.get('name', 'unnamed')} ({v.get('language', '?')})\")
"
```
⚠️ **IMPORTANT:** Use the FULL voice_id (e.g., `69da9c9bca78499b98fdac698d2a20cd`), not a truncated version. The API will return "Voice validation failed" if you use a shortened ID.
### Step 5: Substack Login
Substack has no API — posting requires browser automation.
1. Open the OpenClaw managed browser: use browser tool with `profile="openclaw"`
2. Navigate to `https://substack.com/sign-in`
3. Help the user log in with their credentials
4. Verify access by navigating to their publication dashboard
5. Save the publication URL to `config.json`
The browser session persists across restarts. One-time setup.
### Step 6: Save Config
Create `skills/yt-content-engine/config.json` (relative to your workspace):
```json
{
"heygen": {
"apiKey": "YOUR_API_KEY",
"avatarId": "YOUR_AVATAR_ID",
"voiceId": "YOUR_VOICE_ID"
},
"substack": {
"publication": "yourblog.substack.com"
},
"twitter": {
"handle": "@yourhandle"
},
"author": {
"voice": "Description of your writing voice and style",
"name": "Your Name"
},
"video": {
"clipCount": 5,
"maxClipSeconds": 60,
"cropMode": "auto"
}
}
```
**Tip:** If the user already has a voice guide from the `yt-to-blog` skill, read it from `skills/yt-to-blog/references/voice-guide.md` and use it for the `author.voice` field.
### Step 7: Verify Everything
Run the setup script with the config in place:
```bash
bash skills/yt-content-engine/setup.sh
```
It will test each component and report status.
---
## How to Invoke
### Full Pipeline
```
"Turn this into a full content suite: https://youtu.be/XXXXX"
"Content engine this video: [URL]"
"Run the full pipeline on [URL]"
```
### Individual Steps
```
"Just get me the transcript from [URL]"
"Write a blog post from [URL]" (steps 1-2)
"Post this to Substack" (step 3, after blog exists)
"Tweet about this blog post" (step 4)
"Generate video clips from this blog" (steps 5-7)
"Just split this into scripts" (step 5 only)
```
---
## Pipeline Steps
### Step ①: Transcript
Create the output directory for this run, then fetch the YouTube transcript:
```bash
mkdir -p /tmp/yt-content-engine/output-$(date +%Y-%m-%d)/scripts
mkdir -p /tmp/yt-content-engine/output-$(date +%Y-%m-%d)/videos
```
```bash
summarize "YOUTUBE_URL" --extract > /tmp/yt-content-engine/transcript.txt
```
The `--extract` flag prints the raw transcript without LLM summarization. Read the output. If it fails (no captions available), try with `--youtube yt-dlp` for auto-generated captions, or tell the user and suggest they provide a manual transcript.
### Step ②: Blog Draft
Transform the transcript into a polished long-form blog post.
**Load the author voice** from `config.json` → `author.voice`. If a more detailed voice guide exists at `skills/yt-to-blog/references/voice-guide.md`, read and use that too.
**Analysis phase** — before writing, extract from the transcript:
- Core thesis — the single strongest argument or revelation
- Key data points — statistics, quotes, dates, names
- Narrative moments — anecdotes, examples, scenes
- Source links — URLs, studies, references mentioned
- Missing context — what does the reader need that the video assumed?
**Writing structure:**
1. **Cold open (1-3 paragraphs):** Scene-setting. Specific, sensory, emotional hook before data.
2. **Thesis pivot (1 paragraph):** Connect scene to the bigger story.
3. **Data body (5-15 paragraphs):** Alternate data and editorial. Each stat gets a punch line. Subheadings for major breaks only.
4. **Callback (1-2 paragraphs):** Return to opening scene/metaphor.
5. **Closing (3-6 short paragraphs):** Escalating fragments. Final hammer line.
**Writing rules:**
- Vary sentence length dramatically — long data sentences, then short punches
- Em dashes for asides, not parentheses
- Sentence fragments for emphasis
- No bullet lists in the body — narrative flow
- Inline source links, no footnotes
- No "in conclusion" or "to summarize"
- Credit video source naturally: "As [Name] put it..." with link
- Target: 1,500-3,000 words
**Generate 3-5 headline options** with distinct strategies (contrast/irony, revelation, moral framing, callback). Each with a subtitle. Let the user pick.
Save the final draft to the output folder as `blog.md`.
### Step ③: Substack Publish
Post the blog to Substack via browser automation.
1. Read `config.json` → `