@capacitor-community/text-to-speech 4.1.1 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -9
- package/android/src/main/java/com/getcapacitor/community/tts/SpeakResultCallback.java +1 -1
- package/android/src/main/java/com/getcapacitor/community/tts/TextToSpeech.java +54 -25
- package/android/src/main/java/com/getcapacitor/community/tts/TextToSpeechPlugin.java +5 -2
- package/dist/docs.json +38 -1
- package/dist/esm/definitions.d.ts +17 -0
- package/dist/esm/definitions.js +11 -1
- package/dist/esm/definitions.js.map +1 -1
- package/dist/plugin.cjs.js +12 -0
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +12 -0
- package/dist/plugin.js.map +1 -1
- package/ios/Plugin/TextToSpeech.swift +12 -9
- package/ios/Plugin/TextToSpeechPlugin.swift +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -51,6 +51,7 @@ const speak = async () => {
|
|
|
51
51
|
pitch: 1.0,
|
|
52
52
|
volume: 1.0,
|
|
53
53
|
category: 'ambient',
|
|
54
|
+
queueStrategy: 1
|
|
54
55
|
});
|
|
55
56
|
};
|
|
56
57
|
|
|
@@ -83,6 +84,7 @@ const isLanguageSupported = async (lang: string) => {
|
|
|
83
84
|
* [`openInstall()`](#openinstall)
|
|
84
85
|
* [`addListener('onRangeStart', ...)`](#addlisteneronrangestart)
|
|
85
86
|
* [Interfaces](#interfaces)
|
|
87
|
+
* [Enums](#enums)
|
|
86
88
|
|
|
87
89
|
</docgen-index>
|
|
88
90
|
|
|
@@ -192,15 +194,16 @@ addListener(eventName: 'onRangeStart', listenerFunc: (info: { start: number; end
|
|
|
192
194
|
|
|
193
195
|
#### TTSOptions
|
|
194
196
|
|
|
195
|
-
| Prop
|
|
196
|
-
|
|
|
197
|
-
| **`text`**
|
|
198
|
-
| **`lang`**
|
|
199
|
-
| **`rate`**
|
|
200
|
-
| **`pitch`**
|
|
201
|
-
| **`volume`**
|
|
202
|
-
| **`voice`**
|
|
203
|
-
| **`category`**
|
|
197
|
+
| Prop | Type | Description | Default | Since |
|
|
198
|
+
| ------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------- | ----- |
|
|
199
|
+
| **`text`** | <code>string</code> | The text that will be synthesised when the utterance is spoken. | | |
|
|
200
|
+
| **`lang`** | <code>string</code> | The language of the utterance. Possible languages can be queried using `getSupportedLanguages`. | <code>"en-US"</code> | |
|
|
201
|
+
| **`rate`** | <code>number</code> | The speed at which the utterance will be spoken at. | <code>1.0</code> | |
|
|
202
|
+
| **`pitch`** | <code>number</code> | The pitch at which the utterance will be spoken at. | <code>1.0</code> | |
|
|
203
|
+
| **`volume`** | <code>number</code> | The volume that the utterance will be spoken at. | <code>1.0</code> | |
|
|
204
|
+
| **`voice`** | <code>number</code> | The index of the selected voice that will be used to speak the utterance. Possible voices can be queried using `getSupportedVoices`. | | |
|
|
205
|
+
| **`category`** | <code>string</code> | Select the iOS Audio session category. Possible values: `ambient` and `playback`. Use `playback` to play audio even when the app is in the background. Only available for iOS. | <code>"ambient"</code> | |
|
|
206
|
+
| **`queueStrategy`** | <code><a href="#queuestrategy">QueueStrategy</a></code> | Select the strategy to adopt when several requests to speak overlap. | <code>QueueStrategy.Flush</code> | 5.1.0 |
|
|
204
207
|
|
|
205
208
|
|
|
206
209
|
#### SpeechSynthesisVoice
|
|
@@ -222,6 +225,17 @@ The <a href="#speechsynthesisvoice">SpeechSynthesisVoice</a> interface represent
|
|
|
222
225
|
| ------------ | ----------------------------------------- |
|
|
223
226
|
| **`remove`** | <code>() => Promise<void></code> |
|
|
224
227
|
|
|
228
|
+
|
|
229
|
+
### Enums
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
#### QueueStrategy
|
|
233
|
+
|
|
234
|
+
| Members | Value | Description |
|
|
235
|
+
| ----------- | -------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
236
|
+
| **`Flush`** | <code>0</code> | Use `Flush` to stop the current request when a new request is sent. |
|
|
237
|
+
| **`Add`** | <code>1</code> | Use `Add` to buffer the speech request. The request will be executed when all previous requests have been completed. |
|
|
238
|
+
|
|
225
239
|
</docgen-api>
|
|
226
240
|
|
|
227
241
|
## Changelog
|
|
@@ -15,6 +15,7 @@ import java.util.ArrayList;
|
|
|
15
15
|
import java.util.Collections;
|
|
16
16
|
import java.util.HashMap;
|
|
17
17
|
import java.util.Locale;
|
|
18
|
+
import java.util.Map;
|
|
18
19
|
import java.util.Set;
|
|
19
20
|
|
|
20
21
|
public class TextToSpeech implements android.speech.tts.TextToSpeech.OnInitListener {
|
|
@@ -25,11 +26,44 @@ public class TextToSpeech implements android.speech.tts.TextToSpeech.OnInitListe
|
|
|
25
26
|
private android.speech.tts.TextToSpeech tts = null;
|
|
26
27
|
private int initializationStatus;
|
|
27
28
|
private JSObject[] supportedVoices = null;
|
|
29
|
+
private Map<String, SpeakResultCallback> requests = new HashMap();
|
|
28
30
|
|
|
29
31
|
TextToSpeech(Context context) {
|
|
30
32
|
this.context = context;
|
|
31
33
|
try {
|
|
32
34
|
tts = new android.speech.tts.TextToSpeech(context, this);
|
|
35
|
+
tts.setOnUtteranceProgressListener(
|
|
36
|
+
new UtteranceProgressListener() {
|
|
37
|
+
@Override
|
|
38
|
+
public void onStart(String utteranceId) {}
|
|
39
|
+
|
|
40
|
+
@Override
|
|
41
|
+
public void onDone(String utteranceId) {
|
|
42
|
+
SpeakResultCallback callback = requests.get(utteranceId);
|
|
43
|
+
if (callback != null) {
|
|
44
|
+
callback.onDone();
|
|
45
|
+
requests.remove(utteranceId);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@Override
|
|
50
|
+
public void onError(String utteranceId) {
|
|
51
|
+
SpeakResultCallback callback = requests.get(utteranceId);
|
|
52
|
+
if (callback != null) {
|
|
53
|
+
callback.onError();
|
|
54
|
+
requests.remove(utteranceId);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@Override
|
|
59
|
+
public void onRangeStart(String utteranceId, int start, int end, int frame) {
|
|
60
|
+
SpeakResultCallback callback = requests.get(utteranceId);
|
|
61
|
+
if (callback != null) {
|
|
62
|
+
callback.onRangeStart(start, end);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
);
|
|
33
67
|
} catch (Exception ex) {
|
|
34
68
|
Log.d(LOG_TAG, ex.getLocalizedMessage());
|
|
35
69
|
}
|
|
@@ -50,29 +84,24 @@ public class TextToSpeech implements android.speech.tts.TextToSpeech.OnInitListe
|
|
|
50
84
|
String callbackId,
|
|
51
85
|
SpeakResultCallback resultCallback
|
|
52
86
|
) {
|
|
53
|
-
tts.
|
|
54
|
-
|
|
55
|
-
new UtteranceProgressListener() {
|
|
56
|
-
@Override
|
|
57
|
-
public void onStart(String utteranceId) {}
|
|
58
|
-
|
|
59
|
-
@Override
|
|
60
|
-
public void onDone(String utteranceId) {
|
|
61
|
-
resultCallback.onDone();
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
@Override
|
|
65
|
-
public void onError(String utteranceId) {
|
|
66
|
-
resultCallback.onError();
|
|
67
|
-
}
|
|
87
|
+
speak(text, lang, rate, pitch, volume, voice, callbackId, resultCallback, android.speech.tts.TextToSpeech.QUEUE_FLUSH);
|
|
88
|
+
}
|
|
68
89
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
90
|
+
public void speak(
|
|
91
|
+
String text,
|
|
92
|
+
String lang,
|
|
93
|
+
float rate,
|
|
94
|
+
float pitch,
|
|
95
|
+
float volume,
|
|
96
|
+
int voice,
|
|
97
|
+
String callbackId,
|
|
98
|
+
SpeakResultCallback resultCallback,
|
|
99
|
+
int queueStrategy
|
|
100
|
+
) {
|
|
101
|
+
if (queueStrategy != android.speech.tts.TextToSpeech.QUEUE_ADD) {
|
|
102
|
+
stop();
|
|
103
|
+
}
|
|
104
|
+
requests.put(callbackId, resultCallback);
|
|
76
105
|
|
|
77
106
|
Locale locale = Locale.forLanguageTag(lang);
|
|
78
107
|
|
|
@@ -92,8 +121,7 @@ public class TextToSpeech implements android.speech.tts.TextToSpeech.OnInitListe
|
|
|
92
121
|
int resultCode = tts.setVoice(newVoice);
|
|
93
122
|
}
|
|
94
123
|
}
|
|
95
|
-
|
|
96
|
-
tts.speak(text, android.speech.tts.TextToSpeech.QUEUE_FLUSH, ttsParams, callbackId);
|
|
124
|
+
tts.speak(text, queueStrategy, ttsParams, callbackId);
|
|
97
125
|
} else {
|
|
98
126
|
HashMap<String, String> ttsParams = new HashMap<>();
|
|
99
127
|
ttsParams.put(android.speech.tts.TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, callbackId);
|
|
@@ -102,12 +130,13 @@ public class TextToSpeech implements android.speech.tts.TextToSpeech.OnInitListe
|
|
|
102
130
|
tts.setLanguage(locale);
|
|
103
131
|
tts.setSpeechRate(rate);
|
|
104
132
|
tts.setPitch(pitch);
|
|
105
|
-
tts.speak(text,
|
|
133
|
+
tts.speak(text, queueStrategy, ttsParams);
|
|
106
134
|
}
|
|
107
135
|
}
|
|
108
136
|
|
|
109
137
|
public void stop() {
|
|
110
138
|
tts.stop();
|
|
139
|
+
requests.clear();
|
|
111
140
|
}
|
|
112
141
|
|
|
113
142
|
public JSArray getSupportedLanguages() {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package com.getcapacitor.community.tts;
|
|
2
2
|
|
|
3
3
|
import android.util.Base64;
|
|
4
|
+
import android.util.Log;
|
|
4
5
|
import com.getcapacitor.JSArray;
|
|
5
6
|
import com.getcapacitor.JSObject;
|
|
6
7
|
import com.getcapacitor.Plugin;
|
|
@@ -37,6 +38,7 @@ public class TextToSpeechPlugin extends Plugin {
|
|
|
37
38
|
float pitch = call.getFloat("pitch", 1.0f);
|
|
38
39
|
float volume = call.getFloat("volume", 1.0f);
|
|
39
40
|
int voice = call.getInt("voice", -1);
|
|
41
|
+
int queueStrategy = call.getInt("queueStrategy", 0);
|
|
40
42
|
|
|
41
43
|
boolean isLanguageSupported = implementation.isLanguageSupported(lang);
|
|
42
44
|
if (!isLanguageSupported) {
|
|
@@ -56,17 +58,18 @@ public class TextToSpeechPlugin extends Plugin {
|
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
@Override
|
|
59
|
-
public void onRangeStart(int start, int end
|
|
61
|
+
public void onRangeStart(int start, int end) {
|
|
60
62
|
JSObject ret = new JSObject();
|
|
61
63
|
ret.put("start", start);
|
|
62
64
|
ret.put("end", end);
|
|
65
|
+
String spokenWord = text.substring(start, end);
|
|
63
66
|
ret.put("spokenWord", spokenWord);
|
|
64
67
|
notifyListeners("onRangeStart", ret);
|
|
65
68
|
}
|
|
66
69
|
};
|
|
67
70
|
|
|
68
71
|
try {
|
|
69
|
-
implementation.speak(text, lang, rate, pitch, volume, voice, call.getCallbackId(), resultCallback);
|
|
72
|
+
implementation.speak(text, lang, rate, pitch, volume, voice, call.getCallbackId(), resultCallback, queueStrategy);
|
|
70
73
|
} catch (Exception ex) {
|
|
71
74
|
call.reject(ex.getLocalizedMessage());
|
|
72
75
|
}
|
package/dist/docs.json
CHANGED
|
@@ -193,6 +193,24 @@
|
|
|
193
193
|
"docs": "Select the iOS Audio session category.\nPossible values: `ambient` and `playback`.\nUse `playback` to play audio even when the app is in the background.\n\nOnly available for iOS.",
|
|
194
194
|
"complexTypes": [],
|
|
195
195
|
"type": "string | undefined"
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"name": "queueStrategy",
|
|
199
|
+
"tags": [
|
|
200
|
+
{
|
|
201
|
+
"text": "5.1.0",
|
|
202
|
+
"name": "since"
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"text": "QueueStrategy.Flush",
|
|
206
|
+
"name": "default"
|
|
207
|
+
}
|
|
208
|
+
],
|
|
209
|
+
"docs": "Select the strategy to adopt when several requests to speak overlap.",
|
|
210
|
+
"complexTypes": [
|
|
211
|
+
"QueueStrategy"
|
|
212
|
+
],
|
|
213
|
+
"type": "QueueStrategy"
|
|
196
214
|
}
|
|
197
215
|
]
|
|
198
216
|
},
|
|
@@ -282,7 +300,26 @@
|
|
|
282
300
|
]
|
|
283
301
|
}
|
|
284
302
|
],
|
|
285
|
-
"enums": [
|
|
303
|
+
"enums": [
|
|
304
|
+
{
|
|
305
|
+
"name": "QueueStrategy",
|
|
306
|
+
"slug": "queuestrategy",
|
|
307
|
+
"members": [
|
|
308
|
+
{
|
|
309
|
+
"name": "Flush",
|
|
310
|
+
"value": "0",
|
|
311
|
+
"tags": [],
|
|
312
|
+
"docs": "Use `Flush` to stop the current request when a new request is sent."
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
"name": "Add",
|
|
316
|
+
"value": "1",
|
|
317
|
+
"tags": [],
|
|
318
|
+
"docs": "Use `Add` to buffer the speech request. The request will be executed when all previous requests have been completed."
|
|
319
|
+
}
|
|
320
|
+
]
|
|
321
|
+
}
|
|
322
|
+
],
|
|
286
323
|
"typeAliases": [],
|
|
287
324
|
"pluginConfigs": []
|
|
288
325
|
}
|
|
@@ -40,6 +40,16 @@ export interface TextToSpeechPlugin {
|
|
|
40
40
|
spokenWord: string;
|
|
41
41
|
}) => void): Promise<PluginListenerHandle>;
|
|
42
42
|
}
|
|
43
|
+
export declare enum QueueStrategy {
|
|
44
|
+
/**
|
|
45
|
+
* Use `Flush` to stop the current request when a new request is sent.
|
|
46
|
+
*/
|
|
47
|
+
Flush = 0,
|
|
48
|
+
/**
|
|
49
|
+
* Use `Add` to buffer the speech request. The request will be executed when all previous requests have been completed.
|
|
50
|
+
*/
|
|
51
|
+
Add = 1
|
|
52
|
+
}
|
|
43
53
|
export interface TTSOptions {
|
|
44
54
|
/**
|
|
45
55
|
* The text that will be synthesised when the utterance is spoken.
|
|
@@ -87,6 +97,13 @@ export interface TTSOptions {
|
|
|
87
97
|
* @default "ambient"
|
|
88
98
|
*/
|
|
89
99
|
category?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Select the strategy to adopt when several requests to speak overlap.
|
|
102
|
+
*
|
|
103
|
+
* @since 5.1.0
|
|
104
|
+
* @default QueueStrategy.Flush
|
|
105
|
+
*/
|
|
106
|
+
queueStrategy?: QueueStrategy;
|
|
90
107
|
}
|
|
91
108
|
/**
|
|
92
109
|
* The SpeechSynthesisVoice interface represents a voice that the system supports.
|
package/dist/esm/definitions.js
CHANGED
|
@@ -1,2 +1,12 @@
|
|
|
1
|
-
export
|
|
1
|
+
export var QueueStrategy;
|
|
2
|
+
(function (QueueStrategy) {
|
|
3
|
+
/**
|
|
4
|
+
* Use `Flush` to stop the current request when a new request is sent.
|
|
5
|
+
*/
|
|
6
|
+
QueueStrategy[QueueStrategy["Flush"] = 0] = "Flush";
|
|
7
|
+
/**
|
|
8
|
+
* Use `Add` to buffer the speech request. The request will be executed when all previous requests have been completed.
|
|
9
|
+
*/
|
|
10
|
+
QueueStrategy[QueueStrategy["Add"] = 1] = "Add";
|
|
11
|
+
})(QueueStrategy || (QueueStrategy = {}));
|
|
2
12
|
//# sourceMappingURL=definitions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\n\nexport interface TextToSpeechPlugin {\n /**\n * Starts the TTS engine and plays the desired text.\n */\n speak(options: TTSOptions): Promise<void>;\n /**\n * Stops the TTS engine.\n */\n stop(): Promise<void>;\n /**\n * Returns a list of supported BCP 47 language tags.\n */\n getSupportedLanguages(): Promise<{ languages: string[] }>;\n /**\n * Returns a list of supported voices.\n */\n getSupportedVoices(): Promise<{ voices: SpeechSynthesisVoice[] }>;\n /**\n * Checks if a specific BCP 47 language tag is supported.\n */\n isLanguageSupported(options: {\n lang: string;\n }): Promise<{ supported: boolean }>;\n /**\n * Verifies proper installation and availability of resource files on the system.\n *\n * Only available for Android.\n */\n openInstall(): Promise<void>;\n\n addListener(\n eventName: 'onRangeStart',\n listenerFunc: (info: {\n start: number;\n end: number;\n spokenWord: string;\n }) => void,\n ): Promise<PluginListenerHandle>;\n}\n\nexport interface TTSOptions {\n /**\n * The text that will be synthesised when the utterance is spoken.\n *\n * @example \"Hello world\"\n */\n text: string;\n /**\n * The language of the utterance.\n * Possible languages can be queried using `getSupportedLanguages`.\n *\n * @default \"en-US\"\n */\n lang?: string;\n /**\n * The speed at which the utterance will be spoken at.\n *\n * @default 1.0\n */\n rate?: number;\n /**\n * The pitch at which the utterance will be spoken at.\n *\n * @default 1.0\n */\n pitch?: number;\n /**\n * The volume that the utterance will be spoken at.\n *\n * @default 1.0\n */\n volume?: number;\n /**\n * The index of the selected voice that will be used to speak the utterance.\n * Possible voices can be queried using `getSupportedVoices`.\n */\n voice?: number;\n /**\n * Select the iOS Audio session category.\n * Possible values: `ambient` and `playback`.\n * Use `playback` to play audio even when the app is in the background.\n *\n * Only available for iOS.\n *\n * @default \"ambient\"\n */\n category?: string;\n}\n\n/**\n * The SpeechSynthesisVoice interface represents a voice that the system supports.\n */\nexport interface SpeechSynthesisVoice {\n /**\n * Specifies whether the voice is the default voice for the current app (`true`) or not (`false`).\n *\n * @example false\n */\n default: boolean;\n /**\n * BCP 47 language tag indicating the language of the voice.\n *\n * @example \"en-US\"\n */\n lang: string;\n /**\n * Specifies whether the voice is supplied by a local (`true`) or remote (`false`) speech synthesizer service.\n *\n * @example true\n */\n localService: boolean;\n /**\n * Human-readable name that represents the voice.\n *\n * @example \"Microsoft Zira Desktop - English (United States)\"\n */\n name: string;\n /**\n * Type of URI and location of the speech synthesis service for this voice.\n *\n * @example \"urn:moz-tts:sapi:Microsoft Zira Desktop - English (United States)?en-US\"\n */\n voiceURI: string;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AA0CA,MAAM,CAAN,IAAY,aASX;AATD,WAAY,aAAa;IACvB;;OAEG;IACH,mDAAS,CAAA;IACT;;OAEG;IACH,+CAAO,CAAA;AACT,CAAC,EATW,aAAa,KAAb,aAAa,QASxB","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\n\nexport interface TextToSpeechPlugin {\n /**\n * Starts the TTS engine and plays the desired text.\n */\n speak(options: TTSOptions): Promise<void>;\n /**\n * Stops the TTS engine.\n */\n stop(): Promise<void>;\n /**\n * Returns a list of supported BCP 47 language tags.\n */\n getSupportedLanguages(): Promise<{ languages: string[] }>;\n /**\n * Returns a list of supported voices.\n */\n getSupportedVoices(): Promise<{ voices: SpeechSynthesisVoice[] }>;\n /**\n * Checks if a specific BCP 47 language tag is supported.\n */\n isLanguageSupported(options: {\n lang: string;\n }): Promise<{ supported: boolean }>;\n /**\n * Verifies proper installation and availability of resource files on the system.\n *\n * Only available for Android.\n */\n openInstall(): Promise<void>;\n\n addListener(\n eventName: 'onRangeStart',\n listenerFunc: (info: {\n start: number;\n end: number;\n spokenWord: string;\n }) => void,\n ): Promise<PluginListenerHandle>;\n}\n\nexport enum QueueStrategy {\n /**\n * Use `Flush` to stop the current request when a new request is sent.\n */\n Flush = 0,\n /**\n * Use `Add` to buffer the speech request. The request will be executed when all previous requests have been completed.\n */\n Add = 1,\n}\n\nexport interface TTSOptions {\n /**\n * The text that will be synthesised when the utterance is spoken.\n *\n * @example \"Hello world\"\n */\n text: string;\n /**\n * The language of the utterance.\n * Possible languages can be queried using `getSupportedLanguages`.\n *\n * @default \"en-US\"\n */\n lang?: string;\n /**\n * The speed at which the utterance will be spoken at.\n *\n * @default 1.0\n */\n rate?: number;\n /**\n * The pitch at which the utterance will be spoken at.\n *\n * @default 1.0\n */\n pitch?: number;\n /**\n * The volume that the utterance will be spoken at.\n *\n * @default 1.0\n */\n volume?: number;\n /**\n * The index of the selected voice that will be used to speak the utterance.\n * Possible voices can be queried using `getSupportedVoices`.\n */\n voice?: number;\n /**\n * Select the iOS Audio session category.\n * Possible values: `ambient` and `playback`.\n * Use `playback` to play audio even when the app is in the background.\n *\n * Only available for iOS.\n *\n * @default \"ambient\"\n */\n category?: string;\n /**\n * Select the strategy to adopt when several requests to speak overlap.\n *\n * @since 5.1.0\n * @default QueueStrategy.Flush\n */\n queueStrategy?: QueueStrategy;\n}\n\n/**\n * The SpeechSynthesisVoice interface represents a voice that the system supports.\n */\nexport interface SpeechSynthesisVoice {\n /**\n * Specifies whether the voice is the default voice for the current app (`true`) or not (`false`).\n *\n * @example false\n */\n default: boolean;\n /**\n * BCP 47 language tag indicating the language of the voice.\n *\n * @example \"en-US\"\n */\n lang: string;\n /**\n * Specifies whether the voice is supplied by a local (`true`) or remote (`false`) speech synthesizer service.\n *\n * @example true\n */\n localService: boolean;\n /**\n * Human-readable name that represents the voice.\n *\n * @example \"Microsoft Zira Desktop - English (United States)\"\n */\n name: string;\n /**\n * Type of URI and location of the speech synthesis service for this voice.\n *\n * @example \"urn:moz-tts:sapi:Microsoft Zira Desktop - English (United States)?en-US\"\n */\n voiceURI: string;\n}\n"]}
|
package/dist/plugin.cjs.js
CHANGED
|
@@ -4,6 +4,18 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var core = require('@capacitor/core');
|
|
6
6
|
|
|
7
|
+
exports.QueueStrategy = void 0;
|
|
8
|
+
(function (QueueStrategy) {
|
|
9
|
+
/**
|
|
10
|
+
* Use `Flush` to stop the current request when a new request is sent.
|
|
11
|
+
*/
|
|
12
|
+
QueueStrategy[QueueStrategy["Flush"] = 0] = "Flush";
|
|
13
|
+
/**
|
|
14
|
+
* Use `Add` to buffer the speech request. The request will be executed when all previous requests have been completed.
|
|
15
|
+
*/
|
|
16
|
+
QueueStrategy[QueueStrategy["Add"] = 1] = "Add";
|
|
17
|
+
})(exports.QueueStrategy || (exports.QueueStrategy = {}));
|
|
18
|
+
|
|
7
19
|
const TextToSpeech = core.registerPlugin('TextToSpeech', {
|
|
8
20
|
web: () => Promise.resolve().then(function () { return web; }).then(m => new m.TextToSpeechWeb()),
|
|
9
21
|
});
|
package/dist/plugin.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst TextToSpeech = registerPlugin('TextToSpeech', {\n web: () => import('./web').then(m => new m.TextToSpeechWeb()),\n});\n// Warm up\nif ('speechSynthesis' in window) {\n window.speechSynthesis;\n}\nexport * from './definitions';\nexport { TextToSpeech };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class TextToSpeechWeb extends WebPlugin {\n constructor() {\n super();\n this.speechSynthesis = null;\n if ('speechSynthesis' in window) {\n this.speechSynthesis = window.speechSynthesis;\n window.addEventListener('beforeunload', () => {\n this.stop();\n });\n }\n }\n async speak(options) {\n if (!this.speechSynthesis) {\n this.throwUnsupportedError();\n }\n await this.stop();\n const speechSynthesis = this.speechSynthesis;\n const utterance = this.createSpeechSynthesisUtterance(options);\n return new Promise((resolve, reject) => {\n utterance.onend = () => {\n resolve();\n };\n utterance.onerror = (event) => {\n reject(event);\n };\n speechSynthesis.speak(utterance);\n });\n }\n async stop() {\n if (!this.speechSynthesis) {\n this.throwUnsupportedError();\n }\n this.speechSynthesis.cancel();\n }\n async getSupportedLanguages() {\n const voices = this.getSpeechSynthesisVoices();\n const languages = voices.map(voice => voice.lang);\n const filteredLanguages = languages.filter((v, i, a) => a.indexOf(v) == i);\n return { languages: filteredLanguages };\n }\n async getSupportedVoices() {\n const voices = this.getSpeechSynthesisVoices();\n return { voices };\n }\n async isLanguageSupported(options) {\n const result = await this.getSupportedLanguages();\n const isLanguageSupported = result.languages.includes(options.lang);\n return { supported: isLanguageSupported };\n }\n async openInstall() {\n this.throwUnimplementedError();\n }\n createSpeechSynthesisUtterance(options) {\n const voices = this.getSpeechSynthesisVoices();\n const utterance = new SpeechSynthesisUtterance();\n const { text, lang, rate, pitch, volume, voice } = options;\n if (voice) {\n utterance.voice = voices[voice];\n }\n if (volume) {\n utterance.volume = volume >= 0 && volume <= 1 ? volume : 1;\n }\n if (rate) {\n utterance.rate = rate >= 0.1 && rate <= 10 ? rate : 1;\n }\n if (pitch) {\n utterance.pitch = pitch >= 0 && pitch <= 2 ? pitch : 2;\n }\n if (lang) {\n utterance.lang = lang;\n }\n utterance.text = text;\n return utterance;\n }\n getSpeechSynthesisVoices() {\n if (!this.speechSynthesis) {\n this.throwUnsupportedError();\n }\n if (!this.supportedVoices || this.supportedVoices.length < 1) {\n this.supportedVoices = this.speechSynthesis.getVoices();\n }\n return this.supportedVoices;\n }\n throwUnsupportedError() {\n throw this.unavailable('SpeechSynthesis API not available in this browser.');\n }\n throwUnimplementedError() {\n throw this.unimplemented('Not implemented on web.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/definitions.js","esm/index.js","esm/web.js"],"sourcesContent":["export var QueueStrategy;\n(function (QueueStrategy) {\n /**\n * Use `Flush` to stop the current request when a new request is sent.\n */\n QueueStrategy[QueueStrategy[\"Flush\"] = 0] = \"Flush\";\n /**\n * Use `Add` to buffer the speech request. The request will be executed when all previous requests have been completed.\n */\n QueueStrategy[QueueStrategy[\"Add\"] = 1] = \"Add\";\n})(QueueStrategy || (QueueStrategy = {}));\n//# sourceMappingURL=definitions.js.map","import { registerPlugin } from '@capacitor/core';\nconst TextToSpeech = registerPlugin('TextToSpeech', {\n web: () => import('./web').then(m => new m.TextToSpeechWeb()),\n});\n// Warm up\nif ('speechSynthesis' in window) {\n window.speechSynthesis;\n}\nexport * from './definitions';\nexport { TextToSpeech };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class TextToSpeechWeb extends WebPlugin {\n constructor() {\n super();\n this.speechSynthesis = null;\n if ('speechSynthesis' in window) {\n this.speechSynthesis = window.speechSynthesis;\n window.addEventListener('beforeunload', () => {\n this.stop();\n });\n }\n }\n async speak(options) {\n if (!this.speechSynthesis) {\n this.throwUnsupportedError();\n }\n await this.stop();\n const speechSynthesis = this.speechSynthesis;\n const utterance = this.createSpeechSynthesisUtterance(options);\n return new Promise((resolve, reject) => {\n utterance.onend = () => {\n resolve();\n };\n utterance.onerror = (event) => {\n reject(event);\n };\n speechSynthesis.speak(utterance);\n });\n }\n async stop() {\n if (!this.speechSynthesis) {\n this.throwUnsupportedError();\n }\n this.speechSynthesis.cancel();\n }\n async getSupportedLanguages() {\n const voices = this.getSpeechSynthesisVoices();\n const languages = voices.map(voice => voice.lang);\n const filteredLanguages = languages.filter((v, i, a) => a.indexOf(v) == i);\n return { languages: filteredLanguages };\n }\n async getSupportedVoices() {\n const voices = this.getSpeechSynthesisVoices();\n return { voices };\n }\n async isLanguageSupported(options) {\n const result = await this.getSupportedLanguages();\n const isLanguageSupported = result.languages.includes(options.lang);\n return { supported: isLanguageSupported };\n }\n async openInstall() {\n this.throwUnimplementedError();\n }\n createSpeechSynthesisUtterance(options) {\n const voices = this.getSpeechSynthesisVoices();\n const utterance = new SpeechSynthesisUtterance();\n const { text, lang, rate, pitch, volume, voice } = options;\n if (voice) {\n utterance.voice = voices[voice];\n }\n if (volume) {\n utterance.volume = volume >= 0 && volume <= 1 ? volume : 1;\n }\n if (rate) {\n utterance.rate = rate >= 0.1 && rate <= 10 ? rate : 1;\n }\n if (pitch) {\n utterance.pitch = pitch >= 0 && pitch <= 2 ? pitch : 2;\n }\n if (lang) {\n utterance.lang = lang;\n }\n utterance.text = text;\n return utterance;\n }\n getSpeechSynthesisVoices() {\n if (!this.speechSynthesis) {\n this.throwUnsupportedError();\n }\n if (!this.supportedVoices || this.supportedVoices.length < 1) {\n this.supportedVoices = this.speechSynthesis.getVoices();\n }\n return this.supportedVoices;\n }\n throwUnsupportedError() {\n throw this.unavailable('SpeechSynthesis API not available in this browser.');\n }\n throwUnimplementedError() {\n throw this.unimplemented('Not implemented on web.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["QueueStrategy","registerPlugin","WebPlugin"],"mappings":"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"}
|
package/dist/plugin.js
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
var capacitorTextToSpeech = (function (exports, core) {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
+
exports.QueueStrategy = void 0;
|
|
5
|
+
(function (QueueStrategy) {
|
|
6
|
+
/**
|
|
7
|
+
* Use `Flush` to stop the current request when a new request is sent.
|
|
8
|
+
*/
|
|
9
|
+
QueueStrategy[QueueStrategy["Flush"] = 0] = "Flush";
|
|
10
|
+
/**
|
|
11
|
+
* Use `Add` to buffer the speech request. The request will be executed when all previous requests have been completed.
|
|
12
|
+
*/
|
|
13
|
+
QueueStrategy[QueueStrategy["Add"] = 1] = "Add";
|
|
14
|
+
})(exports.QueueStrategy || (exports.QueueStrategy = {}));
|
|
15
|
+
|
|
4
16
|
const TextToSpeech = core.registerPlugin('TextToSpeech', {
|
|
5
17
|
web: () => Promise.resolve().then(function () { return web; }).then(m => new m.TextToSpeechWeb()),
|
|
6
18
|
});
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst TextToSpeech = registerPlugin('TextToSpeech', {\n web: () => import('./web').then(m => new m.TextToSpeechWeb()),\n});\n// Warm up\nif ('speechSynthesis' in window) {\n window.speechSynthesis;\n}\nexport * from './definitions';\nexport { TextToSpeech };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class TextToSpeechWeb extends WebPlugin {\n constructor() {\n super();\n this.speechSynthesis = null;\n if ('speechSynthesis' in window) {\n this.speechSynthesis = window.speechSynthesis;\n window.addEventListener('beforeunload', () => {\n this.stop();\n });\n }\n }\n async speak(options) {\n if (!this.speechSynthesis) {\n this.throwUnsupportedError();\n }\n await this.stop();\n const speechSynthesis = this.speechSynthesis;\n const utterance = this.createSpeechSynthesisUtterance(options);\n return new Promise((resolve, reject) => {\n utterance.onend = () => {\n resolve();\n };\n utterance.onerror = (event) => {\n reject(event);\n };\n speechSynthesis.speak(utterance);\n });\n }\n async stop() {\n if (!this.speechSynthesis) {\n this.throwUnsupportedError();\n }\n this.speechSynthesis.cancel();\n }\n async getSupportedLanguages() {\n const voices = this.getSpeechSynthesisVoices();\n const languages = voices.map(voice => voice.lang);\n const filteredLanguages = languages.filter((v, i, a) => a.indexOf(v) == i);\n return { languages: filteredLanguages };\n }\n async getSupportedVoices() {\n const voices = this.getSpeechSynthesisVoices();\n return { voices };\n }\n async isLanguageSupported(options) {\n const result = await this.getSupportedLanguages();\n const isLanguageSupported = result.languages.includes(options.lang);\n return { supported: isLanguageSupported };\n }\n async openInstall() {\n this.throwUnimplementedError();\n }\n createSpeechSynthesisUtterance(options) {\n const voices = this.getSpeechSynthesisVoices();\n const utterance = new SpeechSynthesisUtterance();\n const { text, lang, rate, pitch, volume, voice } = options;\n if (voice) {\n utterance.voice = voices[voice];\n }\n if (volume) {\n utterance.volume = volume >= 0 && volume <= 1 ? volume : 1;\n }\n if (rate) {\n utterance.rate = rate >= 0.1 && rate <= 10 ? rate : 1;\n }\n if (pitch) {\n utterance.pitch = pitch >= 0 && pitch <= 2 ? pitch : 2;\n }\n if (lang) {\n utterance.lang = lang;\n }\n utterance.text = text;\n return utterance;\n }\n getSpeechSynthesisVoices() {\n if (!this.speechSynthesis) {\n this.throwUnsupportedError();\n }\n if (!this.supportedVoices || this.supportedVoices.length < 1) {\n this.supportedVoices = this.speechSynthesis.getVoices();\n }\n return this.supportedVoices;\n }\n throwUnsupportedError() {\n throw this.unavailable('SpeechSynthesis API not available in this browser.');\n }\n throwUnimplementedError() {\n throw this.unimplemented('Not implemented on web.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/definitions.js","esm/index.js","esm/web.js"],"sourcesContent":["export var QueueStrategy;\n(function (QueueStrategy) {\n /**\n * Use `Flush` to stop the current request when a new request is sent.\n */\n QueueStrategy[QueueStrategy[\"Flush\"] = 0] = \"Flush\";\n /**\n * Use `Add` to buffer the speech request. The request will be executed when all previous requests have been completed.\n */\n QueueStrategy[QueueStrategy[\"Add\"] = 1] = \"Add\";\n})(QueueStrategy || (QueueStrategy = {}));\n//# sourceMappingURL=definitions.js.map","import { registerPlugin } from '@capacitor/core';\nconst TextToSpeech = registerPlugin('TextToSpeech', {\n web: () => import('./web').then(m => new m.TextToSpeechWeb()),\n});\n// Warm up\nif ('speechSynthesis' in window) {\n window.speechSynthesis;\n}\nexport * from './definitions';\nexport { TextToSpeech };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class TextToSpeechWeb extends WebPlugin {\n constructor() {\n super();\n this.speechSynthesis = null;\n if ('speechSynthesis' in window) {\n this.speechSynthesis = window.speechSynthesis;\n window.addEventListener('beforeunload', () => {\n this.stop();\n });\n }\n }\n async speak(options) {\n if (!this.speechSynthesis) {\n this.throwUnsupportedError();\n }\n await this.stop();\n const speechSynthesis = this.speechSynthesis;\n const utterance = this.createSpeechSynthesisUtterance(options);\n return new Promise((resolve, reject) => {\n utterance.onend = () => {\n resolve();\n };\n utterance.onerror = (event) => {\n reject(event);\n };\n speechSynthesis.speak(utterance);\n });\n }\n async stop() {\n if (!this.speechSynthesis) {\n this.throwUnsupportedError();\n }\n this.speechSynthesis.cancel();\n }\n async getSupportedLanguages() {\n const voices = this.getSpeechSynthesisVoices();\n const languages = voices.map(voice => voice.lang);\n const filteredLanguages = languages.filter((v, i, a) => a.indexOf(v) == i);\n return { languages: filteredLanguages };\n }\n async getSupportedVoices() {\n const voices = this.getSpeechSynthesisVoices();\n return { voices };\n }\n async isLanguageSupported(options) {\n const result = await this.getSupportedLanguages();\n const isLanguageSupported = result.languages.includes(options.lang);\n return { supported: isLanguageSupported };\n }\n async openInstall() {\n this.throwUnimplementedError();\n }\n createSpeechSynthesisUtterance(options) {\n const voices = this.getSpeechSynthesisVoices();\n const utterance = new SpeechSynthesisUtterance();\n const { text, lang, rate, pitch, volume, voice } = options;\n if (voice) {\n utterance.voice = voices[voice];\n }\n if (volume) {\n utterance.volume = volume >= 0 && volume <= 1 ? volume : 1;\n }\n if (rate) {\n utterance.rate = rate >= 0.1 && rate <= 10 ? rate : 1;\n }\n if (pitch) {\n utterance.pitch = pitch >= 0 && pitch <= 2 ? pitch : 2;\n }\n if (lang) {\n utterance.lang = lang;\n }\n utterance.text = text;\n return utterance;\n }\n getSpeechSynthesisVoices() {\n if (!this.speechSynthesis) {\n this.throwUnsupportedError();\n }\n if (!this.supportedVoices || this.supportedVoices.length < 1) {\n this.supportedVoices = this.speechSynthesis.getVoices();\n }\n return this.supportedVoices;\n }\n throwUnsupportedError() {\n throw this.unavailable('SpeechSynthesis API not available in this browser.');\n }\n throwUnimplementedError() {\n throw this.unimplemented('Not implemented on web.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["QueueStrategy","registerPlugin","WebPlugin"],"mappings":"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"}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import AVFoundation
|
|
2
2
|
import Capacitor
|
|
3
3
|
|
|
4
|
+
enum QUEUE_STRATEGY: Int {
|
|
5
|
+
case QUEUE_ADD = 1, QUEUE_FLUSH = 0
|
|
6
|
+
}
|
|
7
|
+
|
|
4
8
|
@objc public class TextToSpeech: NSObject, AVSpeechSynthesizerDelegate {
|
|
5
9
|
let synthesizer = AVSpeechSynthesizer()
|
|
6
10
|
var calls: [CAPPluginCall] = []
|
|
@@ -29,8 +33,10 @@ import Capacitor
|
|
|
29
33
|
self.resolveCurrentCall()
|
|
30
34
|
}
|
|
31
35
|
|
|
32
|
-
@objc public func speak(_ text: String, _ lang: String, _ rate: Float, _ pitch: Float, _ category: String, _ volume: Float, _ voice: Int, _ call: CAPPluginCall) throws {
|
|
33
|
-
|
|
36
|
+
@objc public func speak(_ text: String, _ lang: String, _ rate: Float, _ pitch: Float, _ category: String, _ volume: Float, _ voice: Int, _ queueStrategy: Int, _ call: CAPPluginCall) throws {
|
|
37
|
+
if queueStrategy == QUEUE_STRATEGY.QUEUE_FLUSH.rawValue {
|
|
38
|
+
self.synthesizer.stopSpeaking(at: .immediate)
|
|
39
|
+
}
|
|
34
40
|
self.calls.append(call)
|
|
35
41
|
|
|
36
42
|
let utterance = AVSpeechUtterance(string: text)
|
|
@@ -68,14 +74,11 @@ import Capacitor
|
|
|
68
74
|
|
|
69
75
|
// Adjust rate for a closer match to other platform.
|
|
70
76
|
@objc private func adjustRate(_ rate: Float) -> Float {
|
|
71
|
-
let baseRate = AVSpeechUtteranceDefaultSpeechRate
|
|
72
|
-
if rate
|
|
73
|
-
return baseRate
|
|
74
|
-
}
|
|
75
|
-
if rate > baseRate {
|
|
76
|
-
return baseRate + (rate * 0.025)
|
|
77
|
+
let baseRate: Float = AVSpeechUtteranceDefaultSpeechRate
|
|
78
|
+
if rate >= 1.0 {
|
|
79
|
+
return (0.1 * rate) + (baseRate - 0.1)
|
|
77
80
|
}
|
|
78
|
-
return rate
|
|
81
|
+
return rate * baseRate
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
@objc private func resolveCurrentCall() {
|
|
@@ -20,6 +20,7 @@ public class TextToSpeechPlugin: CAPPlugin {
|
|
|
20
20
|
let volume = call.getFloat("volume") ?? 1.0
|
|
21
21
|
let voice = call.getInt("voice") ?? -1
|
|
22
22
|
let category = call.getString("category") ?? "ambient"
|
|
23
|
+
let queueStrategy = call.getInt("queueStrategy") ?? 0
|
|
23
24
|
|
|
24
25
|
let isLanguageSupported = implementation.isLanguageSupported(lang)
|
|
25
26
|
guard isLanguageSupported else {
|
|
@@ -28,7 +29,7 @@ public class TextToSpeechPlugin: CAPPlugin {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
do {
|
|
31
|
-
try implementation.speak(text, lang, rate, pitch, category, volume, voice, call)
|
|
32
|
+
try implementation.speak(text, lang, rate, pitch, category, volume, voice, queueStrategy, call)
|
|
32
33
|
} catch {
|
|
33
34
|
call.reject(error.localizedDescription)
|
|
34
35
|
}
|