react-native-davoice-tts 1.0.417 → 1.0.419

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.
@@ -2,7 +2,7 @@ require 'json'
2
2
 
3
3
  Pod::Spec.new do |s|
4
4
  s.name = "TTSRNBridge"
5
- s.version = "1.0.423" # Update to your package version
5
+ s.version = "1.0.428" # Update to your package version
6
6
  s.summary = "TTS for React Native."
7
7
  s.description = <<-DESC
8
8
  A React Native module for tts .
@@ -1 +1 @@
1
- 9c2900d3bbc5599ade3ff6c0c5133e53 tts-1.0.0.aar
1
+ 1348ba0e9080bc918c43bbcc8ebb3910 tts-1.0.0.aar
@@ -1 +1 @@
1
- 3ab209cbfc132f971a308a04d8cc89c8e0db4d97 tts-1.0.0.aar
1
+ bd3cb66d4a4ea4f5b62f4f31964385ea58d1f32c tts-1.0.0.aar
@@ -8,32 +8,32 @@
8
8
  <key>BinaryPath</key>
9
9
  <string>DavoiceTTS.framework/DavoiceTTS</string>
10
10
  <key>LibraryIdentifier</key>
11
- <string>ios-arm64_x86_64-simulator</string>
11
+ <string>ios-arm64</string>
12
12
  <key>LibraryPath</key>
13
13
  <string>DavoiceTTS.framework</string>
14
14
  <key>SupportedArchitectures</key>
15
15
  <array>
16
16
  <string>arm64</string>
17
- <string>x86_64</string>
18
17
  </array>
19
18
  <key>SupportedPlatform</key>
20
19
  <string>ios</string>
21
- <key>SupportedPlatformVariant</key>
22
- <string>simulator</string>
23
20
  </dict>
24
21
  <dict>
25
22
  <key>BinaryPath</key>
26
23
  <string>DavoiceTTS.framework/DavoiceTTS</string>
27
24
  <key>LibraryIdentifier</key>
28
- <string>ios-arm64</string>
25
+ <string>ios-arm64_x86_64-simulator</string>
29
26
  <key>LibraryPath</key>
30
27
  <string>DavoiceTTS.framework</string>
31
28
  <key>SupportedArchitectures</key>
32
29
  <array>
33
30
  <string>arm64</string>
31
+ <string>x86_64</string>
34
32
  </array>
35
33
  <key>SupportedPlatform</key>
36
34
  <string>ios</string>
35
+ <key>SupportedPlatformVariant</key>
36
+ <string>simulator</string>
37
37
  </dict>
38
38
  </array>
39
39
  <key>CFBundlePackageType</key>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-davoice-tts",
3
- "version": "1.0.417",
3
+ "version": "1.0.419",
4
4
  "description": "tts library for React Native",
5
5
  "main": "tts/index.js",
6
6
  "types": "tts/index.d.ts",
package/speech/index.d.ts CHANGED
@@ -146,6 +146,9 @@ declare class Speech {
146
146
  private ttsChain;
147
147
  private ttsPendingResolve;
148
148
  private ttsPendingTimeout;
149
+ private speakWaiters;
150
+ private speakWaitTimeout;
151
+ private ttsEpoch;
149
152
  private sttTransitionChain;
150
153
  private dbgAsset;
151
154
  private _onNativeFinishedSpeaking;
@@ -196,7 +199,6 @@ declare class Speech {
196
199
  changeVoice(name: string): Promise<number>;
197
200
  private _nativeSpeak;
198
201
  private enqueueSttTransition;
199
- private _speakAndWait;
200
202
  private sttEmitter;
201
203
  private ttsEmitter;
202
204
  private unifiedEmitter;
@@ -309,7 +311,15 @@ declare class Speech {
309
311
  initTTS(modelOrConfig: ModelRef | {
310
312
  model: ModelRef;
311
313
  }): Promise<any>;
314
+ /**
315
+ * Speaks `text`. The text goes to the native speech queue right away, so call
316
+ * it for each sentence as soon as you have it: the queue prepares the next
317
+ * sentences while the current one plays, and they follow each other without
318
+ * gaps. Resolves when everything queued so far has been spoken (native
319
+ * onFinishedSpeaking: the queue is empty).
320
+ */
312
321
  speak(text: string, speakerId?: number, speed?: number): Promise<void>;
322
+ private _releaseSpeakWaiters;
313
323
  private _cancelTtsWait;
314
324
  stopSpeaking(): Promise<any>;
315
325
  private wavChain;
package/speech/index.ts CHANGED
@@ -280,6 +280,10 @@ class Speech {
280
280
  private ttsChain: Promise<void> = Promise.resolve();
281
281
  private ttsPendingResolve: (() => void) | null = null;
282
282
  private ttsPendingTimeout: any = null;
283
+ // speak(): texts native has queued, waiting for the queue to be spoken
284
+ private speakWaiters: Array<() => void> = [];
285
+ private speakWaitTimeout: any = null;
286
+ private ttsEpoch = 0; // bumped by stopSpeaking/initAll/destroyAll
283
287
  private sttTransitionChain: Promise<void> = Promise.resolve();
284
288
 
285
289
  private dbgAsset(label: string, x: any) {
@@ -308,6 +312,8 @@ class Speech {
308
312
  const r = this.ttsPendingResolve;
309
313
  this.ttsPendingResolve = null;
310
314
  if (r) r();
315
+ // 3) speak(): everything queued has been spoken
316
+ this._releaseSpeakWaiters();
311
317
  }
312
318
 
313
319
  /** Voices available in the loaded .dm (the names changeVoice() accepts; the
@@ -458,27 +464,6 @@ class Speech {
458
464
  return run;
459
465
  }
460
466
 
461
- private _speakAndWait(text: string, speakerId: number, s: number, timeoutMs = 600000) {
462
- return new Promise<void>((resolve, reject) => {
463
- this.ttsPendingResolve = resolve;
464
- // safety: never hang forever
465
- this.ttsPendingTimeout = setTimeout(() => {
466
- dbg('Timeout waiting for onFinishedSpeaking — releasing wait');
467
- if (this.ttsPendingTimeout) { clearTimeout(this.ttsPendingTimeout); this.ttsPendingTimeout = null; }
468
- const r = this.ttsPendingResolve;
469
- this.ttsPendingResolve = null;
470
- if (r) r(); // ✅ accept after timeout
471
- }, timeoutMs);
472
- try {
473
- this._nativeSpeak(text, speakerId, s);
474
- } catch (e) {
475
- if (this.ttsPendingTimeout) { clearTimeout(this.ttsPendingTimeout); this.ttsPendingTimeout = null; }
476
- this.ttsPendingResolve = null;
477
- reject(e as any);
478
- }
479
- });
480
- }
481
-
482
467
  private sttEmitter: NativeEventEmitter | null = null;
483
468
  private ttsEmitter: NativeEventEmitter | typeof DeviceEventEmitter | null = null;
484
469
  private unifiedEmitter: NativeEventEmitter | null = null;
@@ -1473,14 +1458,46 @@ class Speech {
1473
1458
  return r;
1474
1459
  }
1475
1460
 
1461
+ /**
1462
+ * Speaks `text`. The text goes to the native speech queue right away, so call
1463
+ * it for each sentence as soon as you have it: the queue prepares the next
1464
+ * sentences while the current one plays, and they follow each other without
1465
+ * gaps. Resolves when everything queued so far has been spoken (native
1466
+ * onFinishedSpeaking: the queue is empty).
1467
+ */
1476
1468
  async speak(text: string, speakerId = 0, speed = 1.0) {
1477
1469
  // sanitize and invert (avoid NaN/undefined/null)
1478
1470
  // Reverse speed to length.
1479
1471
  const s = Number.isFinite(speed as number) && speed !== 0 ? 1.0 / (speed as number) : 1.0;
1480
1472
  this.ensureListeners();
1481
- // MIN: serialize + await actual completion (event-driven)
1482
- this.ttsChain = this.ttsChain.then(() => this._speakAndWait(text, speakerId, s));
1483
- return this.ttsChain;
1473
+ const epoch = this.ttsEpoch;
1474
+ let release!: () => void;
1475
+ const spoken = new Promise<void>((resolve) => { release = resolve; });
1476
+ // Only the sends are serialized (in order); none waits for the previous
1477
+ // text to be spoken. A stop drops the texts not sent yet.
1478
+ const send = this.ttsChain.then(async () => {
1479
+ if (epoch !== this.ttsEpoch) return release();
1480
+ await this._nativeSpeak(text, speakerId, s);
1481
+ if (epoch !== this.ttsEpoch) return release();
1482
+ // Waits from now: a queue-empty event sent before native had this text
1483
+ // has already arrived.
1484
+ this.speakWaiters.push(release);
1485
+ if (this.speakWaitTimeout) clearTimeout(this.speakWaitTimeout);
1486
+ this.speakWaitTimeout = setTimeout(() => {
1487
+ dbg('Timeout waiting for onFinishedSpeaking — releasing speak waits');
1488
+ this._releaseSpeakWaiters();
1489
+ }, 600000);
1490
+ });
1491
+ this.ttsChain = send.catch(() => {});
1492
+ await send;
1493
+ return spoken;
1494
+ }
1495
+
1496
+ private _releaseSpeakWaiters() {
1497
+ if (this.speakWaitTimeout) { clearTimeout(this.speakWaitTimeout); this.speakWaitTimeout = null; }
1498
+ const waiters = this.speakWaiters;
1499
+ this.speakWaiters = [];
1500
+ waiters.forEach((release) => release());
1484
1501
  }
1485
1502
 
1486
1503
  // --- NEW: cancel any pending "wait for finished" immediately ---
@@ -1498,6 +1515,10 @@ class Speech {
1498
1515
  this.ttsPendingResolve = null;
1499
1516
  if (r) r();
1500
1517
 
1518
+ // speak(): drop the texts not sent yet, release the ones waiting
1519
+ this.ttsEpoch++;
1520
+ this._releaseSpeakWaiters();
1521
+
1501
1522
  // IMPORTANT: do NOT call app callback here (stopSpeaking should not emit "finished")
1502
1523
  // this.handlers.onFinishedSpeaking() <-- DO NOT
1503
1524
  }