retiam 2.0.1 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/THIRD_PARTY_NOTICES.md +3 -3
  2. package/agent/AGENTS.md +70 -0
  3. package/agent/CLAUDE.md +2 -0
  4. package/agent/skill/SKILL.md +114 -0
  5. package/agent/skill/examples/AreaLesson.ts +48 -0
  6. package/agent/skill/examples/ExplainMotion.ts +32 -0
  7. package/agent/skill/examples/NarratedMotion.ts +50 -0
  8. package/agent/skill/examples/SecantToTangent.ts +142 -0
  9. package/agent/skill/references/api.md +111 -0
  10. package/agent/skill/references/explainers.md +123 -0
  11. package/agent/skill/references/quality.md +151 -0
  12. package/agent/skill/references/styles.md +58 -0
  13. package/agent/skill/references/tts.md +166 -0
  14. package/agent/templates/explainer/lesson.json +25 -0
  15. package/agent/templates/explainer/review.json +6 -0
  16. package/agent/templates/explainer/styles.json +92 -0
  17. package/bin/agent-kit.js +26 -0
  18. package/bin/cli.js +24 -4
  19. package/bin/context.js +57 -0
  20. package/bin/init.js +71 -12
  21. package/bin/lesson-project.js +30 -0
  22. package/bin/lesson.js +195 -0
  23. package/bin/lint.js +6 -6
  24. package/bin/snapshot-runtime.js +185 -0
  25. package/bin/snapshot.js +32 -225
  26. package/dist/THIRD_PARTY_NOTICES.md +3 -3
  27. package/dist/UTIF-D6vx2UEX.min.js +1 -0
  28. package/dist/{UTIF-2Ear_0Uo.js → UTIF-mkffT70R.js} +1 -1
  29. package/dist/decompress-D7LzbvPD.min.js +15 -0
  30. package/dist/{index-B2sJBy4c.js → index-CdBPrYbr.js} +3830 -3795
  31. package/dist/index-jgFyrc2D.min.js +10472 -0
  32. package/dist/libs/explainer/example.d.ts +3 -0
  33. package/dist/libs/explainer/index.d.ts +5 -0
  34. package/dist/libs/explainer/index.js +135 -0
  35. package/dist/libs/explainer/plan.d.ts +12 -0
  36. package/dist/libs/explainer/plan.js +219 -0
  37. package/dist/libs/explainer/runtime.d.ts +24 -0
  38. package/dist/libs/explainer/styles.d.ts +3 -0
  39. package/dist/libs/explainer/types.d.ts +124 -0
  40. package/dist/libs/explainer/visuals.d.ts +18 -0
  41. package/dist/libs/tts/animations/Speak.d.ts +13 -7
  42. package/dist/libs/tts/components/TTSNarrationComponent.d.ts +9 -7
  43. package/dist/libs/tts/core/TTSCache.d.ts +3 -3
  44. package/dist/libs/tts/core/TTSClient.d.ts +3 -3
  45. package/dist/libs/tts/core/types.d.ts +48 -6
  46. package/dist/libs/tts/index.d.ts +2 -1
  47. package/dist/libs/tts/index.js +203 -1333
  48. package/dist/libs/tts/node/index.d.ts +10 -0
  49. package/dist/libs/tts/node/index.js +791 -0
  50. package/dist/libs/tts/providers/ElevenLabsTTSProvider.d.ts +30 -0
  51. package/dist/libs/tts/providers/ITTSProvider.d.ts +2 -2
  52. package/dist/libs/vite/index.d.ts +28 -0
  53. package/dist/libs/vite/index.js +158 -0
  54. package/dist/main-Cc4QQbSK.min.js +5939 -0
  55. package/dist/{main-D_G4uIju.js → main-DMu_5Qy7.js} +1 -1
  56. package/dist/msEdgeV2-D3w4Xsn-.js +642 -0
  57. package/dist/opentype.module-B-1cYAb-.min.js +1 -0
  58. package/dist/retiam.es.js +1 -1
  59. package/dist/retiam.es.min.js +1 -0
  60. package/dist/src/engine/animation/Animation.d.ts +1 -0
  61. package/dist/src/engine/entities/composites/text/mathjaxInterop.d.ts +6 -0
  62. package/package.json +15 -8
  63. package/readme.md +27 -7
@@ -0,0 +1,123 @@
1
+ # Explainer production with Retiam
2
+
3
+ Use this for educational animations. Ordinary title animations and other short
4
+ edits do not need a lesson plan. An AI coding harness authors the subject model,
5
+ script and TypeScript scenes; the CLI supplies deterministic production tools.
6
+ No particular AI provider or additional agent service is required.
7
+
8
+ ## Start from the learner's question
9
+
10
+ Read `lesson/lesson.json` and the existing source. Establish the topic, audience,
11
+ prerequisites, learning objective, duration constraints and requested style from
12
+ the prompt. Infer routine choices; ask only about consequential missing context.
13
+ The supplied area lesson is a working API reference, not the requested subject.
14
+ Replace its model and beats when the user asks for another topic.
15
+
16
+ Research claims that need verification. Record source IDs, titles, links or
17
+ notes in `sources`, and connect factual claims to those IDs. Explicitly mark an
18
+ illustrative model. A numeric simulation may be correct for its assumptions yet
19
+ misrepresent the real system; explain assumptions and avoid false causality.
20
+
21
+ Plan a visible construction and the narration together. Useful beats include a
22
+ question, a prediction, a counterexample, a mechanism, a generalization, an
23
+ application and a resolved takeaway. Choose the sequence for the subject rather
24
+ than forcing every topic into the same chapter count. Each beat records `goal`,
25
+ `visibleChange` and `focus`. Text such as “explain the process” is not a visible
26
+ change; “a molecule passes through the membrane while concentration decreases” is.
27
+
28
+ ## Select the visual mechanism
29
+
30
+ - Algorithms: derive graph, table, queue and code updates from one execution trace.
31
+ Check a result against an independent reference. Use native `Code` and
32
+ `retiam/graphs`; introduce auxiliary representations only when they help.
33
+ - Mathematics: vary a parameter, deform geometry, decompose areas, or connect a
34
+ construction to `Tex`. Transfer identity and color into the notation.
35
+ - Physics: use `retiam/physics` when rigid-body dynamics explain the phenomenon;
36
+ mathematical fields or a deterministic analytic model may be more appropriate.
37
+ - Biology and other processes: author an accurate conceptual model and use
38
+ local interactions, flows and scale changes. Use vectors, shapes or labeled
39
+ assets; a process illustration need not pretend to be a physical simulation.
40
+ - History, economics and data: anchor timelines, maps, comparisons and charts to
41
+ sources. Reveal changes and relationships without animating an unsupported
42
+ causal claim.
43
+
44
+ Use the matching native sublibrary for supported features. Do not import every
45
+ library just to exercise the engine. Novel subjects still need original scenes.
46
+
47
+ ## Write for a curious teacher
48
+
49
+ Keep formal definitions and conditions exact. Around them, invite the learner to
50
+ predict, give space to think, and explain why an observed event matters. Vary the
51
+ rhythm: not every sentence needs a question. Avoid forced jokes and filler.
52
+
53
+ For example: “A currently says four. What if we go through B?” Then a real pause
54
+ while the route lights up. “Two, plus one… three. That's better. Let's remember it.”
55
+ Do not expose the candidate or subtitle answer during that prediction pause.
56
+
57
+ Keep performance notes out of spoken text. A narration segment has an `id`,
58
+ `text`, and optional `pauseAfterMs`. Segments need not correspond one-to-one to
59
+ visual actions. Split at purposeful thinking pauses, retaining coherent speech
60
+ between them. Edge remains the default. When ElevenLabs is selected, use its
61
+ native provider and the initialization/performance guidance in [tts.md](tts.md).
62
+ Keep caption/cue `text` clean; put delivery markup in a segment's `speechText`.
63
+ Other generators may normalize recordings into `PreparedSpeech`.
64
+ Include narration in an explainer unless the user requests a silent treatment.
65
+ The sample's disabled narration is an offline-preview convenience, not a reason
66
+ to omit the requested video's spoken explanation.
67
+
68
+ ## Public workflow
69
+
70
+ The core authoring types and runtime are exported by `retiam/explainer`. Pure
71
+ validation, compilation and style resolution also import in Node through
72
+ `retiam/explainer/plan`. Find declarations with `retiam context --json`.
73
+
74
+ 1. Edit the lesson and write a subject model under `src/`. Persist the requested
75
+ profile in `style`. `retiam lesson style excalidraw` selects the whiteboard look;
76
+ custom style objects extend a preset. Read [styles.md](styles.md) for the look.
77
+ 2. Run `npm run lesson:check`. It checks schema/source references and any prepared
78
+ audio. Its `requiredReview` remains a separate obligation, not a quality score.
79
+ 3. For narration set `narration.enabled` to true, then run
80
+ `npm run lesson:prepare`. First-time native synthesis needs network access;
81
+ subsequent calls use the native cache. It writes `lesson/prepared.json` and
82
+ public audio files. Keep them for reproducible export. Silent preview timings
83
+ are explicitly marked `estimated` and are not locked speech timings.
84
+ 4. Import the lesson and optional prepared manifest into the scene. Use
85
+ `prepareLesson(this, plan, {prepared})`, then `await lesson.run(handlers)`.
86
+ All handlers are built before playback. Put mutations in animations or `b.at()`;
87
+ do not mutate shared objects directly while constructing later beat handlers.
88
+ 5. Bind timing to `b.cue('name')` and `b.durationMs`. A cue identifies a segment
89
+ and optionally a spoken phrase; repeated phrases require `occurrence`.
90
+ Missing, ambiguous or stale cues fail visibly instead of drifting silently.
91
+ Check timing with `npm run lesson:timeline`.
92
+ 6. Type-check and lint, then capture setup, prediction, reveal, transition and
93
+ conclusion frames. `lesson check --json` lists useful sample times. Open the
94
+ PNGs and watch representative short clips for pacing. Fix observed issues.
95
+ 7. Render with the normal Retiam renderer and export captions with
96
+ `npm run lesson:captions`. Inspect final video/audio streams, listen to speech,
97
+ check synchronization and pauses, and update `lesson/review.json` with concrete
98
+ evidence. Report any unavailable checks honestly.
99
+
100
+ The runtime preloads audio, compiles one frame-aligned clock, and schedules all
101
+ clips and visual beat groups on that clock. Native speech and imported assets
102
+ share `durationMs`, word timestamps and a URL in `PreparedSpeech`. Caption cues
103
+ are grouped within speech segments so they cannot bridge a thinking pause.
104
+
105
+ ## Small executable reference
106
+
107
+ Copy `../examples/AreaLesson.ts` from the skill directory into `src/scenes/` to
108
+ run it. `npx create-retiam my-video --template explainer` opens this construction
109
+ with the lesson JSON editable outside the scene. The sample is silent by default
110
+ so a fresh preview works offline; enable native narration when needed.
111
+
112
+ `styleGeometry`, `drawGeometry`, `transferValue` and `emphasize` supply reusable
113
+ motion behaviors. Use public Retiam entities for the rest of the construction.
114
+ A style profile does not automatically make a static scene explanatory.
115
+
116
+ ## Review evidence
117
+
118
+ In `lesson/review.json`, keep automatic command results separate from observed
119
+ facts. Record a frame/clip path, the beat reviewed, what was observed and whether
120
+ it was fixed. Inspect overlaps, readable label sizes, stable identity, meaningful
121
+ motion, prediction/reveal order, and a conclusion with time to read. Check claims
122
+ against sources and domain calculations against independent results. A passing
123
+ plan check cannot establish factual or pedagogical correctness.
@@ -0,0 +1,151 @@
1
+ # 3Blue1Brown-inspired visual explanations
2
+
3
+ The default direction is a 3Blue1Brown-inspired mathematical explainer, built
4
+ with Retiam. Teach through visual intuition and evolving constructions. Match
5
+ the user's subject, audience, duration, and aspect ratio; an explicitly different
6
+ style or palette overrides this default.
7
+
8
+ ## Default visual and narrative direction
9
+
10
+ - **Start with a question worth seeing answered.** Give the viewer a concrete
11
+ example to predict or inspect. Build intuition before naming the general rule.
12
+ - **Make the mathematical objects the main actors.** Let a graph, geometry,
13
+ field, system, or construction occupy the stage. Develop it through the
14
+ explanation, with enough spatial continuity to follow what changed and why.
15
+ - **Use a clean dark canvas.** Favor black or deep charcoal, crisp geometry,
16
+ white mathematical typography, and a few clear accents. Blue and warm yellow
17
+ are useful starting accents; assign colors by mathematical role and preserve
18
+ those roles between diagrams, symbols, and transitions. Keep grids subdued.
19
+ - **Let notation grow from the construction.** Introduce a formula when the
20
+ diagram has established its meaning. Place corresponding terms and objects
21
+ in the same colors. Transform relevant terms deliberately, exposing the
22
+ reasoning instead of replacing complete screens of equations.
23
+ - **Choreograph discoveries.** Use smooth drawing, motion, decomposition,
24
+ regrouping, comparison, and parameter sweeps. Focus the camera or emphasize
25
+ an object when a detail becomes important. Leave time for the viewer to make
26
+ an inference before stating it, then test or generalize the insight.
27
+ - **Narrate as an explanation.** When using narration, generate it through
28
+ `retiam/tts`. Use conversational questions and precise language, synchronize
29
+ speech with visible events, and allow meaningful silent pauses. Keep requested
30
+ subtitles unobtrusive so they leave room for the mathematical construction.
31
+ Match vocal delivery to the beat's question, discovery, or resolution. For
32
+ expressive ElevenLabs delivery follow [tts.md](tts.md): choose model-compatible
33
+ cues, listen to a representative sample, and preserve clean caption text.
34
+
35
+ The goal is a clear, satisfying visual argument. Choose 2D or 3D according to
36
+ the concept. Use a slide, dashboard, or another aesthetic when requested.
37
+
38
+ ## Plan events the viewer can see
39
+
40
+ For each substantial beat, identify:
41
+
42
+ | Decision | Useful answer |
43
+ | --- | --- |
44
+ | What must become clear? | A relationship, cause, comparison, or mechanism |
45
+ | What visibly changes? | A path, configuration, parameter, grouping, or viewpoint |
46
+ | What carries continuity? | The same point, node, symbol, shape, or color meaning |
47
+ | Where should the eye go? | One object or relationship at a time |
48
+ | What warrants a pause? | A meaningful comparison or resolved result |
49
+
50
+ Write an action such as “the second point travels along the curve while the
51
+ secant rotates and the gap collapses.” “Explain the derivative” or “show the next
52
+ heading” does not specify a visual event. Derive the number and length of beats
53
+ from the explanation; do not impose the same five scenes on every subject.
54
+
55
+ Prefer an evolving construction: establish the objects, expose a contrast or
56
+ problem, show the mechanism changing the state, then resolve and generalize.
57
+ Preserve enough context that the viewer can understand each transformation.
58
+
59
+ ## Choreograph meaning
60
+
61
+ - **Carry the idea in geometry.** Trace an actual route, move a point along its
62
+ function, deform the existing object, reveal how pieces assemble, or run the
63
+ simulation. Text describes a result after the viewer has seen its cause.
64
+ - **Preserve identity.** Move or transform the same object between states. Keep
65
+ variable colors consistent between diagrams and formulas. Use matching-symbol
66
+ transforms for a meaningful equation change when appropriate.
67
+ When unrelated symbols should disappear, use `morphUnmatched: false` rather
68
+ than deforming every leftover glyph into a new one.
69
+ - **Direct attention.** Establish context, emphasize the current relationship,
70
+ and widen the view for the result. Zoom or pan only when a close relationship,
71
+ changing frontier, or new scale benefits from it. A well-composed static shot
72
+ can support excellent motion; constant camera movement can obscure it.
73
+ - **Use a few distinct motion functions.** Drawing reveals structure; travel
74
+ shows flow; a morph preserves correspondence; a brief pulse marks a state
75
+ change; a hold gives time to infer. Choose the functions the concept needs.
76
+ - **Coordinate timing.** Related changes should happen together. Give an action
77
+ an appropriate acceleration, settle, and readable pause. Use `Concurrent`
78
+ with an explicit group duration so its defaults do not retime the children.
79
+ Use linear progress for uniform physical/data sweeps and eased motion for
80
+ entrances or changes that should settle; follow the actual simulated model.
81
+ - **Keep labels local and short.** Anchor a cost near the affected node or a
82
+ quantity beside its geometric span. Prefer a few precise words to paragraphs.
83
+ Use `Tex` for formulas and meaningful term matching, not plain text equations.
84
+ - **Let narration explain why.** Align each utterance with the event it explains.
85
+ If requested, use `retiam/tts` and its prepared audio duration. Repeatedly
86
+ replacing paragraphs beside an otherwise idle diagram is not enough motion.
87
+
88
+ Choose colors for hierarchy and meaning, with enough contrast for the output.
89
+ Keep guides quieter than active geometry and leave negative space. The default
90
+ dark palette supports the construction; glow, 3D, and sound effects need an
91
+ explanatory purpose.
92
+
93
+ ## Presentation patterns to revise
94
+
95
+ For an animation brief, revise these patterns unless they serve a specific need:
96
+
97
+ - A permanent title/header, large body panel, footer, chapter number, and page
98
+ counter framing every beat in the same layout.
99
+ - A diagram occupying one corner while most of the frame is explanatory text.
100
+ - An entire screen fading away, followed by a new heading and another fade-in.
101
+ - A long voiceover over a static scene with only a progress bar or decorative glow.
102
+ - Identical reveal timing for every beat, or unrelated objects appearing at once.
103
+ - An algorithm shown mainly as table rows changing while its mechanism stays idle.
104
+
105
+ For example, a Dijkstra explanation can begin with a question about competing
106
+ routes in the graph. Let the viewer predict a winner, then show why counting
107
+ roads can fail when their costs differ. Make the reason for finalizing the
108
+ cheapest unsettled cost visible using the nonnegative-edge assumption.
109
+ Trace the inspected edge, show the candidate cost beside the affected node, and
110
+ visibly retain or reject that route. Move attention with the active frontier,
111
+ keep cost and settled-state meanings consistent, then dim explored clutter and
112
+ trace the winning path. Use a priority queue or table when explaining that
113
+ structure, rather than reserving half the canvas for one throughout the video.
114
+ Follow actual weighted relaxation order; decorative propagation must not imply
115
+ an incorrect algorithm.
116
+
117
+ ## Working reference
118
+
119
+ [SecantToTangent.ts](../examples/SecantToTangent.ts) is a silent visual reference:
120
+
121
+ | Time | Visible event | Purpose |
122
+ | --- | --- | --- |
123
+ | 0–3.1 s | Draw the curve, mark two points, introduce the secant and its gap | Establish the construction |
124
+ | 3.1–6.3 s | Move the second point along the curve; the line rotates and the gap shrinks | Show what determines the secant slope |
125
+ | 6.3–11.1 s | Bring attention closer and continue the convergence | Make the limiting relationship visible |
126
+ | 11.1–13.1 s | Resolve the tangent and transform the equation | Connect geometry to notation |
127
+ | 13.1–19.5 s | Move the tangent point across both sides of the curve, updating the slope | Generalize beyond one frozen example |
128
+ | 19.5–21.5 s | Hold the resolved construction | Allow the takeaway to register |
129
+
130
+ The smaller `ExplainMotion.ts` and `NarratedMotion.ts` examples isolate API and
131
+ speech mechanics. They are not visual templates for finished explainers.
132
+
133
+ ## Review the rendered evidence
134
+
135
+ Capture the setup, the middle of the main mechanism, a transition, and the resolved
136
+ state at the intended aspect ratio. Open the PNGs and watch playback.
137
+
138
+ - Is the mathematical/data relationship correct throughout the motion?
139
+ - Does the construction establish intuition before introducing the general rule?
140
+ - Do corresponding geometric objects and mathematical terms keep their color meaning?
141
+ - Is the focal object clear, with readable labels and no accidental overlap or clipping?
142
+ - Does the main action demonstrate the idea without requiring every caption?
143
+ - Can the viewer follow the same object through transitions and reframing?
144
+ - Do motion and pauses feel purposeful when watched at normal speed?
145
+ - Does the conclusion remain visible long enough to read?
146
+
147
+ Compare the middle of adjacent beats. If only the heading or paragraph changes,
148
+ redesign the visible action. A deliberate reading hold or final rest is useful;
149
+ idle slides throughout an explanation need revision. Record concrete observed
150
+ issues and fix them. Lint and type checks cannot judge aesthetic quality or
151
+ explanatory correctness, and static screenshots cannot establish pacing.
@@ -0,0 +1,58 @@
1
+ # Visual style profiles
2
+
3
+ Teaching goals and visual style are independent. Read the user's prompt first.
4
+ An explicit requested style overrides `lesson/lesson.json`; save that choice so
5
+ future revisions remain consistent. Keep the same mathematical/content model and
6
+ narration cues when restyling. Preserve explicit brand, aspect and accessibility
7
+ constraints. `retiam lesson styles --json` gives actual tokens for this version.
8
+
9
+ ## mathematical — default, matching the Dijkstra video
10
+
11
+ Use navy `#0A1020`, light text, vivid blue and gold, with mint, coral, violet and
12
+ teal available as stable object identities. Color carries meaning across the
13
+ construction, labels, formulas and data transfers. Do not turn the palette into
14
+ random per-frame decoration. Let lines trace real paths, values travel between
15
+ representations, replacements settle smoothly and discarded candidates fade.
16
+ Ask a question, allow a thinking pause, then reveal its answer through geometry.
17
+ Use native `Tex` and syntax-highlighted `Code` where they explain the subject.
18
+ Introduce tables and queues as teaching objects only when relevant. Maintain
19
+ spatial continuity through derivations and applications; conclude with the idea
20
+ that the evolving construction has established.
21
+
22
+ ## excalidraw — hand-drawn whiteboard
23
+
24
+ Use warm paper, dark ink, blue and amber markers. The profile selects Retiam's
25
+ bundled `excalifont` for vector labels. Use native `toExcalidraw` through
26
+ `styleGeometry`, and `drawGeometry` for progressive sketch drawing. Use seeded,
27
+ restrained roughness, intentional arrows and light hatching. Keep mathematical
28
+ symbols readable in `Tex`. A question, sketched experiment and resolving annotation
29
+ can share one evolving board. Use dark paper as a custom override if requested.
30
+ Do not apply roughness to every text glyph or continuously jitter all labels.
31
+
32
+ ## minimal — clear vector construction
33
+
34
+ Use a light canvas, precise outlines, generous negative space and a small number
35
+ of semantic colors. Motion should isolate a relation: align, compare, decompose,
36
+ transfer or resolve. Keep labels local and avoid filling the quiet space with
37
+ paragraphs. Minimal graphics can still carry a lively teacher's narration.
38
+
39
+ ## cinematic — deliberate depth and staging
40
+
41
+ Use a dark canvas, violet/teal accents, slower establishing moves and a strong
42
+ focus for the current event. Use depth or 3D when it explains a spatial relation;
43
+ 2D with deliberate staging is also valid. Lighting and highlights support the
44
+ mechanism. Keep labels and formulas clear as the camera moves, and let the
45
+ resolved state rest. Motion quality does not require constant camera movement.
46
+
47
+ ## Custom override
48
+
49
+ A prompt can describe a new palette or reference look. Preserve the selected
50
+ profile's useful behavior while overriding tokens in JSON, for example:
51
+
52
+ ```json
53
+ {"style":{"extends":"excalidraw","name":"Night chalkboard","background":"#122322","ink":"#F4F2DD","primary":"#7DE1C4","secondary":"#F1CC75","muted":"#94AAA5","accents":["#7DE1C4","#F1CC75"]}}
54
+ ```
55
+
56
+ `resolveStyle` validates the tokens. Fonts must be bundled aliases or available
57
+ user-supplied font assets. Profile changes affect only entities using the profile;
58
+ agent-authored custom colors/materials must be reviewed during a restyle.
@@ -0,0 +1,166 @@
1
+ # Retiam narration: synthesis and performance
2
+
3
+ Use `retiam/tts` for speech, timing, subtitles, and the scene voiceover bus.
4
+ Microsoft Edge is the default. Use the native `ElevenLabsTTSProvider` when the
5
+ user selects ElevenLabs and supplies credentials. Preserve the chosen provider;
6
+ diagnose failures rather than silently switching generators or installing Python
7
+ TTS tools. Read the installed declarations before using newer options.
8
+
9
+ ## ElevenLabs: initialize the provider directly
10
+
11
+ No ElevenLabs Vite plugin or Vite configuration is needed. For a self-contained
12
+ scene example, put `new ElevenLabsTTSProvider()`, `await provider.init({ apiKey,
13
+ voiceId, ... })`, and `await provider.synthesize(...)` inside `Scene.run()`.
14
+ Pass the key directly to initialization. A `.env`, `process.env`, a preparation
15
+ script, and pre-generated audio are optional workflows, not setup requirements;
16
+ do not introduce them when the user requests a simple in-scene example.
17
+ Register synthesis in `composer.pendingTasks` before awaiting it for headless
18
+ rendering. A provider instance can be used directly; selecting it globally is
19
+ only needed when using the `TTS`, `Speak`, or `speak()` facades.
20
+
21
+ To select an initialized provider globally:
22
+
23
+ ```ts
24
+ import { ElevenLabsTTSProvider, TTS } from 'retiam/tts';
25
+
26
+ export async function useExpressiveVoice(apiKey: string, voiceId: string) {
27
+ const provider = new ElevenLabsTTSProvider();
28
+ await provider.init({
29
+ apiKey, voiceId,
30
+ modelId: 'eleven_v3',
31
+ voiceSettings: { stability: 0.5 },
32
+ });
33
+ TTS.setProvider(provider);
34
+ return provider;
35
+ }
36
+ ```
37
+
38
+ `apiKey` and `voiceId` come from the caller's setup, not literal credentials
39
+ committed to a scene. Browser initialization uses the caller's key directly and
40
+ makes it accessible to that browser. For private preparation use Node's
41
+ `retiam/tts/node` entry point, with the same provider API, and ship the generated
42
+ audio. Do not add ElevenLabs credentials or middleware to `vite.config.ts`.
43
+ Initialization validates local settings without generating audio or fetching
44
+ voices. Use `await provider.fetchVoices()` when choosing a voice;
45
+ `provider.getVoices()` and `TTS.findVoice()` then use that fetched catalog.
46
+ Require a real ElevenLabs voice ID, not an Edge ID or an invented display name.
47
+
48
+ The default model is `eleven_multilingual_v2`. Select an available expressive
49
+ model such as `eleven_v3` or `eleven_v4` deliberately when directing with audio
50
+ tags. Keep a compatible model/voice pairing throughout a speaker's performance.
51
+ The provider accepts open model IDs, MP3 output formats, model-specific voice
52
+ settings, language, seed, pronunciation dictionaries, and neighboring-text context.
53
+ Per-line overrides go in `elevenlabs`; `speed` can also be supplied at the top
54
+ level. Omitted voice/rate settings inherit provider defaults through `Speak`,
55
+ `speak()` and `TTSNarrationComponent`. `TTS.init()` preserves the selected provider;
56
+ `TTS.configure()` explicitly restores the default Edge client.
57
+
58
+ ## Direct a natural explanation
59
+
60
+ Choose the emotional action of a beat: inviting a prediction, weighing a
61
+ possibility, making a discovery, or calmly resolving the explanation. Let the
62
+ voice express that action. A constant promotional excitement or a cue on every
63
+ sentence makes an explanation harder to follow. Keep the speaker recognizable
64
+ across beats, with a voice suited to the requested language and audience.
65
+
66
+ Write speech for listening: concrete questions, contractions, varied sentence
67
+ lengths, and emphasis on the relationship changing on screen. Read technical
68
+ symbols as intended speech; keep formulas and concise notation in the visuals.
69
+ Prefer phrase or paragraph performances to synthesizing isolated words, so the
70
+ model can carry an idea through to its conclusion. Split at genuine explanatory
71
+ boundaries, preserving neighboring context when needed.
72
+
73
+ Model-specific controls:
74
+
75
+ - On v3/v4, use occasional delivery tags such as `[curious]` or `[excited]` for
76
+ a meaningful change in delivery. These models do not support SSML break tags;
77
+ use punctuation and phrasing for vocal pauses. Test the chosen voice's delivery.
78
+ - On v2 models, use natural punctuation and supported SSML breaks sparingly.
79
+ Do not assume v3 audio tags work on v2 or Edge. Edge supports its own `pitch`
80
+ prosody; ElevenLabs rejects nonzero Edge pitch settings.
81
+ - Lower stability can increase variation; higher stability can reduce it.
82
+ Treat settings as voice/model-dependent. Adjust a short representative sample
83
+ after listening, rather than maximizing style or copying one preset everywhere.
84
+ - Supported speed is 0.7–1.2. Start close to the voice's natural pace and use
85
+ explicit scene holds for prediction time. A seed is best-effort, not guaranteed
86
+ repeatability; approved local audio provides repeatable rendering.
87
+
88
+ Keep performance directions out of captions. Supply clean `displayText` when
89
+ synthesis text contains delivery or pronunciation markup:
90
+
91
+ ```ts
92
+ import { Speak } from 'retiam/tts';
93
+
94
+ export function directedLine() {
95
+ return new Speak('[curious] What changes if we move this point?', {
96
+ displayText: 'What changes if we move this point?',
97
+ elevenlabs: { modelId: 'eleven_v3', voiceSettings: { stability: 0.5 } },
98
+ });
99
+ }
100
+ ```
101
+
102
+ Listen for pronunciation, expression, unwanted vocalizations, rushed endings,
103
+ and pauses before approving a voice. Regenerate only the lines that need it.
104
+ Keep approved audio across visual revisions; settings alone cannot lock a
105
+ performance. Do not spend credits merely to test whether initialization works.
106
+ See the model-specific [ElevenLabs delivery guide](https://elevenlabs.io/docs/overview/capabilities/text-to-speech/best-practices)
107
+ when using an unfamiliar model or control.
108
+
109
+ ## Lessons and prepared speech
110
+
111
+ For ElevenLabs lessons set `narration.provider` to `elevenlabs`, set `voice` to
112
+ the chosen voice ID, and put model/delivery settings under `narration.elevenlabs`.
113
+ Keep each segment's `text` clean for captions and cue phrases. Optional
114
+ `speechText` contains the exact synthesis script, including delivery tags.
115
+ Keep actual prediction/reveal gaps in `pauseAfterMs`, separate from vocal rhythm.
116
+
117
+ `retiam lesson prepare` supports both native providers. For ElevenLabs the CLI
118
+ reads `ELEVENLABS_API_KEY` from its environment and passes it to provider.init().
119
+ The key does not go in the lesson JSON. It caches audio and word timings and
120
+ writes `lesson/prepared.json` plus `public/narration/*.mp3`. Reuse those assets
121
+ for subsequent preview and render. Changing delivery text or voice settings
122
+ invalidates the corresponding prepared speech. The runtime can also synthesize
123
+ using an initialized matching global provider or an explicit synthesis adapter.
124
+
125
+ ## Edge browser and renderer setup
126
+
127
+ Only Edge uses the existing Vite proxy. New projects already enable it. For an
128
+ older project, preserve other plugins and add `msEdgeTTSPlugin` from
129
+ `retiam/vite` on the server side. Its route is `/api/tts/msedge/synthesize` in
130
+ Vite development/preview and Retiam's renderer. Static hosts need that server
131
+ route or prepared audio. Never import the Vite plugin into scene code.
132
+
133
+ ## Timeline recipe
134
+
135
+ Use [NarratedMotion.ts](../examples/NarratedMotion.ts) as the executable
136
+ integration recipe, adapting its speech and visual action to the brief.
137
+
138
+ - Use `Speak` for simultaneous narration and motion. Set `entity` to an entity
139
+ already added to the scene, so playback uses that scene's audio bus.
140
+ - Call `prepareAudio()` before locking timings. Register the synthesis promise
141
+ in `this.composer.pendingTasks` before awaiting it. Do not register playback
142
+ promises or `this.play(...)`: those require timeline steps and would deadlock.
143
+ - Derive motion duration from prepared `Speak.duration`. Pass that duration to
144
+ `Concurrent` too, so its defaults do not rescale the narration.
145
+ - `await speak(this, text, options)` handles playback, subtitles, ducking and
146
+ scene pacing. For headless use, pre-synthesize the same text/options and
147
+ register only synthesis as pending work. The provider caches that result.
148
+ - `TTS.speak(...)` is a lower-level client facade; it does not pace the scene.
149
+ - Add `Subtitles` and pass it to the narration. Caption text uses the generated
150
+ audio's `text`; ElevenLabs character alignment is converted to word timings
151
+ for lesson cues. Missing timing metadata is not a license to guess cue times.
152
+ - `stream()` yields sentence-sized complete audio results, not transport byte
153
+ chunks. A directed line with `displayText` stays one performance.
154
+
155
+ ## Diagnose and verify
156
+
157
+ For ElevenLabs, check initialization, voice/model compatibility, API permissions,
158
+ quota/rate-limit errors, and network access. Errors surface without automatic
159
+ paid retries. After disposal the provider requires initialization again. For
160
+ Edge, a 404 means missing middleware/route; a 502 means upstream synthesis
161
+ failed. Inspect the actual error before changing providers.
162
+
163
+ Browser autoplay may require a user gesture; headless tools supply their own
164
+ autoplay flag. Verify that exported video contains non-silent audio, listen to
165
+ the performance, and check synchronization. A type check or visual snapshot
166
+ does not establish speech quality.
@@ -0,0 +1,25 @@
1
+ {
2
+ "version": 1,
3
+ "title": "Why does area grow so fast?",
4
+ "topic": "How a square's area changes when its side length doubles",
5
+ "audience": "Curious beginners",
6
+ "objective": "See why doubling both side lengths produces four unit squares.",
7
+ "style": "mathematical",
8
+ "narration": {"enabled": false, "provider": "msedge", "voice": "en-US-AndrewNeural", "speed": 1, "pitch": "+0Hz", "volume": 1},
9
+ "sources": [],
10
+ "claims": [{"id":"area-model","text":"A square of side two can be partitioned into four squares of side one.","sourceIds":[],"illustrative":true}],
11
+ "beats": [
12
+ {"id":"predict","goal":"Invite a prediction before exposing the area.","visibleChange":"Draw one unit square and mark its side length.","focus":"The original square","minDurationMs":4500,
13
+ "narration":[{"id":"question","text":"Here is one unit square. If we double its side length, what happens to its area?","pauseAfterMs":900}],
14
+ "cues":[{"id":"show","segment":"question"}]},
15
+ {"id":"grow","goal":"Separate a change in side length from a change in area.","visibleChange":"Expand the outline while retaining the original square.","focus":"Both sides grow","minDurationMs":5000,
16
+ "narration":[{"id":"expand","text":"Let's double both sides. The original square still fits in the corner. How much new space have we made?","pauseAfterMs":700}],
17
+ "cues":[{"id":"expand","segment":"expand"}]},
18
+ {"id":"count","goal":"Discover the four equal areas through decomposition.","visibleChange":"Reveal the three additional unit squares in sequence.","focus":"Four equal pieces","minDurationMs":5000,
19
+ "narration":[{"id":"reveal","text":"One here, another above, and one more in the corner. Together with our original square, that makes four."}],
20
+ "cues":[{"id":"reveal","segment":"reveal"}]},
21
+ {"id":"connect","goal":"Connect the construction to the general area relationship.","visibleChange":"Keep all four pieces visible and reveal the equation below them.","focus":"Side length and area","minDurationMs":4500,
22
+ "narration":[{"id":"insight","text":"Two times the side length gives four times the area. That's the square in side squared: two growing directions, multiplied together."}],
23
+ "cues":[{"id":"equation","segment":"insight"}]}
24
+ ]
25
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "automated": {},
3
+ "observations": [],
4
+ "requiredReview": ["Check factual claims and illustrative model assumptions.","Inspect the beginning, prediction pause, main mechanism, transition and conclusion.","Watch a short preview at normal speed to assess pacing and attention.","Verify the final audio track, captions and video dimensions."],
5
+ "status": "not-reviewed"
6
+ }
@@ -0,0 +1,92 @@
1
+ {
2
+ "mathematical": {
3
+ "name": "Dijkstra-style mathematical explainer",
4
+ "background": "#0A1020",
5
+ "ink": "#ECF0F5",
6
+ "muted": "#74869C",
7
+ "primary": "#6CD5FF",
8
+ "secondary": "#F7CF73",
9
+ "font": "roboto",
10
+ "strokeWidth": 0.035,
11
+ "rough": false,
12
+ "roughness": 0,
13
+ "fillStyle": "solid",
14
+ "motion": {
15
+ "drawMs": 1200,
16
+ "moveMs": 1400,
17
+ "holdMs": 700
18
+ },
19
+ "accents": [
20
+ "#65F0C4",
21
+ "#FF879F",
22
+ "#BA98FF",
23
+ "#55DDE0"
24
+ ]
25
+ },
26
+ "excalidraw": {
27
+ "name": "Excalidraw whiteboard",
28
+ "background": "#FFFDF7",
29
+ "ink": "#263238",
30
+ "muted": "#7B858C",
31
+ "primary": "#1971C2",
32
+ "secondary": "#D46B08",
33
+ "font": "excalifont",
34
+ "strokeWidth": 0.04,
35
+ "rough": true,
36
+ "roughness": 0.7,
37
+ "fillStyle": "hachure",
38
+ "motion": {
39
+ "drawMs": 1600,
40
+ "moveMs": 1500,
41
+ "holdMs": 900
42
+ },
43
+ "accents": [
44
+ "#1971C2",
45
+ "#D46B08"
46
+ ]
47
+ },
48
+ "minimal": {
49
+ "name": "Minimal vector",
50
+ "background": "#F8FAFC",
51
+ "ink": "#17212B",
52
+ "muted": "#68788A",
53
+ "primary": "#2563EB",
54
+ "secondary": "#C2410C",
55
+ "font": "roboto",
56
+ "strokeWidth": 0.025,
57
+ "rough": false,
58
+ "roughness": 0,
59
+ "fillStyle": "solid",
60
+ "motion": {
61
+ "drawMs": 900,
62
+ "moveMs": 1100,
63
+ "holdMs": 650
64
+ },
65
+ "accents": [
66
+ "#2563EB",
67
+ "#C2410C"
68
+ ]
69
+ },
70
+ "cinematic": {
71
+ "name": "Cinematic diagrams",
72
+ "background": "#080B18",
73
+ "ink": "#F4F1FF",
74
+ "muted": "#8290AA",
75
+ "primary": "#B79AFF",
76
+ "secondary": "#58E0CE",
77
+ "font": "roboto",
78
+ "strokeWidth": 0.04,
79
+ "rough": false,
80
+ "roughness": 0,
81
+ "fillStyle": "solid",
82
+ "motion": {
83
+ "drawMs": 1500,
84
+ "moveMs": 2000,
85
+ "holdMs": 1000
86
+ },
87
+ "accents": [
88
+ "#B79AFF",
89
+ "#58E0CE"
90
+ ]
91
+ }
92
+ }
@@ -0,0 +1,26 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import {copyLessonKit} from './lesson-project.js';
5
+
6
+ export const agentKitRoot = fileURLToPath(new URL('../agent/', import.meta.url));
7
+
8
+ /** Used only while creating an empty project or preparing a fresh template. */
9
+ export function copyAgentKit(directory, options = {}) {
10
+ const files = [];
11
+ for (const name of ['AGENTS.md', 'CLAUDE.md']) {
12
+ fs.copyFileSync(path.join(agentKitRoot, name), path.join(directory, name));
13
+ files.push(name);
14
+ }
15
+ const destination = path.join(directory, '.agents/skills/retiam');
16
+ fs.cpSync(path.join(agentKitRoot, 'skill'), destination, { recursive: true });
17
+ function collect(folder) {
18
+ for (const entry of fs.readdirSync(folder, { withFileTypes: true })) {
19
+ const location = path.join(folder, entry.name);
20
+ if (entry.isDirectory()) collect(location);
21
+ else files.push(path.relative(directory, location).split(path.sep).join('/'));
22
+ }
23
+ }
24
+ collect(destination);
25
+ return [...files,...copyLessonKit(directory,options)];
26
+ }