Add ink integration UI and media playback

This commit is contained in:
2026-05-15 21:23:46 +02:00
parent 44dc64f830
commit f2e786d5bc
89 changed files with 6561 additions and 556 deletions
+18 -21
View File
@@ -62,7 +62,7 @@ Major modules:
- `module-registry.js`, `base-module.js`, `loader.js`: module lifecycle, dependency graph, progress overlay, state reporting.
- `text-processor-module.js`, `paragraph-layout-module.js`, `layout-renderer-module.js`: SmartyPants, language-aware hyphenation, Knuth-Plass line breaking, DOM rendering.
- `markup-parser-module.js`: story markup for chapters, sections, Markdown emphasis, images, SFX, and music.
- `markup-parser-module.js`: story markup fallback for chapters, sections, Markdown emphasis, images, SFX, and music.
- `sentence-queue-module.js`, `playback-coordinator-module.js`, `animation-queue-module.js`: sentence preparation, synchronized playback, timing, fast-forward.
- `tts-factory-module.js` plus provider modules: TTS provider selection, voice settings, speed mapping, caching, and playback.
- `audio-manager-module.js`: master, speech, music, and sound effect volume, music playback, sound effects, and music ducking.
@@ -82,10 +82,12 @@ Inline Markdown emphasis:
***bold italic*** or ___bold italic___
```
Canonical block/media tags use Ink-style `#` syntax. In Ink these are real Ink tags. In YAML and Zork narrative output, leading `#...` lines are parsed by the server into the same structured `StoryTag` objects before reaching the client. The browser only consumes structured `TurnResult` objects.
Chapter:
```text
::chapter[The Mysterious Mansion]
#chapter[The Mysterious Mansion]
The first paragraph uses a drop cap and no first-line indent.
@@ -97,51 +99,46 @@ The heading is centered, italic, and uses the same text face as the body. The fi
Section or text block:
```text
::section
#section
The first paragraph starts a separated block without horizontal indent.
The following paragraph returns to the normal indent.
```
`::textblock` is treated the same way. The first paragraph after the marker is separated from previous content by one line of vertical space.
`#textblock` is treated the same way. The first paragraph after the marker is separated from previous content by one line of vertical space.
Images are parsed for future rendering:
```text
::image[widescreen](mansion-rain.jpg)
::image[portrait](portrait-letter.jpg)
#image[mansion-rain.jpg](landscape)
#image[portrait-letter.jpg](portrait pause=2)
```
Image file names are relative to `public/images/`. `widescreen` means 100% page width and 50% page height. `portrait` means 100% page width and 100% page height.
Image file names are relative to `public/images/`. `widescreen` is accepted as an alias for `landscape`.
Sound effects can be placed inline:
Sound effects are story tags:
```text
The door opens {{sfx:squeaky-door.ogg}} and the hall exhales.
#sfx[squeaky-door.ogg]
The door opens and the hall exhales.
```
The marker is removed from display text and TTS text. It becomes a timed media cue that fires when the text animation reaches that point. Sound effect paths are relative to `public/sounds/`.
The tag is parsed by the server into a `StoryTag` object. Sound effect paths are relative to `public/sounds/`.
Music can be placed as a block:
```text
::music[crossfade, loop, lead=4](rain-theme.ogg)
#music[rain-theme.ogg](crossfade, loop, lead=4)
```
Music can also be placed inline:
```text
The candles gutter. {{music:cut:danger.ogg}} Something moves upstairs.
```
Music paths are relative to `public/music/`. Supported modes are `queue`, `crossfade`, and `cut`. Use `loop` or `once` to control repetition. `lead=<seconds>` delays the following text/TTS paragraph so the music can play alone before narration continues.
Music paths are relative to `public/music/`. Supported modes are `queue`, `crossfade`, and `cut`. Use `loop` or `once` to control repetition. `lead=<seconds>` delays the following text/TTS paragraph so the music can play alone before narration continues. To place that pause between a chapter heading and the dropcapped first paragraph, put the music tag after the chapter tag and before the first prose paragraph; TTS generation for the next spoken paragraph continues during the lead pause.
## Assets
- `public/sounds/`: sound effects referenced by `{{sfx:file}}`.
- `public/music/`: background music referenced by `::music[...]` or `{{music:mode:file}}`.
- `public/images/`: story images referenced by `::image[...]`.
- `public/sounds/`: sound effects referenced by `#sfx[file]` tags.
- `public/music/`: background music referenced by `#music[file](...)` tags.
- `public/images/`: story images referenced by `#image[file](...)`.
- `public/fonts/`: font assets used by the book UI.
Keep third-party assets licensed for local redistribution, and document source and license in the folder README or alongside the file.