Add Piper TTS audio integration for vocabulary words
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 28s
CI / test-go-edu-search (push) Successful in 32s
CI / test-python-klausur (push) Failing after 2m24s
CI / test-python-agent-core (push) Successful in 24s
CI / test-nodejs-website (push) Successful in 26s
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 28s
CI / test-go-edu-search (push) Successful in 32s
CI / test-python-klausur (push) Failing after 2m24s
CI / test-python-agent-core (push) Successful in 24s
CI / test-nodejs-website (push) Successful in 26s
audio_service.py: Connects to compliance-tts-service (Piper TTS,
MIT license) for high-quality German (Thorsten) and English (Lessac)
voices. Audio cached as MP3 on first request.
vocabulary_api.py: New endpoints:
- GET /vocabulary/word/{id}/audio/{lang} — word pronunciation
- GET /vocabulary/word/{id}/audio-syllables/{lang} — slow syllable-by-syllable
Anton App analysis: identified 5 features to adopt (star system,
games as rewards, progress bars, listening exercises, matching exercises).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -99,6 +99,68 @@ async def api_get_filters():
|
||||
}
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Audio TTS for Words
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@router.get("/word/{word_id}/audio/{lang}")
|
||||
async def api_get_word_audio(word_id: str, lang: str = "en"):
|
||||
"""Get or generate TTS audio for a vocabulary word.
|
||||
|
||||
Returns MP3 audio. Generated on first request, cached after.
|
||||
Uses Piper TTS (MIT license) with Thorsten (DE) and Lessac (EN) voices.
|
||||
"""
|
||||
from fastapi.responses import Response as FastAPIResponse
|
||||
|
||||
word = await get_word(word_id)
|
||||
if not word:
|
||||
raise HTTPException(status_code=404, detail="Wort nicht gefunden")
|
||||
|
||||
text = word.english if lang == "en" else word.german
|
||||
if not text:
|
||||
raise HTTPException(status_code=400, detail=f"Kein Text fuer Sprache '{lang}'")
|
||||
|
||||
from audio_service import get_or_generate_audio
|
||||
audio_bytes = await get_or_generate_audio(text, language=lang, word_id=word_id)
|
||||
|
||||
if not audio_bytes:
|
||||
raise HTTPException(status_code=503, detail="TTS Service nicht verfuegbar")
|
||||
|
||||
return FastAPIResponse(content=audio_bytes, media_type="audio/mpeg")
|
||||
|
||||
|
||||
@router.get("/word/{word_id}/audio-syllables/{lang}")
|
||||
async def api_get_syllable_audio(word_id: str, lang: str = "en"):
|
||||
"""Get TTS audio with slow syllable pronunciation.
|
||||
|
||||
Generates audio like "ap ... ple" with pauses between syllables.
|
||||
"""
|
||||
from fastapi.responses import Response as FastAPIResponse
|
||||
|
||||
word = await get_word(word_id)
|
||||
if not word:
|
||||
raise HTTPException(status_code=404, detail="Wort nicht gefunden")
|
||||
|
||||
syllables = word.syllables_en if lang == "en" else word.syllables_de
|
||||
if not syllables:
|
||||
# Fallback to full word
|
||||
text = word.english if lang == "en" else word.german
|
||||
syllables = [text]
|
||||
|
||||
# Join syllables with pauses (Piper handles "..." as pause)
|
||||
slow_text = " ... ".join(syllables)
|
||||
|
||||
from audio_service import get_or_generate_audio
|
||||
cache_key = f"{word_id}_syl_{lang}"
|
||||
audio_bytes = await get_or_generate_audio(slow_text, language=lang, word_id=cache_key)
|
||||
|
||||
if not audio_bytes:
|
||||
raise HTTPException(status_code=503, detail="TTS Service nicht verfuegbar")
|
||||
|
||||
return FastAPIResponse(content=audio_bytes, media_type="audio/mpeg")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Learning Unit Creation from Word Selection
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user