{"id":"8b52cbb9-bf91-422d-a6e5-fa485c20cc6c","slug":"prez-audio","kind":"skill","name":"prez-audio","summary":"Turn a slide deck into a narrated video: Claude Code skills + a Python engine (ElevenLabs, Kokoro, ffmpeg)","owner":"Igosuki","repoUrl":"https://github.com/Igosuki/prez-audio","license":"MIT","licenseTier":"permissive","trust":"community","stars":0,"match":null,"fewStars":true,"format":"skill","createdAt":"2026-10-09T11:22:11.000Z","addedAt":"2026-10-21T10:30:54.843Z","logoUrl":"https://avatars.githubusercontent.com/u/406150?u=3f475126783bc5e42319d3c6cbfb0eb6a15d77a2&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["design-media","developer-tools"],"tags":["claude-code","elevenlabs","ffmpeg","kokoro","presentation","text-to-speech"],"runtime":"python","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-26T11:40:34.143Z","sample":false,"url":"https://conduits.dev/tools/prez-audio","language":"Python","transports":["stdio"],"install":{"pypi":"prez-audio"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# prez-audio\n\nTurn a slide deck into a narrated video with a cloned voice. Claude Code writes the script and drives the pipeline through three skills; a Python engine (`prez`) does the deterministic work: freeze the slides, call the speech APIs, assemble the video with ffmpeg.\n\nInspired by a LinkedIn post describing the same machine: a talk's deck, narrated by a cloned ElevenLabs voice, produced by Claude Code with three skills, an engine and tests. This repository is an independent open-source reimplementation of that idea, not the original code.\n\n**Demo:** [watch it in the player](https://www.gepsens.com/prez-audio/) (chapters, highlighted sentence, speeds ×1 to ×10), or the raw [mp4](docs/demo/demo-kokoro.mp4). The 6-slide deck in `examples/demo-deck/` was narrated by the local Kokoro voice and produced end to end by `prez`, with no manual editing.\n\n## En bref\n\n`prez-audio` transforme une présentation (deck HTML, PDF ou images) en vidéo narrée avec ta voix clonée ElevenLabs. Trois skills Claude Code (`prez-nouveau`, `prez-discours`, `prez-production`) pilotent un moteur Python, `prez`. L'humain n'intervient qu'à quelques points : valider le plan, fournir la clé API, commenter le discours slide par slide sur une page claude.ai, choisir la voix à l'oreille parmi 4 versions de la slide 1, dire « continue ».\n\nRègle centrale : on corrige une phrase dans le discours, jamais dans la vidéo. Chaque artefact porte l'empreinte de ses entrées ; seules les slides modifiées sont régénérées. Livrables : la vidéo, le player, la page de review, et la machine elle-même (le projet, rejouable).\n\nDémarrage rapide : voir [Quickstart](#quickstart). Démo hors ligne sans clé API : `examples/demo-deck/` avec le backend `fake`.\n\n## Pipeline\n\n```mermaid\nflowchart LR\n    deck[Deck: URL, HTML, PDF, images]\n    transcript[Talk transcript]\n    notes[Notes and sources]\n    voice[Cloned voice]\n\n    deck --> s1\n    transcript --> s2\n    notes --> s2\n    voice --> s3\n\n    s1[\"1. Freeze<br/>prez-nouveau<br/>slides to PNG\"] --> s2\n    s2[\"2. Discours<br/>prez-discours<br/>one text per slide\"] --> h1\n    h1{{\"Human checkpoint 1<br/>comment and validate<br/>the discours\"}} --> s3\n    s3[\"3. Voice<br/>prez-production<br/>4 auditions, synth\"] --> h2\n    h2{{\"Human checkpoint 2<br/>choose the voice by ear\"}} --> s4\n    s4[\"4. Montage<br/>verify, render, player\"]\n\n    s4 --> video[video.mp4, .srt, .vtt]\n    s4 --> player[player.html]\n    s2 --> review[review.html]\n    s4 --> machine[The machine: project, discours, state]\n```\n\nThe audition runs before the full synthesis, so checkpoint 2 comes before any credit is spent on the whole deck.\n\n## Quickstart\n\n### Install\n\nRequires Python 3.11+ and [uv](https://docs.astral.sh/uv/).\n\n```\ngit clone https://github.com/Igosuki/prez-audio && cd prez-audio\nuv sync\nuv run playwright install chromium\nuv run prez --help\n```\n\nTo get `prez` on your PATH without cloning: `uv tool install git+https://github.com/Igosuki/prez-audio`, then `uv tool run --from git+https://github.com/Igosuki/prez-audio playwright install chromium`.\n\nAs a Claude Code plugin:\n\n```\n/plugin marketplace add Igosuki/prez-audio\n/plugin install prez-audio@prez-audio\n```\n\n### Offline demo (fake backend, no API key)\n\nFrom the checkout:\n\n```\nuv run prez new demo --deck examples/demo-deck/index.html --title \"Demo\" --backend fake\nuv run prez -C demo freeze\nmkdir -p demo/discours && cp examples/demo-deck/discours/*.md demo/discours/\nuv run prez -C demo validate all\nuv run prez -C demo synth\nuv run prez -C demo render\nuv run prez -C demo player       # open demo/out/player.html\n```\n\nThen edit one sentence in `demo/discours/slide-03.md` and run `status`, `synth` and `render` again: `synth` refuses until you `validate 3`, and afterwards only slide 3 is re-voiced and re-clipped.\n\nThe fake backend produces a quiet tone at about 0.35 s per word. It exercises the whole pipeline, including fingerprints and partial rebuilds.\n\n### Local demo with a real voice (Kokoro, free, no API key)\n\nThe `kokoro` backend runs the open Kokoro-82M model locally through ONNX Runtime (French voice `ff_siwis`, English `af_heart`). It needs no system packages. The first synth downloads about 120 MB (int8 model plus voices) to `~/.cache/prez-audio/kokoro/` (`$XDG_CACHE_HOME` is honoured).\n\n```\nuv sync --extra kokoro\nuv run prez new demo --deck examples/demo-deck/index.html --title \"Demo\" --lang fr --backend kokoro\n```\n\nThen follow the same steps as the offline demo. `prez voice set voice_id=<kokoro voice>` picks another voice; `prez audition` compares four speeds (0.9 to 1.2) instead of stability/style, and `prez voice choose K` writes the speed. Kokoro ignores stability, style and neighbouring-slide context.\n\n### Real run with ElevenLabs\n\n1. Clone your voice in ElevenLabs and note its `voice_id`.\n2. Store the key: `export ELEVENLABS_API_KEY=...` or `prez key set` (OS keyring; `prez key check` confirms without printing it). It is never written to the project.\n3. In Claude Code, with the plugin installed, ask: \"Narrate my deck at <URL>\". The skills take it from there:\n   - `prez-nouveau` creates the project and freezes the slides.\n   - `prez-discours` writes the script and publishes the review page.\n   - `prez-production` runs the audition, synthesis, verification, render and player.\n\nYou can also run every step by hand with the `prez` commands below.\n\n## The three skills\n\n| Skill | Does | Human step |\n|---|---|---|\n| `prez-nouveau` | Creates the project from a deck, gathers transcript, notes and sources, sets the voice and key, freezes slides to PNG | Confirms the slide count |\n| `prez-discours` | Writes one spoken text per slide from transcript, notes and slide images; publishes the review page; applies comments | Comments card by card; says when it is validated |\n| `prez-production` | Auditions 4 voice variants, synthesizes, verifies, renders, builds the player, redoes edited slides | Chooses the voice by ear |\n\n## Commands\n\n```\nprez new <dir> --deck <src> [--title T] [--lang fr] [--backend elevenlabs|kokoro|fake]\nprez freeze [--exclude 40-42]\nprez status [--json]\nprez discours init | text <sel>\nprez validate <sel>\nprez review-page\nprez audition [--slide 1] [--variants 4]\nprez voice show | set k=v | choose K\nprez synth [<sel>] [--force]\nprez verify [<sel>]\nprez render [--force] [--burn-subs]\nprez player\nprez key set\n```\n\nSlide selectors: `3`, `3,5`, `3-7`, `all`. Run from inside a project or with `-C <dir>`. See [DESIGN.md](DESIGN.md) for details.\n\n## Project layout\n\n```\n<project>/\n  prez.toml          config\n  sources/           transcript, notes, figures\n  deck/              frozen copy of an HTML deck\n  slides/            slide-NN.png and manifest.json\n  discours/          slide-NN.md, the source of truth\n  state/             validated.json, voice.json\n  audition/          voice variants (ignored by git)\n  audio/             TTS output and metadata (ignored)\n  build/clips/       per-slide clips (ignored)\n  out/               video, subtitles, chapters, player, review page (ignored)\n```\n\nThe project is meant to live in a git repository. The discours, sources, slides and state are committed; generated media is rebuilt.\n\n## Guardrails\n\nThe engine enforces these; the skills cannot bypass them.\n\n1. No voice without validated text. `synth` refuses a slide whose text differs from the validated version.\n2. No video with a stale voice. `render` refuses unless every slide's audio matches its expected fingerprint.\n3. Only modified slides are redone. `synth` and `render` skip slides whose fingerprint matches; `--force` overrides.\n4. The deck reads no local file. While freezing, the browser aborts any `file://` request outside the deck's own directory.\n5. Only Claude talks to claude.ai. The engine has no claude.ai code; publishing and reading comments go through Claude Code's Artifact tools.\n\n`prez verify` transcribes each slide's audio and compares it to the text. When the speech-to-text API refuses the request (for example a key without that permission), it reports SKIPPED, never a pass.\n\n## Fingerprints\n\n- `text_fp`: hash of the normalized spoken text of a slide.\n- `audio_fp`: hash of `text_fp` and the voice parameters (backend, voice, model, stability, similarity, style, speed, speaker boost, language). Neighbor slides are not part of it: editing slide 7 re-voices slide 7 only.\n- `clip_fp`: hash of `audio_fp`, the audio file itself, the slide image and the render parameters. Re-voicing a slide with `--force` therefore rebuilds its clip.\n\nChanging a voice parameter makes every slide stale, which is the intended behavior.\n\n## Requirements\n\n- Python 3.11+, uv\n- ffmpeg and ffprobe on PATH\n- Playwright Chromium for HTML decks: `uv run playwright install chromium`\n- poppler (`pdftoppm`) for PDF decks\n- An ElevenLabs account and cloned voice for real runs\n- Claude Code, for the skills\n- An OS keyring (Secret Service, Keychain, Windows Credential Locker) for `prez key set`; otherwise use `ELEVENLABS_API_KEY`\n\n## Known limits\n\n- Slides are still images. Animations and videos inside the deck are not captured.\n- Deck slide detection covers reveal.js, a few common class patterns, a configurable CSS selector, and keyboard navigation as a fallback. Unusual decks may need `deck.selector`.\n- Verification needs speech-to-text access on the ElevenLabs key; without it the check is skipped.\n- A full render of a long deck takes a long time. Keep the machine awake (`systemd-inhibit` on Linux, `caffeinate` on macOS).\n- The voice must be chosen by a person listening; there is no automatic quality judge.\n- Voice backends: ElevenLabs (cloned voices, speech-to-text verification), Kokoro (local, free, preset voices, no verification) and the offline fake backend. No other provider is implemented.\n\n## License\n\nMIT, see [LICENSE](LICENSE).\n"}