
document-to-narration
Convert written documents to narrated video scripts with TTS audio and word-level timing. Use when preparing essays, blog posts, or articles for video narration. Outputs scene files, audio, and VTT with precise word timestamps. Keywords: narration, voiceover, TTS, scenes, audio, timing, video script, spoken.
- Installs
- 974
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/jwynia/agent-skills --skill document-to-narration- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads document-to-narration automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Document to Narration
Convert written documents into narrated video scripts with precise word-level timing.
Core Principle
The agent interprets; the document guides. Rather than rigid template-based splits, this skill uses agent judgment to find where the content naturally breathes, argues, and transitions. The document's argument flow determines scene breaks, not a predetermined structure.
When to Use This Skill
Use this skill when:
- Converting a blog post or essay to video narration
- Preparing content for TTS audio generation
- Breaking long-form content into digestible scenes
- Creating word-level synchronized captions for video
Do NOT use this skill when:
- The content is already in scene/script format
- You need real-time voice synthesis (this is batch processing)
- Working with dialogue or multi-speaker content (single voice only)
Prerequisites
- Deno installed (https://deno.land/)
- Python 3.12 with venv support
- ffmpeg for audio conversion
- whisper-cpp (installed via @remotion/install-whisper-cpp)
- TTS model at
tts/model/(not in git due to size - see Model Setup below)
Complete Pipeline
There are two approaches: per-scene (legacy) and full narration (recommended).
Full Narration Pipeline (Recommended)
Generates a single audio file for consistent volume and pacing:
Document (.md)
↓ [agent interprets scene breaks]
Scene .txt files (01-scene-name.txt, 02-scene-name.txt, ...)
↓ [TTS via narrate-full.py - SINGLE PASS]
full-narration.wav (one consistent audio file)
↓ [Whisper via transcribe-full.py]
full-narration.json + full-narration.vtt (word-level timing)
↓ [extract-scene-boundaries.py]
Scene timing boundaries for video composition
Per-Scene Pipeline (Legacy)
Generates separate audio per scene - can cause volume inconsistencies:
Scene .txt files
↓ [TTS via narrate-scenes.py - MULTIPLE PASSES]
Scene .wav files (volume may vary between scenes)
↓ [concatenate]
Combined audio (may have clipping at boundaries)
Warning: Per-scene TTS generates audio with different volume levels and pacing. When concatenated, this causes audible jumps and clipping. Use the full narration pipeline instead.
Quick Start
Full Narration Pipeline (Recommended)
cd .claude/skills/document-to-narration
source tts/.venv/bin/activate
# 1. Split document into scenes (manual or scripted)
deno run --allow-read --allow-write scripts/split-to-scenes.ts input.md --output ./output/
# 2. Generate single audio file
python scripts/narrate-full.py ./output/scenes/
# 3. Transcribe with word-level timestamps
python scripts/transcribe-full.py ./output/full-narration.wav
# 4. Extract scene boundaries for video timing
python scripts/extract-scene-boundaries.py ./output/scenes/ ./output/full-narration.json --typescript
Legacy Per-Scene Pipeline
# 1. Split document into scenes
deno run --allow-read --allow-write scripts/split-to-scenes.ts input.md --output ./output/
# 2. Generate audio per scene (may have volume inconsistencies)
source tts/.venv/bin/activate
python scripts/narrate-scenes.py ./output/scenes/
# 3. Transcribe (DEPRECATED: transcribe-scenes.ts requires whisper-cpp)
# Use transcribe-full.py instead after concatenating audio
Instructions
Step 1: Setup (First Time Only)
Create Python Virtual Environment
cd .claude/skills/document-to-narration/tts
python3.12 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
TTS Model Setup
The fine-tuned voice model (~7.8GB) is not included in git due to size.
Place your Qwen3-TTS model files in tts/model/:
tts/model/
├── config.json
├── generation_config.json
├── model.safetensors # Main model weights
├── tokenizer_config.json
├── vocab.json
├── merges.txt
└── speech_tokenizer/
└── ...
Install Whisper (if not already installed)
The @remotion/install-whisper-cpp package handles this:
import { installWhisperCpp, downloadWhisperModel } from '@remotion/install-whisper-cpp';
await installWhisperCpp({ to: './whisper-cpp', version: '1.5.5' });
await downloadWhisperModel({ model: 'medium', folder: './whisper-cpp' });
Step 2: Prepare Your Document
The skill works best with:
- Markdown documents with clear heading structure (H1, H2)
- Well-structured arguments with distinct sections
- Content that reads naturally aloud
Step 3: Run the Pipeline
deno run -A scripts/full-pipeline.ts /path/to/essay.md --output ./output/essay-name/
Step 4: Review Output
output/essay-name/
├── scenes/
│ ├── 01-opening-hook.txt # Scene script
│ ├── 01-opening-hook.wav # Generated audio
│ ├── 01-opening-hook.vtt # Word-level captions
│ ├── 02-core-argument.txt
│ ├── 02-core-argument.wav
│ ├── 02-core-argument.vtt
│ └── ...
└── manifest.json # Complete timing data
Scene Boundary Heuristics
The agent identifies scene breaks using these heuristics:
Strong Boundaries (Almost Always Break)
- H2 heading changes
- "Here's the thing" / "The point is" pivot statements
- Major metaphor introduction
- Explicit enumeration ("First...", "Second...")
- Significant perspective shifts
Moderate Boundaries (Consider Breaking)
- Long paragraph after short ones (or vice versa)
- Example-to-principle transitions
- "But" / "However" / "Meanwhile" at paragraph start
- Question-then-answer patterns
Weak Boundaries (Usually Keep Together)
- Paragraph-to-paragraph within same example
- Sequential evidence for same point
- Build-up to a punchline/reveal
Scene Length Guidance
- Target: 100-300 words per scene (30-90 seconds of audio)
- Minimum: 50 words (avoid micro-scenes)
- Maximum: 500 words (avoid cognitive overload)
Anti-Patterns
The Paragraph Slicer
Pattern: Breaking at every paragraph or heading mechanically. Problem: Ignores argument flow. Scenes feel choppy and disconnected. Fix: Look for rhetorical units, not structural units. Multiple paragraphs often form one scene.
The Wall of Text
Pattern: Keeping entire sections as single scenes. Problem: Creates TTS audio that's too long. Loses natural breathing room. Fix: Target 100-300 words. Find the natural pause point within sections.
The Verbatim Transcriber
Pattern: Copying written text exactly without spoken adaptation. Problem: Written conventions don't work when spoken. Parentheticals, complex punctuation, and nested clauses confuse TTS and listeners. Fix: Apply adaptation rules. Read it aloud mentally.
The Over-Adapter
Pattern: Rewriting content so heavily it loses the author's voice. Problem: The result doesn't sound like the original author. Fix: Preserve voice, adjust mechanics. If the author uses rhetorical questions, keep them.
Available Scripts
scripts/split-to-scenes.ts
Parse a markdown document and output scene text files.
deno run --allow-read --allow-write scripts/split-to-scenes.ts input.md --output ./output/
deno run --allow-read --allow-write scripts/split-to-scenes.ts input.md --output ./output/ --adapt
deno run --allow-read scripts/split-to-scenes.ts input.md --dry-run
Options:
--output- Directory for scene files (created if doesn't exist)--adapt- Apply spoken adaptation rules--dry-run- Preview scene breaks without writing files
Output: Numbered .txt files and initial manifest.json
scripts/narrate-full.py (Recommended)
Generate a single TTS audio file from all scene files. Produces consistent volume and pacing.
python scripts/narrate-full.py ./output/scenes/
python scripts/narrate-full.py ./output/scenes/ --force
python scripts/narrate-full.py ./output/scenes/ --speaker jwynia
python scripts/narrate-full.py ./output/scenes/ --output ./custom/path/audio.wav
Options:
--force- Regenerate even if output exists--speaker- Speaker name (default: jwynia)--output- Custom output path (default:../full-narration.wav)
Output: Single full-narration.wav in parent directory of scenes
scripts/narrate-scenes.py (Legacy)
Generate TTS audio for each scene file separately. Not recommended - can cause volume inconsistencies when concatenated.
python scripts/narrate-scenes.py ./output/scenes/
python scripts/narrate-scenes.py ./output/scenes/ --force
python scripts/narrate-scenes.py ./output/scenes/ --speaker jwynia
Options:
--force- Regenerate even if output exists--speaker- Speaker name (default: jwynia)
Output: .wav files alongside each .txt file
scripts/transcribe-full.py (Recommended)
Transcribe audio with word-level timestamps using Python's openai-whisper.
python scripts/transcribe-full.py ./output/full-narration.wav
python scripts/transcribe-full.py ./output/full-narration.wav --model large-v3
python scripts/transcribe-full.py ./output/full-narration.wav --output-dir ./captions/
Options:
--model- Whisper model: tiny, base, small, medium, large, large-v2, large-v3 (default: medium)--output-dir- Output directory (default: same as audio file)
Output:
.vttfile with word-level timestamps.jsonfile with captions array for Remotion
Dependencies: Requires openai-whisper in Python environment:
pip install openai-whisper
scripts/extract-scene-boundaries.py
Extract scene timing boundaries from transcript by matching scene opening phrases.
# Human-readable table
python scripts/extract-scene-boundaries.py ./output/scenes/ ./output/full-narration.json
# JSON output
python scripts/extract-scene-boundaries.py ./output/scenes/ ./output/full-narration.json --json
# TypeScript for Video.tsx
python scripts/extract-scene-boundaries.py ./output/scenes/ ./output/full-narration.json --typescript
Options:
--json- Output as JSON array--typescript- Output as TypeScript code for Video.tsx scenes array
Output: Scene numbers, slugs, start times, and durations
scripts/transcribe-scenes.ts (Deprecated)
Deprecated: Requires whisper-cpp binary which may not be installed. Use
transcribe-full.pyinstead.
Transcribe per-scene audio files using whisper-cpp.
deno run --allow-read --allow-write --allow-run scripts/transcribe-scenes.ts ./output/scenes/
Output: .vtt files with word-level timestamps
scripts/full-pipeline.ts
Orchestrate the complete pipeline.
deno run -A scripts/full-pipeline.ts input.md --output ./output/project-name/
Options:
--output- Output directory (required)--adapt- Apply spoken adaptation--skip-tts- Skip audio generation (text only)--skip-transcribe- Skip Whisper transcription
Output Format
manifest.json
{
"source": "appliance-vs-trade-tool-draft.md",
"created_at": "2024-01-15T10:30:00Z",
"total_scenes": 9,
"total_duration_seconds": 420,
"scenes": [
{
"number": 1,
"slug": "popcorn-opening",
"word_count": 185,
"audio_duration_seconds": 55.2,
"files": {
"text": "scenes/01-popcorn-opening.txt",
"audio": "scenes/01-popcorn-opening.wav",
"captions": "scenes/01-popcorn-opening.vtt"
},
"captions": [
{ "text": "Two", "startMs": 0, "endMs": 180, "confidence": 0.98 },
{ "text": "people", "startMs": 180, "endMs": 450, "confidence": 0.97 }
]
}
]
}
VTT Format
WEBVTT
00:00.000 --> 00:00.180
Two
00:00.180 --> 00:00.450
people
00:00.450 --> 00:00.720
walk
00:00.720 --> 00:01.100
into
Spoken Adaptation
When --adapt is enabled, the skill transforms written conventions to spoken equivalents:
| Written | Spoken |
|---|---|
| Parenthetical asides | Em-dash or separate sentence |
| "e.g." | "for example" |
| "i.e." | "that is" |
| Long nested clauses | Split into multiple sentences |
| Semicolons | Periods |
*emphasis* | Context-appropriate stress |
Preserve:
- Author's voice and tone
- Rhetorical questions
- Deliberate repetition
- Key phrases and memorable formulations
Integration
With remotion-designer
- Pass manifest scene list to remotion-designer
- Each scene becomes a visual design unit
- Word-level timing drives text animation
With Remotion Compositions
import { Audio, useCurrentFrame, Sequence } from 'remotion';
import manifest from './output/manifest.json';
// Use scene durations for Sequence timing
{manifest.scenes.map((scene, i) => (
<Sequence
from={accumulatedFrames}
durationInFrames={scene.audio_duration_seconds * fps}
>
<Audio src={staticFile(scene.files.audio)} />
<CaptionRenderer captions={scene.captions} />
</Sequence>
))}
Technical Notes
WAV Format Conversion
Whisper requires 16kHz mono WAV. The pipeline handles conversion automatically:
ffmpeg -i input.wav -ar 16000 -ac 1 output_16khz.wav
TTS Model
The fine-tuned voice model (~7.8GB) is bundled at tts/model/. Uses Qwen3-TTS with custom speaker embedding.
Performance
- TTS: ~5-30 seconds per sentence (Apple Silicon MPS or NVIDIA CUDA)
- Whisper: ~0.5-2x realtime depending on model size
- Full essay (~2000 words): ~10-20 minutes total processing
What This Skill Does NOT Do
- Generate video visuals (use remotion-designer)
- Real-time voice synthesis
- Multi-speaker dialogue
- Edit or improve the content's argument
- Make editorial changes beyond mechanical spoken adaptation
FAQ
What does the document-to-narration skill do?
Convert written documents to narrated video scripts with TTS audio and word-level timing. Use when preparing essays, blog posts, or articles for video narration. Outputs scene files, audio, and VTT with precise word timestamps. Keywords: narration, voiceover, TTS, scenes, audio, timing, video script, spoken.
How do I install document-to-narration?
Run npx skills add https://github.com/jwynia/agent-skills --skill document-to-narration in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/document-to-narration/ (personal) or .claude/skills/document-to-narration/ (project).
Which AI agents can use document-to-narration?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is document-to-narration safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains document-to-narration?
It is published by jwynia in jwynia/agent-skills. It has 974 recorded installs.
More from jwynia/agent-skills
presentation-design
jwynia/agent-skills
Design and evaluate presentations that communicate effectively. Use when designing a presentation, creating slides, getting presentation feedback, structuring a talk, or reviewing slides. Keywords: presentation, slides, talk, PowerPoint, Keynote, reveal.js.
frontend-design
jwynia/agent-skills
Create distinctive, production-grade frontend interfaces with high design quality. Provides analysis tools for auditing existing designs and generation tools for creating color palettes, typography systems, design tokens, and component templates. Supports React, Vue, Svelte, and vanilla HTML/CSS. Use when building web components, pages, or applications. Keywords: design, UI, frontend, CSS, components, palette, typography, tokens, accessibility.
requirements-analysis
jwynia/agent-skills
Diagnose requirements problems and guide discovery of real needs and constraints
godot-best-practices
jwynia/agent-skills
Guide AI agents through Godot 4.x GDScript coding best practices including scene organization, signals, resources, state machines, and performance optimization. This skill should be used when generating GDScript code, creating Godot scenes, designing game architecture, implementing state machines, object pooling, save/load systems, or when the user asks about Godot patterns, node structure, or GDScript standards. Keywords: godot, gdscript, game development, signals, resources, scenes, nodes, state machine, object pooling, save system, autoload, export, type hints.
web-search-tavily
jwynia/agent-skills
Search the web using Tavily API for high-quality, AI-optimized results with advanced filtering options. Use when you need structured search results, domain filtering, relevance scores, or AI-generated answer summaries. Requires TAVILYAPIKEY. Keywords: tavily, advanced search, filtered search, domain filtering, relevance scoring.
godot-asset-generator
jwynia/agent-skills
Generate game assets using AI image generation APIs (DALL-E, Replicate, fal.ai) and prepare them for Godot. Covers the full art pipeline from concept art and style guides to final sprites, sprite sheets, and import configuration. This skill should be used when creating game art, generating sprites, making tilesets, creating UI elements, or preparing assets for Godot import. Keywords: game assets, AI art, DALL-E, Replicate, fal.ai, sprite sheet, tileset, Godot, pixel art, character sprite, game art, texture, animation frames.
Popular media & creative skills
hyperframes
heygen-com/hyperframes
Read first to make, edit, animate or render any video with HyperFrames (HTML rendered to video), including launch films, explainers, music videos, charts, maps, vertical clips, title cards, captions and overlays. Holds the render contract, the work loop and what each kind of video needs.
media-use
heygen-com/hyperframes
Get or make any media for a HyperFrames video - music, sound effects, images, icons, logos, voiceover, avatar and generated video, transcripts, cutouts, colour grades and looks - with HeyGen or free local tools, and mix placed audio. Also for footage that looks dark, flat or dull, or should be stylized or hidden.
hyperframes-registry
heygen-com/hyperframes
About 450 ready-made HyperFrames blocks and components installed as editable source - transitions, overlays, titles, kinetic type, captions, charts, map overlays, 3D, camera moves. Use it before hand-building any named visual (CRT scanlines, glitch, film grain, a chart); also for hyperframes add and catalog.
hyperframes-creative
heygen-com/hyperframes
Non-animation creative direction for HyperFrames videos. Use for design spec (frame.md / design.md) handling, palettes, typography, narration, beat planning, audio-reactive visuals, composition patterns, and brand / style decisions. For atomic motion patterns and scene blueprints, use hyperframes-animation.
ai-video-generation
101-skills/superpowers
Generate AI videos with Google Veo, Seedance 2.0, HappyHorse, Wan, Grok and 40+ models via inference.sh CLI. Models: Veo 3.1, Veo 3, Seedance 2.0, HappyHorse 1.0, Wan 2.5, Grok Imagine Video, OmniHuman, Fabric, HunyuanVideo. Capabilities: text-to-video, image-to-video, reference-to-video, video editing, lipsync, avatar animation, video upscaling, foley sound. Use for: social media videos, marketing content, explainer videos, product demos, AI avatars. Triggers: video generation, ai video, text to video, image to video, veo, animate image, video from image, ai animation, video generator, generate video, t2v, i2v, ai video maker, create video with ai, runway alternative, pika alternative, sora alternative, kling alternative, seedance, happyhorse
ai-image-generation
101-skills/superpowers
Generate AI images with GPT-Image-2, FLUX, Gemini, Grok, Seedream, Reve and 50+ models via inference.sh CLI. Models: GPT-Image-2, FLUX Dev LoRA, FLUX.2 Klein LoRA, Gemini 3 Pro Image, Grok Imagine, Seedream 4.5, Reve, ImagineArt. Capabilities: text-to-image, image-to-image, inpainting, LoRA, image editing, upscaling, text rendering. Use for: AI art, product mockups, concept art, social media graphics, marketing visuals, illustrations. Triggers: flux, image generation, ai image, text to image, stable diffusion, generate image, ai art, midjourney alternative, dall-e alternative, text2img, t2i, image generator, ai picture, create image with ai, generative ai, ai illustration, grok image, gemini image, gpt image, openai image, chatgpt image