@capgo/capacitor-speech-synthesis 8.0.4 → 8.0.6

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.
@@ -1,6 +1,5 @@
1
1
  package ee.forgr.plugin.speechsynthesis;
2
2
 
3
- import android.os.Build;
4
3
  import android.os.Bundle;
5
4
  import android.speech.tts.TextToSpeech;
6
5
  import android.speech.tts.UtteranceProgressListener;
@@ -13,7 +12,6 @@ import com.getcapacitor.PluginMethod;
13
12
  import com.getcapacitor.annotation.CapacitorPlugin;
14
13
  import java.io.File;
15
14
  import java.util.ArrayList;
16
- import java.util.HashMap;
17
15
  import java.util.HashSet;
18
16
  import java.util.List;
19
17
  import java.util.Locale;
@@ -23,7 +21,7 @@ import org.json.JSONException;
23
21
  @CapacitorPlugin(name = "SpeechSynthesis")
24
22
  public class SpeechSynthesisPlugin extends Plugin {
25
23
 
26
- private final String pluginVersion = "8.0.4";
24
+ private final String pluginVersion = "8.0.6";
27
25
  private TextToSpeech tts;
28
26
  private int utteranceIdCounter = 0;
29
27
  private boolean ttsInitialized = false;
@@ -129,7 +127,7 @@ public class SpeechSynthesisPlugin extends Plugin {
129
127
  String language = call.getString("language");
130
128
  String voiceId = call.getString("voiceId");
131
129
 
132
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && voiceId != null) {
130
+ if (voiceId != null) {
133
131
  Voice voice = findVoiceById(voiceId);
134
132
  if (voice != null) {
135
133
  tts.setVoice(voice);
@@ -159,16 +157,7 @@ public class SpeechSynthesisPlugin extends Plugin {
159
157
  params.putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, utteranceId);
160
158
 
161
159
  // Speak
162
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
163
- tts.speak(text, queueMode, params, utteranceId);
164
- } else {
165
- HashMap<String, String> paramsMap = new HashMap<>();
166
- paramsMap.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, utteranceId);
167
- if (volume != null) {
168
- paramsMap.put(TextToSpeech.Engine.KEY_PARAM_VOLUME, String.valueOf(volume));
169
- }
170
- tts.speak(text, queueMode, paramsMap);
171
- }
160
+ tts.speak(text, queueMode, params, utteranceId);
172
161
 
173
162
  JSObject result = new JSObject();
174
163
  result.put("utteranceId", utteranceId);
@@ -194,7 +183,7 @@ public class SpeechSynthesisPlugin extends Plugin {
194
183
  String language = call.getString("language");
195
184
  String voiceId = call.getString("voiceId");
196
185
 
197
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && voiceId != null) {
186
+ if (voiceId != null) {
198
187
  Voice voice = findVoiceById(voiceId);
199
188
  if (voice != null) {
200
189
  tts.setVoice(voice);
@@ -215,34 +204,18 @@ public class SpeechSynthesisPlugin extends Plugin {
215
204
  File outputFile = new File(getContext().getFilesDir(), utteranceId + ".wav");
216
205
 
217
206
  // Synthesize to file
218
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
219
- Bundle params = new Bundle();
220
- params.putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, utteranceId);
221
-
222
- int result = tts.synthesizeToFile(text, params, outputFile, utteranceId);
223
-
224
- if (result == TextToSpeech.SUCCESS) {
225
- JSObject response = new JSObject();
226
- response.put("filePath", outputFile.getAbsolutePath());
227
- response.put("utteranceId", utteranceId);
228
- call.resolve(response);
229
- } else {
230
- call.reject("Failed to synthesize to file");
231
- }
207
+ Bundle params = new Bundle();
208
+ params.putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, utteranceId);
209
+
210
+ int result = tts.synthesizeToFile(text, params, outputFile, utteranceId);
211
+
212
+ if (result == TextToSpeech.SUCCESS) {
213
+ JSObject response = new JSObject();
214
+ response.put("filePath", outputFile.getAbsolutePath());
215
+ response.put("utteranceId", utteranceId);
216
+ call.resolve(response);
232
217
  } else {
233
- HashMap<String, String> params = new HashMap<>();
234
- params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, utteranceId);
235
-
236
- int result = tts.synthesizeToFile(text, params, outputFile.getAbsolutePath());
237
-
238
- if (result == TextToSpeech.SUCCESS) {
239
- JSObject response = new JSObject();
240
- response.put("filePath", outputFile.getAbsolutePath());
241
- response.put("utteranceId", utteranceId);
242
- call.resolve(response);
243
- } else {
244
- call.reject("Failed to synthesize to file");
245
- }
218
+ call.reject("Failed to synthesize to file");
246
219
  }
247
220
  }
248
221
 
@@ -289,7 +262,7 @@ public class SpeechSynthesisPlugin extends Plugin {
289
262
  public void getVoices(PluginCall call) {
290
263
  JSArray voicesArray = new JSArray();
291
264
 
292
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && tts != null) {
265
+ if (tts != null) {
293
266
  Set<Voice> voices = tts.getVoices();
294
267
  if (voices != null) {
295
268
  for (Voice voice : voices) {
@@ -299,19 +272,6 @@ public class SpeechSynthesisPlugin extends Plugin {
299
272
  voiceInfo.put("language", voice.getLocale().toLanguageTag());
300
273
  voiceInfo.put("isNetworkConnectionRequired", voice.isNetworkConnectionRequired());
301
274
 
302
- voicesArray.put(voiceInfo);
303
- }
304
- }
305
- } else {
306
- // Fallback for older Android versions
307
- Locale[] locales = Locale.getAvailableLocales();
308
- for (Locale locale : locales) {
309
- if (tts != null && tts.isLanguageAvailable(locale) >= TextToSpeech.LANG_AVAILABLE) {
310
- JSObject voiceInfo = new JSObject();
311
- String tag = locale.toLanguageTag();
312
- voiceInfo.put("id", tag);
313
- voiceInfo.put("name", locale.getDisplayName());
314
- voiceInfo.put("language", tag);
315
275
  voicesArray.put(voiceInfo);
316
276
  }
317
277
  }
@@ -326,21 +286,13 @@ public class SpeechSynthesisPlugin extends Plugin {
326
286
  public void getLanguages(PluginCall call) {
327
287
  Set<String> languageSet = new HashSet<>();
328
288
 
329
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && tts != null) {
289
+ if (tts != null) {
330
290
  Set<Voice> voices = tts.getVoices();
331
291
  if (voices != null) {
332
292
  for (Voice voice : voices) {
333
293
  languageSet.add(voice.getLocale().toLanguageTag());
334
294
  }
335
295
  }
336
- } else {
337
- // Fallback for older Android versions
338
- Locale[] locales = Locale.getAvailableLocales();
339
- for (Locale locale : locales) {
340
- if (tts != null && tts.isLanguageAvailable(locale) >= TextToSpeech.LANG_AVAILABLE) {
341
- languageSet.add(locale.toLanguageTag());
342
- }
343
- }
344
296
  }
345
297
 
346
298
  List<String> languages = new ArrayList<>(languageSet);
@@ -375,11 +327,7 @@ public class SpeechSynthesisPlugin extends Plugin {
375
327
  return;
376
328
  }
377
329
 
378
- boolean isAvailable = false;
379
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
380
- Voice voice = findVoiceById(voiceId);
381
- isAvailable = voice != null;
382
- }
330
+ boolean isAvailable = findVoiceById(voiceId) != null;
383
331
 
384
332
  JSObject result = new JSObject();
385
333
  result.put("isAvailable", isAvailable);
@@ -414,7 +362,7 @@ public class SpeechSynthesisPlugin extends Plugin {
414
362
  }
415
363
 
416
364
  private Voice findVoiceById(String voiceId) {
417
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && tts != null) {
365
+ if (tts != null) {
418
366
  Set<Voice> voices = tts.getVoices();
419
367
  if (voices != null) {
420
368
  for (Voice voice : voices) {
@@ -7,7 +7,7 @@ import AVFoundation
7
7
  */
8
8
  @objc(SpeechSynthesisPlugin)
9
9
  public class SpeechSynthesisPlugin: CAPPlugin, CAPBridgedPlugin, AVSpeechSynthesizerDelegate {
10
- private let pluginVersion: String = "8.0.4"
10
+ private let pluginVersion: String = "8.0.6"
11
11
  public let identifier = "SpeechSynthesisPlugin"
12
12
  public let jsName = "SpeechSynthesis"
13
13
  public let pluginMethods: [CAPPluginMethod] = [
@@ -122,32 +122,28 @@ public class SpeechSynthesisPlugin: CAPPlugin, CAPBridgedPlugin, AVSpeechSynthes
122
122
  }
123
123
 
124
124
  // Write to file
125
- if #available(iOS 13.0, *) {
126
- let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
127
- let audioFilename = documentsPath.appendingPathComponent("\(utteranceId).caf")
128
-
129
- synthesizer?.write(utterance) { (buffer: AVAudioBuffer) in
130
- guard let pcmBuffer = buffer as? AVAudioPCMBuffer else {
131
- call.reject("Failed to get PCM buffer")
132
- return
133
- }
125
+ let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
126
+ let audioFilename = documentsPath.appendingPathComponent("\(utteranceId).caf")
127
+
128
+ synthesizer?.write(utterance) { (buffer: AVAudioBuffer) in
129
+ guard let pcmBuffer = buffer as? AVAudioPCMBuffer else {
130
+ call.reject("Failed to get PCM buffer")
131
+ return
132
+ }
134
133
 
135
- if let audioFile = try? AVAudioFile(forWriting: audioFilename, settings: pcmBuffer.format.settings) {
136
- do {
137
- try audioFile.write(from: pcmBuffer)
138
- call.resolve([
139
- "filePath": audioFilename.path,
140
- "utteranceId": utteranceId
141
- ])
142
- } catch {
143
- call.reject("Failed to write audio file: \(error.localizedDescription)")
144
- }
145
- } else {
146
- call.reject("Failed to create audio file")
134
+ if let audioFile = try? AVAudioFile(forWriting: audioFilename, settings: pcmBuffer.format.settings) {
135
+ do {
136
+ try audioFile.write(from: pcmBuffer)
137
+ call.resolve([
138
+ "filePath": audioFilename.path,
139
+ "utteranceId": utteranceId
140
+ ])
141
+ } catch {
142
+ call.reject("Failed to write audio file: \(error.localizedDescription)")
147
143
  }
144
+ } else {
145
+ call.reject("Failed to create audio file")
148
146
  }
149
- } else {
150
- call.reject("synthesizeToFile requires iOS 13.0 or later")
151
147
  }
152
148
  }
153
149
 
@@ -189,24 +185,20 @@ public class SpeechSynthesisPlugin: CAPPlugin, CAPBridgedPlugin, AVSpeechSynthes
189
185
  "language": voice.language
190
186
  ]
191
187
 
192
- // Add gender if available
193
- if #available(iOS 13.0, *) {
194
- switch voice.gender {
195
- case .male:
196
- info["gender"] = "male"
197
- case .female:
198
- info["gender"] = "female"
199
- default:
200
- info["gender"] = "neutral"
201
- }
188
+ // Add gender
189
+ switch voice.gender {
190
+ case .male:
191
+ info["gender"] = "male"
192
+ case .female:
193
+ info["gender"] = "female"
194
+ default:
195
+ info["gender"] = "neutral"
202
196
  }
203
197
 
204
198
  // Add network requirement
205
- if #available(iOS 13.0, *) {
206
- // Higher quality voices (enhanced/premium) typically don't require network
207
- // Default quality = 1, Enhanced quality = 2
208
- info["isNetworkConnectionRequired"] = voice.quality.rawValue < 2
209
- }
199
+ // Higher quality voices (enhanced/premium) typically don't require network
200
+ // Default quality = 1, Enhanced quality = 2
201
+ info["isNetworkConnectionRequired"] = voice.quality.rawValue < 2
210
202
 
211
203
  return info
212
204
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-speech-synthesis",
3
- "version": "8.0.4",
3
+ "version": "8.0.6",
4
4
  "description": "Synthesize speech from text with full control over language, voice, pitch, rate, and volume.",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",