🎙️ slidecast
Turn any topic into a polished HTML slide deck — then narrate it into a slide-synced video.
A Claude Code plugin powered by ElevenLabs text-to-speech.
You: make a 10-slide presentation about our Q3 roadmap, dark theme
Claude: …writes roadmap.html (a clean, self-contained deck)
You: now turn it into a narrated video with a calm female voice
Claude: …writes narration.json, picks a voice, renders + speaks each slide → roadmap.mp4
slidecast adds two skills to Claude Code:
| Skill | What it does |
|---|
| create-presentation | Generates a branded, self-contained HTML deck — 16:9, keyboard-navigable, themeable accent colour, optional dimmed logo watermark. |
| narrate-to-video | Renders each slide headless, generates per-slide narration with ElevenLabs, and stitches a slide-synced MP4 with ffmpeg. |
Both are model-invoked — just describe what you want. No commands to memorize.
Bring your own ElevenLabs key. slidecast never bundles credentials; speech runs on your account, billed to your quota.
Requirements
| Tool | Why | Install |
|---|
ELEVENLABS_API_KEY | text-to-speech (your account) | elevenlabs.io → Profile → API Keys |
ffmpeg + ffprobe | audio/video assembly | brew install ffmpeg · apt install ffmpeg |
| Google Chrome / Chromium | headless slide rendering | any recent build (auto-detected, or set CHROME_BIN) |
python3 | helper scripts (stdlib only — no pip installs) | preinstalled on macOS/Linux |
Only the create-presentation skill works without ElevenLabs; you just won't be able to render video.
Install
/plugin marketplace add alinaqi/slidecast
/plugin install slidecast@slidecast
Then make your key available to the session (or put it in your shell profile):
! export ELEVENLABS_API_KEY=sk_your_key_here
Usage
Make a deck
> Create a 12-slide deck introducing our API, accent colour #6366f1, brand "Acme".
You get a single acme-api.html you can open in any browser. Arrow keys navigate; #3 jumps to slide 3.
Narrate it into a video
> Turn acme-api.html into a narrated video. Use a warm British female voice.
Claude drafts narration.json (one line per slide), picks a voice, and runs the build. The acme-api.mp4 lands next to the deck — each slide held for exactly the length of its narration.
Iterate cheaply. The build is idempotent: edit one slide's narration, delete that clip, re-run — only the changed slide is regenerated.
How it works
- The deck is one self-contained HTML file with a tiny slide engine:
#N jumps to slide N · ?render=1 hides the nav chrome (for clean frames) · arrow keys navigate.
narration.json maps each slide to spoken text:
{ "voice_id": "<id>", "model": "eleven_multilingual_v2",
"segments": [ { "slide": 1, "text": "..." }, { "slide": 2, "text": "..." } ] }
build_video.sh calls ElevenLabs per segment, screenshots each slide via headless Chrome, builds a per-slide ffmpeg clip held for the audio's duration (plus a short tail), and concatenates them into the final MP4.
Nothing is hard-coded — swap the voice, edit the text, rebrand the template, and re-run.
Choosing a voice
# your account voices
python3 scripts/list_voices.py
# the public shared library, filtered
python3 scripts/list_voices.py --shared --gender female --language en
Put the chosen voice_id in narration.json. Models: eleven_multilingual_v2 (accents / non-English), eleven_turbo_v2_5 (fast & cheap), eleven_v3 (most expressive).
Tuning (environment variables)
| Var | Default | Effect |
|---|
SLIDECAST_TAIL | 0.6 | seconds of silence held after each line |
SLIDECAST_WIDTH / SLIDECAST_HEIGHT | 1920 / 1080 | output resolution |
SLIDECAST_FORCE | 0 | 1 = regenerate all audio + renders |
SLIDECAST_STABILITY / SLIDECAST_SIMILARITY / SLIDECAST_STYLE | 0.5 / 0.75 / 0.0 | ElevenLabs voice settings |
CHROME_BIN | auto | explicit Chrome/Chromium path |
Local development
git clone https://github.com/alinaqi/slidecast
claude --plugin-dir ./slidecast/plugins/slidecast # load without installing
claude plugin validate ./slidecast/plugins/slidecast # validate the manifest
Run /reload-plugins after edits to pick up changes.
Project layout