SlideStream roadmap¶
Status: draft, October 2026. Update it as phases land; record decisions in ADRs, not here.
Where this is going¶
SlideStream takes a source and turns it into a presentation: a slide deck, a narrated video, or both. The source can be a sentence, a Markdown file, a Word or PDF document, or an existing PowerPoint. Along the way it can add pictures, a voice (including your own), a presenter, a designed template and background music. Users choose how much to steer, from one command with no questions to reviewing and editing every step. Output ranges from a technical lecture deck to a creative explainer video.
Four decisions shape how we get there:
- One tool for the user, many engines behind it. SlideStream orchestrates local and cloud services through adapters and never bundles them (ADR-0010). The engines are listed in SERVICES.md.
- A project folder holds the pipeline's state, so any step can be reviewed, edited and resumed (ADR-0011).
- Every new feature is a stage or an adapter. If it is neither, it waits.
- Every role falls back service → local → bare minimum, so a render always finishes and stays local where it can (ADR-0012). The voice already does: Kokoro, then gTTS.
The CLI stays the main product for power users. The web UI and the Tauri desktop app sit on the same engine. Who it is for, and what they need, is in USER_STORIES.md.
Build order¶
Phase numbers are stable names, so ADRs can refer to them; they are not the order of work. Planned order:
| # | Phase | Why now | Release |
|---|---|---|---|
| 1 | 11: housekeeping (done) | The PyPI page, docs and landing page describe 2.0, not 2.16 | 2.16.1, released |
| 2 | 12: captions, transcript, chapters, alt text | Cheap (narration text and timings exist), often required by institutions | 2.17 |
| 3 | 2c: the user's PowerPoint template | Deterministic design with no service | 2.18 |
| 4 | 14: lecture-quality narration | Bullets appear as spoken, pronunciation, video clips | 2.19 |
| 5 | 13: more outputs | Handout PDF, vertical video, web presentation | 2.20 |
| 6 | 15: richer content | Charts from tables, OCR and long documents | 2.21 |
| 7 | 3, then 4, then 5 | Adapters, project folder, human control | 3.0 |
| 8 | 6 to 10 | Design switch, music, presets, desktop, lens | after 3.0 |
Phase 1: test Presenton against a live server¶
The integration in this working copy was built from Presenton's source and docs and has never talked to a real server (PRESENTON_ANALYSIS.md). Find out whether it solves the template problem before building on it.
- [x] Run Presenton
v0.9.11-betafrom its Docker image. (Used Claude Haiku 5.5 as its LLM rather than Ollama.) - [x] Generate from three real decks: a technical lecture (
.md), a creative piece (.md), and an existing.pptx. - [x] Record for each: slide count kept, slide order kept, how much text
Presenton rewrote, design quality, time taken, and any API differences
from what
presenton.pyexpects. - [x] Find Presenton's health or version endpoint for the adapter probe:
GET /api/v1/auth/status. - [x] Write the result into the analysis doc. Recommendation: go, as an experimental backend for explainer and creative decks. Accepted 16 Oct 2026.
- [x] Send Presenton's
instructionsfield by default. Fixes invented people and most rewritten titles; does not preserve code blocks (no template has a code layout). - [x] Code slides and the fidelity check: Phase 2b.
- [ ] Report the
<b>tag and overlapping-title bugs upstream.
Done when there is a written go or no-go. If no-go, Presenton stays an
experimental option and Phase 6 leans on the pptx-theme backend.
Phase 2: ship the current work as experimental¶
- [x] Replace PyMuPDF (AGPL-3.0) with pypdfium2 (Apache-2.0/BSD-3) for PDF page rendering.
- [x] Add a live contract test for Presenton under
tests/live/. - [x] Refresh
uv.lock. - [x] Bump the version in
pyproject.tomlandsrc/slide_stream/__init__.py. Released as 2.16.0 (16 Oct 2026). - [x] Release notes say Presenton is optional, external, experimental and
CLI-only.
--preserve-styleand--slides-pdfship regardless of the Phase 1 result; they work without Presenton.
Done when the release is on PyPI.
Phase 2b: faithful designed decks (ADR-0013)¶
Make Presenton decks trustworthy for technical content. Each step ships on its own and is tested before the next.
Step 1: the fidelity check (comes first: steps 3 and 4 use it to decide
which slides to fix).
- [x] Parser keeps code blocks as structured data: slide["code_blocks"] =
[{"lang", "code"}], alongside content and markdown.
- [x] fidelity.py: compare source slides with the designed .pptx text;
code kept, title kept, content kept, table kept, possibly invented.
- [x] Print the report after presenton and create --template; write
<output>.fidelity.json.
- [x] providers.presenton.fidelity: warn | strict | off,
fidelity_min_kept.
- [x] Tests on synthetic decks: dropped code, kept code, rewritten title,
invented name and number, extra table row.
Step 2: syntax highlighting.
- [x] code_render.py: Pygments tokens drawn with Pillow in the existing
monospace font; language from the fence, else guessed, else plain.
- [x] Use it for code in SlideStream's plain text cards and the
bullets-beside-artwork layout.
- [x] Light and dark styles; tests that colours differ per token type and
that unknown languages fall back to plain.
Step 3: code slides in the video.
- [x] Theme sampling from neighbouring Presenton frames: background,
accent, light or dark; fall back to SlideStream's look.
- [x] Code card: template-coloured background, title, highlighted code,
sized to fit (shrink the font for long code, within limits).
- [x] providers.presenton.code_slides: auto | always | never; auto
uses the step 1 result.
- [x] In create --template, swap those slides' frames before rendering.
Step 4: code slides in the editable deck.
- [x] In the designed .pptx, replace the chosen slides' shapes with the
title and an editable code text box with one coloured run per
Pygments token; keep slide order, background and notes.
- [x] Title font read from a neighbouring slide.
- [x] Applies to both presenton and create --template.
- [x] Tests: slide count unchanged, notes kept, code text exact, runs
coloured.
- [x] Then: re-run the lecture trial and record the result in the trial README. Done 16 Oct 2026: code shown in video and deck.
Done when the lecture deck shows its code, coloured and correctly
indented, in both the video and the editable .pptx, and the fidelity
report flags slides Presenton changed.
Phase 2c: design from the user's PowerPoint template (ADR-0014)¶
New slides in the user's own style, from a .pptx they already maintain
(a university template, a Quarto/pandoc reference.pptx). No service, no AI
rewording. Pulled ahead of Phase 6 because it depends on nothing in
Phases 3 to 5: python-pptx, the LibreOffice route and the code-slide
helpers already exist.
Step 1: fill a template.
- [ ] pptx_template.py: open a .pptx or .potx, drop its example
slides, pick layouts by pandoc's names (Title Slide, Title and
Content, Section Header, Two Content, Title Only, Blank), with
fallbacks by placeholder type.
- [ ] Fill placeholders: title, bullets, artwork, subtitle; narration in
the speaker notes.
- [ ] Code slides (ADR-0013 code box, keeping the layout's background) and
tables (native, editable PowerPoint tables).
- [ ] Overflow: estimate lines, shrink body text to a floor, report slides
that still overflow.
- [ ] Tests with synthetic templates: standard names, renamed layouts,
missing layouts, .potx, 4:3 size.
Step 2: wire it in.
- [ ] create --pptx-template FILE and settings.pptx_template, for
.pptx output (python-pptx only) and .mp4 output (LibreOffice →
PDF → frames, fitted to the video size with bars, never cropped).
- [ ] doctor checks the template file and, for video, LibreOffice.
Step 3: the plain exporter catches up.
- [ ] export_pptx.py draws code slides and native tables the same way,
instead of turning code into a bullet.
Step 4: Quarto-style helpers.
- [ ] slide-stream template init FILE: a starter template with the
standard layout names (from python-pptx's MIT template, not pandoc's
file).
- [ ] slide-stream template check FILE: layouts found, names missing and
what stands in, missing placeholders, signs of hand styling.
Then: render the trial lecture with a real university template and a
Quarto reference.pptx; record the result in e2e/.
Done when create lecture.md talk.mp4 --pptx-template uni.pptx and the
.pptx equivalent produce slides in the template's style, with code and
tables intact, and template check explains any layout it had to
substitute.
Phase 3: adapters and service status (ADR-0010)¶
This comes before the project folder because the pipeline stages will call these adapters. Settle their interface first.
- [ ] Add
is_configured(),probe()andServiceStatusto the provider interfaces. Keepis_available()as an alias during the change. - [ ] Implement
probe()for each self-hosted service in SERVICES.md; replace each † with a confirmed endpoint. - [ ] Wrap
llm.pyin LLM adapters. Movepresenton.pybehind adesignadapter. - [ ] Add
slide-stream services [--json]. - [ ]
doctorandcreatepreflight useprobe(): strict mode fails before rendering; default mode warns. - [ ] Apply the three-level fallback (ADR-0012) to pictures and presenters: a dead image service tries the local folder before text cards; a dead avatar service falls to static or puppet before none.
- [ ] Report which level each role actually used, in
servicesand in the end-of-run summary. - [ ] Fill in the "Tested" column of SERVICES.md as live tests land.
Done when slide-stream services reports every configured service, and a
dead base_url is caught before the first slide renders.
Phase 4: the project folder (ADR-0011)¶
The biggest refactor so far. Do it in small, safe steps.
- [ ] Characterisation tests that pin today's
createbehaviour for Markdown,.pptx,--script,.pptxoutput and designed slides. - [ ] Create
pipeline/and move one stage at a time out ofcreate(cli.py:203), keeping all tests green after each move. - [ ] Add
state.jsonwith input hashes andformat_version. - [ ] Add
newandbuild; turncreateinto a wrapper. Add--keep-project. - [ ] Point the web server's project workflow (
serve.py:1610) at project folders. - [ ] Add
clean. - [ ] Saved example projects under
tests/fixtures/projects/.
Done when create is a thin wrapper, and editing narration.md then
running build re-runs only audio, avatar and render.
Phase 5: human control¶
- [ ]
build --stop-after,--review,--from,--force. - [ ] An outline stage with review, so users approve structure before any expensive work (an idea taken from Presenton).
- [ ] Tone, verbosity and language options for the outline, content and script stages (also from Presenton).
- [ ] Web and desktop UI show the stages as steps with a "skip reviews" switch.
Done when the same project can run fully automatically or pause at any stage, from the CLI and from the UI.
Phase 6: design backends (ADR-0017, to write)¶
- [ ] Write ADR-0017: one
designrole with interchangeable backends, chosen with--design; it replaces--template(Presenton) and--pptx-template. - [ ]
basic: today's fixed layout, kept as the floor. - [ ]
pptx-theme: the Phase 2c template backend (ADR-0014). - [ ]
presenton: the Phase 3 adapter. - [ ]
preserve: today's--preserve-styleand--slides-pdf. - [ ] Generalise the Phase 2b fidelity check so any design backend can use it.
Done when --design selects any of the four, and the video stage does not
care which one produced the frames.
Phase 7: background music (ADR-0015, to write)¶
- [ ]
--music track.mp3: loop or trim to length, fade in and out, and lower the music under narration (ffmpeg). No AI needed. - [ ] A
musicadapter for ACE-Step 1.5 XL as the default (MIT, output usable commercially). Decide between its own API server and a ComfyUI workflow; the ComfyUI route can reuse the avatar adapter's code. - [ ] A YuE2 adapter as the alternative for songs with lyrics.
- [ ] Generate a track to the video's length, or loop a shorter one with a crossfade. Instrumental by default, since a sung vocal competes with the narration.
- [ ]
doctorshows a one-line licence note when YuE2 or another non-commercial engine is configured. - [ ] Ask Puente to add ACE-Step 1.5 XL as a service.
Done when a video can carry a supplied or generated background track at a level that never masks the narration.
Phase 8: presets (ADR-0016, to write)¶
- [ ] Presets as a config layer between built-in defaults and the user's
file:
lecture,technical,explainer,creative. - [ ] Each sets narration style, image style, design backend, music on or off, and pacing.
- [ ]
slide-stream presetslists them; projects can define their own.
Done when --preset creative and --preset lecture produce clearly
different videos from the same source with no other flags.
Phase 9: desktop¶
The Tauri app stays. Borrow proven patterns from lens-desktop instead of
switching frameworks.
- [ ] A Services panel driven by
slide-stream services --json, showing what is live and how to enable the rest. - [ ] Ollama detection and model download.
- [ ] API keys in the OS keychain instead of
~/.slidestream.yaml. - [ ] Change the bundle identifier from
au.eduserver.slidestreamtoeducation.borck.slidestreambefore the first signed build (signing and notarisation are tied to it; the app stores nothing under it, so only Windows users may need to uninstall the old entry once). - [ ] Code signing and notarisation (builds are unsigned today).
Done when a non-technical user can see which engines are available without reading a config file.
Phase 10: lens family bridges¶
- [ ]
ingestadapter fordocument-analyserover HTTP. - [ ]
checkstage withspeech-analyser(pace, silences) andvideo-analyser(narration against on-slide text).
Done when build can end with a check report in build/.
Phase 11: housekeeping (docs, landing page, tests)¶
The 2026-10 audit found the user-facing material describing SlideStream 2.0. The README is also the PyPI page.
Docs.
- [x] README: cut to about 200 lines (what it is, install, quick start, links
to the docs site); absolute URLs, since PyPI breaks relative links;
drop "What's New in 2.0" and the 2.0-era version history.
- [x] Add CHANGELOG.md, backfilled from the GitHub releases.
- [x] Remove every claim that FFmpeg must be installed (README, USER_GUIDE,
DEVELOPMENT_WORKFLOW, landing page, desktop README and its startup
warning, Dockerfile comment).
- [x] One provider reference per type (TTS, images, LLM, avatar), generated
from the factory's lists, with defaults and the voice floor marked.
- [x] Fix config docs: layers merge, .yml accepted; delete the
"discovery order" sections.
- [x] Standardise install advice on pip install "slide-stream[all]"
(quoted); uv sync for development, not [dev].
- [x] USER_GUIDE: Presenton, code and tables, current model IDs; remove
content duplicated from README and USE_CASES (README: overview;
USE_CASES: recipes; USER_GUIDE: reference).
- [x] DEVELOPMENT_WORKFLOW and CLAUDE.md: current module tree, release steps,
live tests and e2e/.
- [x] Archive obsolete docs (TYPING_IMPROVEMENTS.md, TYPE_SAFETY.md,
avatar-feature-plan.md, liveportrait-api.md,
nonhuman-avatar-api.md) under docs/archive/.
- [x] mkdocs: add Project (Roadmap, User stories, Services, Changelog) and
Decisions (all ADRs) to the nav; build with --strict; fix the link
that points outside docs/.
- [x] deploy/README.md: current image tags and engines.
Landing page.
- [x] Confirm the domain (the old address redirects to
slidestream.borck.education); update site_url, links and CNAME.
- [x] Current features: offline Kokoro voice, mascots and wan-s2v,
PowerPoint output and notes, code slides, designed decks, doctor.
- [x] Link the docs site and PyPI; recommend [all]; no FFmpeg claim.
- [x] Accessibility: <main> and a skip link, hide decorative emoji from
screen readers, fix dark-mode contrast for the accent and links
(both fail WCAG AA), keep Docs visible on small screens.
- [x] No third-party fonts (the page promises privacy): system font stacks.
Tests and CI.
- [x] Split test_providers.py (factory, images, TTS floor, OpenAI TTS,
Chatterbox, Voicebox) and test_serve.py (core, demo, teaser, local
mode, jobs, projects), along their existing section headers.
- [x] Add tests for PDF and Word extraction in draft (untested today);
install the import extra in CI.
- [x] One CI job without system ffmpeg, to exercise the bundled binary.
- [x] Coverage: publish the report and set a floor at today's level, so it
can only rise.
- [x] Silence or fix the Starlette TestClient deprecation warning.
- [x] e2e: a code-and-tables scenario and a Kokoro scenario; no hard-coded
server URLs in committed scenarios.
- [x] Live tests for Presenton (Phase 2 leftover) and Kokoro.
Repo.
- [x] pyproject.toml: keywords, Documentation and Changelog URLs, SPDX
licence field, remove the stale black comment.
- [x] .gitignore: remove duplicates and old output names; ignore site/.
- [x] Move scripts/mascot_video_test.py into e2e/ or remove it.
Done when the PyPI page, docs site and landing page all describe 2.16
correctly, mkdocs build --strict passes, and no test file is over 800
lines.
Phase 12: accessible outputs (ADR-0018, to write)¶
Every video comes with what accessibility rules ask for. Narration text and per-slide timings already exist, so most of this is cheap.
- [ ] Write ADR-0018: narration timing. Synthesise narration per segment (sentence or bullet), so every segment has an exact start and end; captions, chapters (here) and bullet reveal (Phase 14) all use it.
- [ ] Captions:
.srtand.vttbeside every video, one cue per sentence or line-length chunk;--burn-captionsdraws them into the picture. - [ ] Transcript: a readable
.md(and.txt) of the narration, slide by slide, with slide titles as headings. - [ ] Chapters: per-slide chapter markers in the MP4 and a YouTube-style chapter list.
- [ ] Alt text: describe each picture in the
.pptxwith a vision model (already used for picture-only slides);--alt-textto opt in. - [ ] Accessibility checks in
doctor: text contrast on frames, smallest font size against the frame height, missing alt text, captions off. Reading level later throughdocument-analyser(Phase 10).
Done when create deck.md talk.mp4 writes captions, a transcript and
chapters by default, and doctor reports accessibility problems.
Phase 13: more outputs¶
- [ ] Handout PDF: slides with their narration or notes, through the LibreOffice route.
- [ ] Vertical 9:16 video (
--aspect 9:16) for shorts and reels: layouts reflow for portrait; designed slides are letterboxed. - [ ] Self-contained web presentation: one HTML file with slides, audio and captions that plays offline (only if users ask for it; keep it simple, no framework).
Done when one deck produces video, deck, handout and vertical video from the same narration.
Phase 14: lecture-quality narration¶
- [ ] Bullets appear as they are spoken: each bullet is revealed when the narration reaches it, using ADR-0018's segment timings. Applies to SlideStream's own slides; designed slides stay static.
- [ ] Pause markers:
[pause]and[pause 2s]in notes or scripts become real silence (part of segment synthesis; today they are stripped). - [ ] Pronunciation dictionary:
pronunciations:in config and per project (acronyms, names, symbols), applied before TTS. Built-in readings for code symbols so code is not read character by character. - [ ] Video clips on slides:
plays a clip in the slide instead of a still picture; the slide lasts at least as long as the clip.
Done when the trial lecture plays with bullets revealed in step with the
voice, hash() is read naturally, and a slide can show a screen recording.
Phase 15: richer content¶
- [ ] Charts from tables: a numeric Markdown table becomes a chart on
SlideStream's slides and a native chart in the
.pptx; non-numeric tables stay tables. - [ ] Long documents in
draft: split by structure (headings, pages) and summarise in chunks instead of truncating the source. - [ ] OCR for scanned PDFs in
draft, through a local engine (adapter), withdocument-analyseras an option.
Done when draft turns a long or scanned report into a sensible deck,
and a numeric table shows as a chart.
Future work¶
Wanted, but not scheduled:
- Several languages from one deck: translate the narration and voice it per language in one run, with captions per language.
- Batch mode: a folder of decks to a folder of videos, with one report; suits a whole course and CI.
- MCP server: tools for agents to start renders, follow progress and
fetch results, on top of
serve.
Requests to other projects¶
| Project | Request | Why |
|---|---|---|
| Puente | puente connect --json |
Lets SlideStream discover a local stack's URLs without hand-written config. |
| Puente | A Presenton service | Gives power users a one-command Presenton without SlideStream managing Docker. |
| Puente | An ACE-Step 1.5 XL service | The default music engine, alongside or instead of MusicGen, whose weights are non-commercial. |
| Presenton | Open a discussion once Phase 1 works, showing the workflow | Feedback and credit upstream; small, focused PRs for any bugs found. No feature PRs nobody asked for. |
Not planned¶
- Converting a user's PowerPoint template into a SlideStream style format;
the
.pptxitself is the template (ADR-0014). - Vendoring or forking Presenton code, or depending on the
presentonPyPI placeholder. - SlideStream starting and stopping Docker containers by default.
- Switching the desktop app to Electron.
- Optional dependencies under copyleft licences such as AGPL (see SERVICES.md).
- Splitting SlideStream into several PyPI packages. Keep clean module boundaries inside the repo instead.
- A template picker in the desktop app that assumes a Presenton server is running.