Interactive Reader separates active document narration configuration from user-global reusable libraries.
| Scope | Location | Purpose |
|---|---|---|
| Book / Document | chapter.ireader.json (next to input file) |
Active narration settings, character cast, overrides, and policies for a specific document. |
| Global Lexicon | ~/.interactive_reader/lexicon.json |
Reusable pronunciation overrides shared across all books. |
| Global Roster | ~/.interactive_reader/characters.json |
Reusable library of character voice profiles. |
When you run ireader chapter.md, the CLI checks for chapter.ireader.json (or chapter.md.ireader.json) in the same directory. If present, it loads this configuration. Any modifications saved from the Desktop Studio are persisted here.
{
"version": 1,
"default_voice": {
"mode": "single",
"name": "am_fenrir"
},
"speed": 1.0,
"dialogue": {
"enabled": true,
"profiles": [
{
"character_id": "sarah",
"display_name": "Sarah",
"voice": {
"mode": "single",
"name": "af_sarah"
},
"aliases": ["Dr. Sarah", "Sarah Connor"],
"pause_before": 0.15,
"pause_after": 0.15
}
],
"overrides": [
{
"token_start": 42,
"token_end": 56,
"character_id": "sarah"
}
],
"not_dialogue": [
{
"token_start": 105,
"token_end": 112
}
]
},
"pronunciation": {
"rules": [
{
"term": "Enma",
"phonemes": "ˈɛnmə",
"scope": "book",
"case_sensitive": false,
"match_possessives": true
}
]
},
"technical": {
"code_mode": "structured",
"announce_language": true
},
"footnotes": {
"mode": "inline"
},
"adaptive": {
"enabled": false,
"look_ahead": 1
}
}default_voice: Voice specification for narration prose.speed: Default reader playback speed multiplier.dialogue: Dialogue attribution engine settings, character profiles active in this document, speaker overrides, and explicit non-dialogue ranges.pronunciation: Document-scoped phonetic pronunciation overrides.technical: Code-reading policy (literal,structured,concise, orskip).footnotes: Footnote narration policy (inline,end_of_block, orskip).adaptive: Priority look-ahead scheduling configuration.
Stored at ~/.interactive_reader/lexicon.json.
{
"version": 1,
"scope": "global",
"rules": [
{
"term": "Kokoro",
"phonemes": "kəʊkəroʊ",
"scope": "global",
"case_sensitive": false,
"match_possessives": true
}
]
}When resolving the pronunciation of any word token, Interactive Reader evaluates rules in the following deterministic order:
1. Book Rule (in document sidecar `chapter.ireader.json`)
↓
2. Legacy Embedded Global Rule (in sidecar `chapter.ireader.json`)
↓
3. User Global Rule (in `~/.interactive_reader/lexicon.json`)
↓
4. Baseline G2P (Misaki phonemizer)
A book-level rule always takes precedence over a global rule. When a book rule matches the same term as a global rule, the global rule is masked for that book. Removing the book rule unmasks the underlying global rule immediately.
Stored at ~/.interactive_reader/characters.json.
{
"version": 1,
"scope": "global",
"profiles": [
{
"character_id": "dr_watson",
"display_name": "Dr. John Watson",
"voice": {
"mode": "single",
"name": "bm_lewis"
},
"aliases": ["Watson", "the doctor"],
"pause_before": 0.1,
"pause_after": 0.1
}
]
}-
Dormant by Default: Characters saved in the global roster do not automatically participate in dialogue attribution for open books. This prevents accidental attribution collisions when different books feature characters with common names (e.g., "John" or "Mary").
-
Explicit Materialization ("Use in This Book"): When you click Use in This Book in the Studio or select a global character in Dialogue Review, a detached local snapshot is copied into
chapter.ireader.json. -
No Live Sync: After materialization, the book profile is independent. Edits made to the global roster later will not mutate existing book sidecars or trigger unwanted audio invalidation.
-
Identity vs. Recognition:
character_id: The canonical, immutable persisted identity across files.display_name&aliases: Text recognition strings used for matching within a book, not cross-book identity.
All persisted files (chapter.ireader.json, lexicon.json, characters.json) follow strict reliability safeguards:
- Atomic Writes: Writes are performed to temporary files (
.tmp/mkstemp) and committed via atomic rename (os.replace) with disk flushing (fsync). - Strict Validation: Malformed JSON or invalid schema envelopes are rejected without silent data truncation or corruption. If a global file is corrupted, the Studio disables global modifications with a clear warning while preserving book-local editing.
- SHA-256 Concurrency Protection: Multi-window edits verify file hashes prior to write. Non-conflicting edits to distinct entries are merged safely, while conflicting edits to the same character or rule trigger collision notices.