# Narration Guide

Status: v0.1 live explanatory layer

## Purpose

The voice guide turns the simulation into a narrated instrument. It explains the current view, the active scenario, live model readouts, and the current Complex I path bottleneck.

The guide is generated from app state rather than a fixed audio file, so narration tracks:

- zoom scale
- active preset or custom state
- PMF, P/O, ROS hazard
- Complex I path-kinetics bottleneck
- comparative and long-edge caveats

## Modes

Current view:

```text
Explain the live viewport and current model state.
```

Tour:

```text
Move through cell, organelle, membrane, protein, tunneling, aging, and cancer-context views.
```

The tour intentionally changes zoom and preset state so the visual field and spoken explanation stay synchronized.

## Visual Focus

Each narration step produces a focus object:

```text
layer
target
cue
visualKey
```

The Guide tab displays the focus object as a compact readout, and the canvas uses `visualKey` to draw a pulsing callout around the cell transfer region, crista field, membrane chain, Complex I cofactor path, tunneling wells, or stress-pressure regions.

## Speech Layer

The app uses the browser Web Speech API:

```text
speechSynthesis
SpeechSynthesisUtterance
```

If browser speech is blocked or unavailable, the Guide tab still displays the transcript.

The voice selector prefers installed English voices in this order:

```text
en-GB
en-IE
en-AU
other English fallback
```

The playback profile is intentionally calm:

```text
rate 0.88
pitch 1.03
```

The Guide tab displays the selected voice so reviewers can see whether the browser provided a UK English voice or fell back to another local voice.

Browser fallback uses a separate speech string from the visible transcript. The transcript keeps the scientific terms, while the spoken string patches terms that local browser voices often mangle:

```text
mitochondria -> mito chon dria
mitochondrial -> mito chon drial
cardiolipin -> cardio li pin
cristae -> KRIS-tee
```

It also softens sentence cadence by replacing many hard full stops with semicolon pauses for browser speech. This reduces the pitch drop that some built-in voices put at the end of every sentence.

## Installed Natural Voice

The ElevenLabs path is an installed server feature, not a browser setup task:

```text
cp .env.local.example .env.local
python3 scripts/voice_proxy.py
```

Add the API key and voice ID to `.env.local`:

```text
ELEVENLABS_API_KEY=...
ELEVENLABS_VOICE_ID=
ELEVENLABS_AUTO_VOICE=true
ELEVENLABS_PREFERRED_ACCENT=british
ELEVENLABS_PREFERRED_USE=narration
```

Then open the app through the local server:

```text
http://127.0.0.1:8787/
```

The browser calls the same-origin proxy:

```text
POST /tts
```

The proxy calls ElevenLabs:

```text
POST https://api.elevenlabs.io/v1/text-to-speech/:voice_id
```

Reference: `https://elevenlabs.io/docs/api-reference/text-to-speech`

The current proxy uses:

```text
model_id: eleven_multilingual_v2
output_format: mp3_44100_128
```

If `ELEVENLABS_VOICE_ID` is blank and `ELEVENLABS_AUTO_VOICE=true`, the proxy queries the local account's ElevenLabs voices and scores them toward British, narration, audiobook, documentary, calm, warm, and professional labels.

The proxy also applies natural-voice pronunciation aliases before sending text to ElevenLabs:

```text
mitochondria -> mito chon dria
mitochondrial -> mito chon drial
cardiolipin -> cardio li pin
```

The API key stays in `.env.local` locally or in Railway service variables in production. The public UI does not expose API-key or voice-ID fields. Server voice transmits narration text to ElevenLabs; browser speech remains an emergency fallback if the proxy is not running or the request fails.

## HTTPS Voice Deployment

For sharing outside this machine, serve the app through HTTPS and keep the ElevenLabs key on the server. The intended production shape is:

```text
Browser over HTTPS -> same-origin /tts -> server-side ElevenLabs request
```

The local proxy can also run its own TLS listener for testing:

```text
MQF_SCHEME=https
MQF_SSL_CERT=.certs/localhost.pem
MQF_SSL_KEY=.certs/localhost-key.pem
python3 scripts/voice_proxy.py
```

Production deployments usually terminate HTTPS at the hosting platform, load balancer, or reverse proxy. In that case the app server can keep `MQF_SCHEME=http` internally while the public address remains `https://...`.

## Claim Boundary

The narration follows the same standard as the visual model:

- no long-lived quantum coherence claim
- quantum means thermally assisted electron tunneling and hopping
- cancer is treated as heterogeneous and context-dependent
- aging is treated as dysregulated environment, not one universal decline
- structure-derived path kinetics remain review-required where labels are inferred
