narrator support

This commit is contained in:
2025-12-29 13:29:39 +02:00
parent 2a977ddec4
commit 39664b0c88
2 changed files with 214 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
export interface NarratorSettings {
enabled: boolean
rate: number
pitch: number
voice: string
verbosity: 'brief' | 'normal' | 'verbose'
sounds: boolean
}
export const defaultNarratorSettings: NarratorSettings = {
enabled: false,
rate: 1.0,
pitch: 1.0,
voice: '',
verbosity: 'normal',
sounds: true,
}
let settings: NarratorSettings = { ...defaultNarratorSettings }
export function updateSettings(s: NarratorSettings) {
settings = s
}
export function isSupported(): boolean {
return 'speechSynthesis' in window
}
export function getVoices(): SpeechSynthesisVoice[] {
if (!isSupported()) return []
return window.speechSynthesis.getVoices()
}
export function cancel() {
if (!isSupported()) return
window.speechSynthesis.cancel()
}
export function speak(text: string, interrupt = true) {
if (!isSupported() || !settings.enabled) return
if (interrupt) cancel()
const utterance = new SpeechSynthesisUtterance(text)
utterance.rate = settings.rate
utterance.pitch = settings.pitch
if (settings.voice) {
const voices = getVoices()
const match = voices.find(v => v.name === settings.voice)
if (match) utterance.voice = match
}
window.speechSynthesis.speak(utterance)
}
// voices load async - call this early so they're ready
export function preloadVoices() {
if (!isSupported()) return
getVoices()
if (window.speechSynthesis.onvoiceschanged !== undefined) {
window.speechSynthesis.onvoiceschanged = () => {}
}
}
preloadVoices()