UNPKG

3.06 kBPlain TextView Raw
1import { SyntheticPlatformEmitter, CodedError } from '@unimodules/core';
2
3import { SpeechOptions, WebVoice, VoiceQuality } from './Speech.types';
4
5//https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisUtterance/text
6const MAX_SPEECH_INPUT_LENGTH = 32767;
7
8export default {
9 get name(): string {
10 return 'ExponentSpeech';
11 },
12 async speak(id: string, text: string, options: SpeechOptions): Promise<SpeechSynthesisUtterance> {
13 if (text.length > MAX_SPEECH_INPUT_LENGTH) {
14 throw new CodedError(
15 'ERR_SPEECH_INPUT_LENGTH',
16 'Speech input text is too long! Limit of input length is: ' + MAX_SPEECH_INPUT_LENGTH
17 );
18 }
19
20 const message = new SpeechSynthesisUtterance();
21
22 if (typeof options.rate === 'number') {
23 message.rate = options.rate;
24 }
25 if (typeof options.pitch === 'number') {
26 message.pitch = options.pitch;
27 }
28 if (typeof options.language === 'string') {
29 message.lang = options.language;
30 }
31 if (typeof options.volume === 'number') {
32 message.volume = options.volume;
33 }
34 if ('_voiceIndex' in options && options._voiceIndex != null) {
35 const voices = window.speechSynthesis.getVoices();
36 message.voice = voices[Math.min(voices.length - 1, Math.max(0, options._voiceIndex))];
37 }
38 if (typeof options.onResume === 'function') {
39 message.onresume = options.onResume;
40 }
41 if (typeof options.onMark === 'function') {
42 message.onmark = options.onMark;
43 }
44 if (typeof options.onBoundary === 'function') {
45 message.onboundary = options.onBoundary;
46 }
47
48 message.onstart = (nativeEvent: SpeechSynthesisEvent) => {
49 SyntheticPlatformEmitter.emit('Exponent.speakingStarted', { id, nativeEvent });
50 };
51 message.onend = (nativeEvent: SpeechSynthesisEvent) => {
52 SyntheticPlatformEmitter.emit('Exponent.speakingDone', { id, nativeEvent });
53 };
54 message.onpause = (nativeEvent: SpeechSynthesisEvent) => {
55 SyntheticPlatformEmitter.emit('Exponent.speakingStopped', { id, nativeEvent });
56 };
57 message.onerror = (nativeEvent: SpeechSynthesisErrorEvent) => {
58 SyntheticPlatformEmitter.emit('Exponent.speakingError', { id, nativeEvent });
59 };
60
61 message.text = text;
62
63 window.speechSynthesis.speak(message);
64
65 return message;
66 },
67 getVoices(): WebVoice[] {
68 const voices = window.speechSynthesis.getVoices();
69 return voices.map(voice => ({
70 identifier: voice.voiceURI,
71 quality: VoiceQuality.Default,
72 isDefault: voice.default,
73 language: voice.lang,
74 localService: voice.localService,
75 name: voice.name,
76 voiceURI: voice.voiceURI,
77 }));
78 },
79 async isSpeaking(): Promise<boolean> {
80 return window.speechSynthesis.speaking;
81 },
82 async stop(): Promise<void> {
83 return window.speechSynthesis.cancel();
84 },
85 async pause(): Promise<void> {
86 return window.speechSynthesis.pause();
87 },
88 async resume(): Promise<void> {
89 return window.speechSynthesis.resume();
90 },
91 maxSpeechInputLength: MAX_SPEECH_INPUT_LENGTH,
92};