feat: echte Pair-Audios statt TTS, Klick auf Satz spielt Audio (preloaded)

- usePairAudio-Hook: preload beim Kachel-Mount, nur eine Stimme gleichzeitig
- PairSentenceCard: audio_url statt speechSynthesis (TTS nur noch Fallback)
- PairYesNoCard/PairWordCard: Frage klickbar + Speaker-Button (vorher kein Audio)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 21:49:21 +02:00
parent e7dbb9d0a7
commit acfd57ee87
5 changed files with 102 additions and 20 deletions

42
src/hooks/usePairAudio.js Normal file
View File

@@ -0,0 +1,42 @@
import { useEffect, useRef, useState } from 'react'
// Nur eine Stimme gleichzeitig im Feed
let currentAudio = null
export default function usePairAudio(url) {
const audioRef = useRef(null)
const [playing, setPlaying] = useState(false)
useEffect(() => {
if (!url) { audioRef.current = null; return }
const audio = new Audio(url)
audio.preload = 'auto'
const onPlay = () => setPlaying(true)
const onStop = () => setPlaying(false)
audio.addEventListener('play', onPlay)
audio.addEventListener('pause', onStop)
audio.addEventListener('ended', onStop)
audioRef.current = audio
return () => {
audio.pause()
audio.removeEventListener('play', onPlay)
audio.removeEventListener('pause', onStop)
audio.removeEventListener('ended', onStop)
if (currentAudio === audio) currentAudio = null
audio.src = ''
audioRef.current = null
}
}, [url])
function play() {
const audio = audioRef.current
if (!audio) return false
if (currentAudio && currentAudio !== audio) currentAudio.pause()
currentAudio = audio
audio.currentTime = 0
audio.play().catch(() => {})
return true
}
return { play, playing }
}