TubeScribe
by @matusvojtek
YouTube video summarizer with speaker detection, formatted documents, and audio output. Works out of the box with macOS built-in TTS. Optional recommended tools (pandoc, ffmpeg, mlx-audio) enhance quality. Requires internet for YouTube access. No paid APIs or subscriptions. Use when user sends a YouTube URL or asks to summarize/transcribe a YouTube video.
clawhub install tubescribeπ About This Skill
name: TubeScribe description: "YouTube video summarizer with speaker detection, formatted documents, and audio output. Works out of the box with macOS built-in TTS. Optional recommended tools (pandoc, ffmpeg, mlx-audio) enhance quality. Requires internet for YouTube access. No paid APIs or subscriptions. Use when user sends a YouTube URL or asks to summarize/transcribe a YouTube video." metadata: { "openclaw": { "emoji": "π¬", "requires": { "bins": ["summarize"] } } }
TubeScribe π¬
Turn any YouTube video into a polished document + audio summary.
Drop a YouTube link β get a beautiful transcript with speaker labels, key quotes, timestamps that link back to the video, and an audio summary you can listen to on the go.
πΈ Free & No Paid APIs
β¨ Features
π¬ Works With Any Video
Quick Start
When user sends a YouTube URL: 1. Spawn sub-agent with the full pipeline task immediately 2. Reply: "π¬ TubeScribe is processing β I'll let you know when it's ready!" 3. Continue conversation (don't wait!) 4. Sub-agent notification will announce completion with title and details
DO NOT BLOCK β spawn and move on instantly.
First-Time Setup
Run setup to check dependencies and configure defaults:
python skills/tubescribe/scripts/setup.py
This checks: summarize CLI, pandoc, ffmpeg, Kokoro TTS
Full Workflow (Single Sub-Agent)
Spawn ONE sub-agent that does the entire pipeline:
sessions_spawn(
task=f"""
TubeScribe: Process {youtube_url}
β οΈ CRITICAL: Do NOT install any software.
No pip, brew, curl, venv, or binary downloads.
If a tool is missing, STOP and report what's needed.
Run the COMPLETE pipeline β do not stop until all steps are done.
Step 1: Extract
bash
python3 skills/tubescribe/scripts/tubescribe.py "{youtube_url}"
Note the Source and Output paths printed by the script. Use those exact paths in subsequent steps.Step 2: Read source JSON
Read the Source path from Step 1 output and note:
metadata.title (for filename)
metadata.video_id
metadata.channel, upload_date, duration_string Step 3: Create formatted markdown
Write to the Output path from Step 1:1. #
2. Video info block β Channel, Date, Duration, URL (clickable). Empty line between each field.
3. ## Participants β table with bold headers:
| Name | Role | Description |
|----------|----------|-----------------|
---
4. ## Summary β 3-5 paragraphs of prose
5. ## Key Quotes β 5 best with clickable YouTube timestamps. Format each as:
"Quote text here." - 12:34"Another quote." - 25:10
Use regular dash -, NOT em dash β. Do NOT use blockquotes >. Plain paragraphs only.
6. ## Viewer Sentiment (if comments exist)
7. ## Best Comments (if comments exist) β Top 5, NO lines between them:
Comment text here.*- β² 123 @AuthorName*
Next comment text here.
*- β² 45 @AnotherAuthor*
Attribution line: dash + italic. Just blank line between comments, NO --- separators.
8. ## Full Transcript β merge segments, speaker labels, clickable timestampsStep 4: Create DOCX
Clean the title for filename (remove special chars), then:
bash
pandoc
Step 5: Generate audio
Write the summary text to a temp file, then use TubeScribe's built-in audio generation:
bash
Write summary to temp file (use python3 to write, avoids shell escaping issues)
python3 -c " text = '''YOUR SUMMARY TEXT HERE''' with open('Generate audio (auto-detects engine, voice, format from config)
python3 skills/tubescribe/scripts/tubescribe.py \ --generate-audioThis reads ~/.tubescribe/config.json and uses the configured TTS engine (mlx/kokoro/builtin), voice blend, and speed automatically. Output format (mp3/wav) comes from config.Step 6: Cleanup
bash
python3 skills/tubescribe/scripts/tubescribe.py --cleanup
Step 7: Open folder
bash
open ~/Documents/TubeScribe/
Report
Tell what was created: DOCX name, MP3 name + duration, video stats.
""",
label="tubescribe",
runTimeoutSeconds=900,
cleanup="delete"
)
After spawning, reply immediately: > π¬ TubeScribe is processing - I'll let you know when it's ready! Then continue the conversation. The sub-agent notification announces completion.
Configuration
Config file: ~/.tubescribe/config.json
{
"output": {
"folder": "~/Documents/TubeScribe",
"open_folder_after": true,
"open_document_after": false,
"open_audio_after": false
},
"document": {
"format": "docx",
"engine": "pandoc"
},
"audio": {
"enabled": true,
"format": "mp3",
"tts_engine": "mlx"
},
"mlx_audio": {
"path": "~/.openclaw/tools/mlx-audio",
"model": "mlx-community/Kokoro-82M-bf16",
"voice": "af_heart",
"lang_code": "a",
"speed": 1.05
},
"kokoro": {
"path": "~/.openclaw/tools/kokoro",
"voice_blend": { "af_heart": 0.6, "af_sky": 0.4 },
"speed": 1.05
},
"processing": {
"subagent_timeout": 600,
"cleanup_temp_files": true
}
}
Output Options
| Option | Default | Description | |--------|---------|-------------| |output.folder | ~/Documents/TubeScribe | Where to save files |
| output.open_folder_after | true | Open output folder when done |
| output.open_document_after | false | Auto-open generated document |
| output.open_audio_after | false | Auto-open generated audio summary |Document Options
| Option | Default | Values | Description | |--------|---------|--------|-------------| |document.format | docx | docx, html, md | Output format |
| document.engine | pandoc | pandoc | Converter for DOCX (falls back to HTML) |Audio Options
| Option | Default | Values | Description | |--------|---------|--------|-------------| |audio.enabled | true | true, false | Generate audio summary |
| audio.format | mp3 | mp3, wav | Audio format (mp3 needs ffmpeg) |
| audio.tts_engine | mlx | mlx, kokoro, builtin | TTS engine (mlx = fastest on Apple Silicon) |MLX-Audio Options (preferred on Apple Silicon)
| Option | Default | Description | |--------|---------|-------------| |mlx_audio.path | ~/.openclaw/tools/mlx-audio | mlx-audio venv location |
| mlx_audio.model | mlx-community/Kokoro-82M-bf16 | MLX model to use |
| mlx_audio.voice | af_heart | Voice preset (used if no voice_blend) |
| mlx_audio.voice_blend | {af_heart: 0.6, af_sky: 0.4} | Custom voice mix (weighted blend) |
| mlx_audio.lang_code | a | Language code (a=US English) |
| mlx_audio.speed | 1.05 | Playback speed (1.0 = normal, 1.05 = 5% faster) |Kokoro PyTorch Options (fallback)
| Option | Default | Description | |--------|---------|-------------| |kokoro.path | ~/.openclaw/tools/kokoro | Kokoro repo location |
| kokoro.voice_blend | {af_heart: 0.6, af_sky: 0.4} | Custom voice mix |
| kokoro.speed | 1.05 | Playback speed (1.0 = normal, 1.05 = 5% faster) |Processing Options
| Option | Default | Description | |--------|---------|-------------| |processing.subagent_timeout | 600 | Seconds for sub-agent (increase for long videos) |
| processing.cleanup_temp_files | true | Remove /tmp files after completion |Comment Options
| Option | Default | Description | |--------|---------|-------------| |comments.max_count | 50 | Number of comments to fetch |
| comments.timeout | 90 | Timeout for comment fetching (seconds) |Queue Options
| Option | Default | Description | |--------|---------|-------------| |queue.stale_minutes | 30 | Consider a processing job stale after this many minutes |Output Structure
~/Documents/TubeScribe/
βββ {Video Title}.html # Formatted document (or .docx / .md)
βββ {Video Title}_summary.mp3 # Audio summary (or .wav)
After generation, opens the folder (not individual files) so you can access everything.
Dependencies
Required:
summarize CLI β brew install steipete/tap/summarizeOptional (better quality):
pandoc β DOCX output: brew install pandocffmpeg β MP3 audio: brew install ffmpegyt-dlp β YouTube comments: brew install yt-dlppip install mlx-audio (uses MLX backend for Kokoro)yt-dlp Search Paths
TubeScribe checks these locations (in order):
| Priority | Path | Source |
|----------|------|--------|
| 1 | which yt-dlp | System PATH |
| 2 | /opt/homebrew/bin/yt-dlp | Homebrew (Apple Silicon) |
| 3 | /usr/local/bin/yt-dlp | Homebrew (Intel) / Linux |
| 4 | ~/.local/bin/yt-dlp | pip install --user |
| 5 | ~/.local/pipx/venvs/yt-dlp/bin/yt-dlp | pipx |
| 6 | ~/.openclaw/tools/yt-dlp/yt-dlp | TubeScribe auto-install |
If not found, setup downloads a standalone binary to the tools directory. The tools directory version doesn't conflict with system installations.
Queue Handling
When user sends multiple YouTube URLs while one is processing:
Check Before Starting
python skills/tubescribe/scripts/tubescribe.py --queue-status
If Already Processing
# Add to queue instead of starting parallel processing
python skills/tubescribe/scripts/tubescribe.py --queue-add "NEW_URL"
β Replies: "π Added to queue (position 2)"
After Completion
# Check if more in queue
python skills/tubescribe/scripts/tubescribe.py --queue-next
β Automatically pops and processes next URL
Queue Commands
| Command | Description | |---------|-------------| |--queue-status | Show what's processing + queued items |
| --queue-add URL | Add URL to queue |
| --queue-next | Process next item from queue |
| --queue-clear | Clear entire queue |Batch Processing (multiple URLs at once)
python skills/tubescribe/scripts/tubescribe.py url1 url2 url3
Processes all URLs sequentially with a summary at the end.Error Handling
The script detects and reports these errors with clear messages:
| Error | Message | |-------|---------| | Invalid URL | β Not a valid YouTube URL | | Private video | β Video is private β can't access | | Video removed | β Video not found or removed | | No captions | β No captions available for this video | | Age-restricted | β Age-restricted video β can't access without login | | Region-blocked | β Video blocked in your region | | Live stream | β Live streams not supported β wait until it ends | | Network error | β Network error β check your connection | | Timeout | β Request timed out β try again later |
When an error occurs, report it to the user and don't proceed with that video.
Tips
tubescribe url1 url2 url3π‘ Examples
When user sends a YouTube URL: 1. Spawn sub-agent with the full pipeline task immediately 2. Reply: "π¬ TubeScribe is processing β I'll let you know when it's ready!" 3. Continue conversation (don't wait!) 4. Sub-agent notification will announce completion with title and details
DO NOT BLOCK β spawn and move on instantly.
βοΈ Configuration
Config file: ~/.tubescribe/config.json
{
"output": {
"folder": "~/Documents/TubeScribe",
"open_folder_after": true,
"open_document_after": false,
"open_audio_after": false
},
"document": {
"format": "docx",
"engine": "pandoc"
},
"audio": {
"enabled": true,
"format": "mp3",
"tts_engine": "mlx"
},
"mlx_audio": {
"path": "~/.openclaw/tools/mlx-audio",
"model": "mlx-community/Kokoro-82M-bf16",
"voice": "af_heart",
"lang_code": "a",
"speed": 1.05
},
"kokoro": {
"path": "~/.openclaw/tools/kokoro",
"voice_blend": { "af_heart": 0.6, "af_sky": 0.4 },
"speed": 1.05
},
"processing": {
"subagent_timeout": 600,
"cleanup_temp_files": true
}
}
Output Options
| Option | Default | Description | |--------|---------|-------------| |output.folder | ~/Documents/TubeScribe | Where to save files |
| output.open_folder_after | true | Open output folder when done |
| output.open_document_after | false | Auto-open generated document |
| output.open_audio_after | false | Auto-open generated audio summary |Document Options
| Option | Default | Values | Description | |--------|---------|--------|-------------| |document.format | docx | docx, html, md | Output format |
| document.engine | pandoc | pandoc | Converter for DOCX (falls back to HTML) |Audio Options
| Option | Default | Values | Description | |--------|---------|--------|-------------| |audio.enabled | true | true, false | Generate audio summary |
| audio.format | mp3 | mp3, wav | Audio format (mp3 needs ffmpeg) |
| audio.tts_engine | mlx | mlx, kokoro, builtin | TTS engine (mlx = fastest on Apple Silicon) |MLX-Audio Options (preferred on Apple Silicon)
| Option | Default | Description | |--------|---------|-------------| |mlx_audio.path | ~/.openclaw/tools/mlx-audio | mlx-audio venv location |
| mlx_audio.model | mlx-community/Kokoro-82M-bf16 | MLX model to use |
| mlx_audio.voice | af_heart | Voice preset (used if no voice_blend) |
| mlx_audio.voice_blend | {af_heart: 0.6, af_sky: 0.4} | Custom voice mix (weighted blend) |
| mlx_audio.lang_code | a | Language code (a=US English) |
| mlx_audio.speed | 1.05 | Playback speed (1.0 = normal, 1.05 = 5% faster) |Kokoro PyTorch Options (fallback)
| Option | Default | Description | |--------|---------|-------------| |kokoro.path | ~/.openclaw/tools/kokoro | Kokoro repo location |
| kokoro.voice_blend | {af_heart: 0.6, af_sky: 0.4} | Custom voice mix |
| kokoro.speed | 1.05 | Playback speed (1.0 = normal, 1.05 = 5% faster) |Processing Options
| Option | Default | Description | |--------|---------|-------------| |processing.subagent_timeout | 600 | Seconds for sub-agent (increase for long videos) |
| processing.cleanup_temp_files | true | Remove /tmp files after completion |Comment Options
| Option | Default | Description | |--------|---------|-------------| |comments.max_count | 50 | Number of comments to fetch |
| comments.timeout | 90 | Timeout for comment fetching (seconds) |Queue Options
| Option | Default | Description | |--------|---------|-------------| |queue.stale_minutes | 30 | Consider a processing job stale after this many minutes |π Tips & Best Practices
tubescribe url1 url2 url3