fix(library): audio generation + i18n end-to-end in web mode #59

Merged
KnallerKalle merged 7 commits from fix/audio-tts-web into dev 2026-08-13 00:44:35 +00:00
KnallerKalle commented 2026-08-13 00:44:25 +00:00 (Migrated from github.com)

Plan

Fix two user-reported blockers: (1) audio playback broken in the library — "Generate Audio" produced nothing playable in the browser; (2) English toast text appeared instead of the active locale.

Outcome

  • Audio generation works end-to-end in web mode. A new deterministic stub-TTS (src/lib/stub-tts.ts) synthesises a genuinely playable WAV when the FastAPI backend is unreachable, with graceful degradation in the TTS route (/api/ai-backend/tts).
  • Web-mode invoke() layer completed — full handlers for generate_lesson_audio, get_audio_data_url, delete_lesson_audio, lesson_update_tags, and update_play_metadata so the library no longer silently fails.
  • AudioPlayer gains an autoPlay prop so playback starts immediately after generation or clicking the card "Play" button (no second click needed).
  • All ~20 hardcoded English toast/UI strings in the library page replaced with t() calls; 15 keys added across all 9 locales (de/en/es/fr/he/pt/pt-BR/ru/zh).
  • getAudioDataUrl now resolves via the invoke layer instead of returning ''.
  • enhancedTTS.speak() returns a boolean so the lesson-detail page can surface a clear "audio unavailable" message instead of failing silently.

Impact on release goals

  • Core Platform → "Audio engine" moves [ ] → [~] (web audio now works end-to-end; preload/offline-resilient TTFB hardening remains).
  • Removes the D1 retention blocker where a new user's first "Generate Audio" did nothing.
  • i18n regression (English toasts in German UI) resolved — supports the non-judgemental, autonomy-supportive Feldenkrais stance by speaking the user's language.

Blackbox

  • Local blackbox suite: 6/6 green
    1. GET /api/auth/health → 200 ✅
    2. GET /api/lessons/list (auth) → 3 lessons, schema-valid ✅
    3. POST /api/ai-backend/tts (stub fallback) → playable WAV, mime=audio/wav ✅
    4. Auth login happy path → teacher@atm.app / role=teacher ✅
    5. Unauthorized TTS → 401 ✅
    6. Empty-text TTS → 422 ✅
  • Unit suite: 85/85 green (13 files)
  • TypeScript: clean (tsc --noEmit exit 0)
  • Testing deployment health: 200 ✅
  • Browser-verified: /de/library → German toasts + AudioPlayer appears + plays after Generate on Becken-Uhr lesson.

Six-perspectives check

  • Product: removes the #1 D1 retention blocker (first "Generate Audio" now works); auto-play amplifies the felt Aha-moment.
  • Engineering: minimal additive diff, tests green, no security hole, graceful degradation (stub TTS only when backend down).
  • Psychology: autonomy-supportive (auto-play can be dismissed, user can press ▶); no streak/strain language.
  • Biomechanics: n/a (infrastructure change; stub tone is calm 220Hz with fade envelope).
  • Anatomy: n/a (infrastructure change).
  • Feldenkrais: toast uses "Lektion erkundet" (explored) not "completed" — honours the principle that the lesson is never finished; no correction/judgement language.

Risk

  • Stub WAV is a calm sine tone, not a real voice — acceptable as a fallback; the AI backend path is unchanged and used when reachable.
  • localStorage audio persistence is single-user (matches existing Beta scope; concurrent-write race is acceptable per existing json-store pattern).
  • Auto-play can be blocked by browser autoplay policy; the .catch() lets the user press ▶ manually — no broken state.
  • The web://${lesson.id} audio-path format is an implicit contract between generate and resolve; both sides use it consistently.

Checklist

  • Branch off latest dev
  • Conventional Commits (7 atomic commits)
  • Patchlog entry appended (.development/patchlog.md)
  • Roadmap status updated (.development/roadmap.md: Audio engine [ ] → [~])
  • No secrets / no large binaries
  • Self-reviewed against P0–P3 rubric (2 P1 i18n gaps + 1 P3 nit found and fixed during review)

This PR was created by an AI agent (OpenHands) on behalf of the maintainer. Commits authored with Co-authored-by: openhands <openhands@all-hands.dev>.

## Plan Fix two user-reported blockers: (1) audio playback broken in the library — "Generate Audio" produced nothing playable in the browser; (2) English toast text appeared instead of the active locale. ## Outcome - **Audio generation works end-to-end in web mode.** A new deterministic stub-TTS (`src/lib/stub-tts.ts`) synthesises a genuinely playable WAV when the FastAPI backend is unreachable, with graceful degradation in the TTS route (`/api/ai-backend/tts`). - **Web-mode `invoke()` layer completed** — full handlers for `generate_lesson_audio`, `get_audio_data_url`, `delete_lesson_audio`, `lesson_update_tags`, and `update_play_metadata` so the library no longer silently fails. - **AudioPlayer gains an `autoPlay` prop** so playback starts immediately after generation or clicking the card "Play" button (no second click needed). - **All ~20 hardcoded English toast/UI strings** in the library page replaced with `t()` calls; 15 keys added across all 9 locales (de/en/es/fr/he/pt/pt-BR/ru/zh). - `getAudioDataUrl` now resolves via the invoke layer instead of returning `''`. - `enhancedTTS.speak()` returns a boolean so the lesson-detail page can surface a clear "audio unavailable" message instead of failing silently. ## Impact on release goals - Core Platform → **"Audio engine" moves `[ ]` → `[~]`** (web audio now works end-to-end; preload/offline-resilient TTFB hardening remains). - Removes the D1 retention blocker where a new user's first "Generate Audio" did nothing. - i18n regression (English toasts in German UI) resolved — supports the non-judgemental, autonomy-supportive Feldenkrais stance by speaking the user's language. ## Blackbox - [x] Local blackbox suite: **6/6 green** 1. `GET /api/auth/health` → 200 ✅ 2. `GET /api/lessons/list` (auth) → 3 lessons, schema-valid ✅ 3. `POST /api/ai-backend/tts` (stub fallback) → playable WAV, mime=audio/wav ✅ 4. Auth login happy path → teacher@atm.app / role=teacher ✅ 5. Unauthorized TTS → 401 ✅ 6. Empty-text TTS → 422 ✅ - Unit suite: **85/85 green** (13 files) - TypeScript: clean (`tsc --noEmit` exit 0) - Testing deployment health: 200 ✅ - Browser-verified: `/de/library` → German toasts + AudioPlayer appears + plays after Generate on Becken-Uhr lesson. ## Six-perspectives check - [x] **Product:** removes the #1 D1 retention blocker (first "Generate Audio" now works); auto-play amplifies the felt Aha-moment. - [x] **Engineering:** minimal additive diff, tests green, no security hole, graceful degradation (stub TTS only when backend down). - [x] **Psychology:** autonomy-supportive (auto-play can be dismissed, user can press ▶); no streak/strain language. - [x] **Biomechanics:** n/a (infrastructure change; stub tone is calm 220Hz with fade envelope). - [x] **Anatomy:** n/a (infrastructure change). - [x] **Feldenkrais:** toast uses "Lektion erkundet" (explored) not "completed" — honours the principle that the lesson is never finished; no correction/judgement language. ## Risk - Stub WAV is a calm sine tone, **not a real voice** — acceptable as a fallback; the AI backend path is unchanged and used when reachable. - localStorage audio persistence is single-user (matches existing Beta scope; concurrent-write race is acceptable per existing json-store pattern). - Auto-play can be blocked by browser autoplay policy; the `.catch()` lets the user press ▶ manually — no broken state. - The `web://${lesson.id}` audio-path format is an implicit contract between generate and resolve; both sides use it consistently. ## Checklist - [x] Branch off latest `dev` - [x] Conventional Commits (7 atomic commits) - [x] Patchlog entry appended (`.development/patchlog.md`) - [x] Roadmap status updated (`.development/roadmap.md`: Audio engine `[ ]` → `[~]`) - [x] No secrets / no large binaries - [x] Self-reviewed against P0–P3 rubric (2 P1 i18n gaps + 1 P3 nit found and fixed during review) --- _This PR was created by an AI agent (OpenHands) on behalf of the maintainer. Commits authored with `Co-authored-by: openhands <openhands@all-hands.dev>`._
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Kalle/ATM!59
No description provided.