narrator support
This commit is contained in:
@@ -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()
|
||||
Reference in New Issue
Block a user