react-native-davoice-tts 1.0.366 → 1.0.368

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.
Files changed (26) hide show
  1. package/TTSRNBridge.podspec +1 -1
  2. package/android/libs/com/davoice/tts/1.0.0/tts-1.0.0.aar +0 -0
  3. package/android/libs/com/davoice/tts/1.0.0/tts-1.0.0.aar.md5 +1 -1
  4. package/android/libs/com/davoice/tts/1.0.0/tts-1.0.0.aar.sha1 +1 -1
  5. package/android/src/main/java/com/davoice/stt/rn/STTModule.kt +12 -10
  6. package/android/src/main/java/com/davoice/tts/rn/DaVoiceTTSBridge.java +16 -6
  7. package/ios/SpeechBridge/SpeechBridge.m +26 -14
  8. package/ios/TTSRNBridge/DaVoiceTTSBridge.m +15 -6
  9. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64/DavoiceTTS.framework/DavoiceTTS +0 -0
  10. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios.abi.json +432 -418
  11. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios.private.swiftinterface +1 -1
  12. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios.swiftinterface +1 -1
  13. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/DavoiceTTS +0 -0
  14. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.abi.json +432 -418
  15. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +1 -1
  16. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftinterface +1 -1
  17. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.abi.json +432 -418
  18. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +1 -1
  19. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +1 -1
  20. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/_CodeSignature/CodeDirectory +0 -0
  21. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/_CodeSignature/CodeRequirements-1 +0 -0
  22. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/_CodeSignature/CodeResources +24 -24
  23. package/package.json +1 -1
  24. package/speech/index.ts +81 -43
  25. package/stt/index.ts +8 -1
  26. package/tts/DaVoiceTTSBridge.js +7 -1
@@ -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.296" # Update to your package version
5
+ s.version = "1.0.300" # 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
- 98089f198ef8c17572381ae733d1c816 tts-1.0.0.aar
1
+ ccb550ff914e8c1d14ec4a143be82ebe tts-1.0.0.aar
@@ -1 +1 @@
1
- f0271d4b2b4c9afb3d9dbe86325bf35e23d102c9 tts-1.0.0.aar
1
+ 9cdf4df23768ec8752362ea0cb4e47273d062fff tts-1.0.0.aar
@@ -145,8 +145,10 @@ class STTModule(private val rc: ReactApplicationContext)
145
145
  cb.invoke(true)
146
146
  return
147
147
  }
148
- stt?.pauseSpeechRecognitionLite()
149
- cb.invoke(true)
148
+ // ok is false only if the native pause timed out (see STT.kt
149
+ // runPauseResumeSerializedOnMain) - it is never left unresolved.
150
+ val ok = stt?.pauseSpeechRecognitionLite() ?: true
151
+ cb.invoke(ok)
150
152
  }
151
153
 
152
154
  @ReactMethod
@@ -159,8 +161,8 @@ class STTModule(private val rc: ReactApplicationContext)
159
161
 
160
162
  // JS passes number; keep it simple and clamp
161
163
  val t = times.toInt()
162
- stt?.unPauseSpeechRecognitionLite(t)
163
- cb.invoke(true)
164
+ val ok = stt?.unPauseSpeechRecognitionLite(t) ?: true
165
+ cb.invoke(ok)
164
166
  }
165
167
 
166
168
  @ReactMethod
@@ -172,20 +174,20 @@ class STTModule(private val rc: ReactApplicationContext)
172
174
 
173
175
  val t = times.toInt()
174
176
  val ms = preFetchMs.toInt().coerceIn(0, 2000)
175
- stt?.unPauseSpeechRecognitionLite(t, ms)
176
- cb.invoke(true)
177
+ val ok = stt?.unPauseSpeechRecognitionLite(t, ms) ?: true
178
+ cb.invoke(ok)
177
179
  }
178
180
 
179
181
  @ReactMethod
180
182
  fun pauseMicrophone(cb: Callback) {
181
- ensure().pauseMicrophone()
182
- cb.invoke(false)
183
+ val ok = ensure().pauseMicrophone()
184
+ cb.invoke(ok)
183
185
  }
184
186
 
185
187
  @ReactMethod
186
188
  fun unPauseMicrophone(cb: Callback) {
187
- ensure().unPauseMicrophone()
188
- cb.invoke(false)
189
+ val ok = ensure().unPauseMicrophone()
190
+ cb.invoke(ok)
189
191
  }
190
192
 
191
193
  /** Start MIC+VAD remote capture that emits a single WAV via onNewSpeechWAV */
@@ -32,10 +32,20 @@ import com.davoice.tts.LicenseManager;
32
32
 
33
33
  public class DaVoiceTTSBridge extends ReactContextBaseJavaModule {
34
34
 
35
+ private static final boolean DEBUG_LOGS_ENABLED = false;
36
+
35
37
  private final DaVoiceTTSInterface tts;
36
38
  private final ReactApplicationContext reactCtx;
37
39
  final String TAG = "TTS";
38
40
 
41
+ private static void debugLog(String tag, String message) {
42
+ if (DEBUG_LOGS_ENABLED) Log.d(tag, message);
43
+ }
44
+
45
+ private static void infoLog(String tag, String message) {
46
+ if (DEBUG_LOGS_ENABLED) Log.i(tag, message);
47
+ }
48
+
39
49
  public DaVoiceTTSBridge(ReactApplicationContext context) {
40
50
  super(context);
41
51
  this.reactCtx = context;
@@ -343,7 +353,7 @@ public class DaVoiceTTSBridge extends ReactContextBaseJavaModule {
343
353
  String pkg = reactCtx.getPackageName();
344
354
  int resId = reactCtx.getResources().getIdentifier(rawName, "raw", pkg);
345
355
 
346
- Log.d(TAG, "copyRawResourceToCache: rawName=" + rawName + " pkg=" + pkg + " resId=" + resId);
356
+ debugLog(TAG, "copyRawResourceToCache: rawName=" + rawName + " pkg=" + pkg + " resId=" + resId);
347
357
 
348
358
  if (resId == 0) return null;
349
359
 
@@ -360,7 +370,7 @@ public class DaVoiceTTSBridge extends ReactContextBaseJavaModule {
360
370
  while ((len = in.read(buf)) != -1) fos.write(buf, 0, len);
361
371
  }
362
372
 
363
- Log.d(TAG, "copyRawResourceToCache: wrote " + out.getAbsolutePath() + " size=" + out.length());
373
+ debugLog(TAG, "copyRawResourceToCache: wrote " + out.getAbsolutePath() + " size=" + out.length());
364
374
  return out;
365
375
  } catch (Exception e) {
366
376
  Log.e(TAG, "copyRawResourceToCache FAILED rawName=" + rawName + " err=" + e.getMessage(), e);
@@ -398,7 +408,7 @@ public class DaVoiceTTSBridge extends ReactContextBaseJavaModule {
398
408
  {
399
409
  File out = tryCopyRawToCacheIfExists(s, defaultExt);
400
410
  if (out != null) {
401
- Log.i(TAG, "resolveToLocalFileForRead: copied res/raw '" + s + "' -> " + out.getAbsolutePath());
411
+ infoLog(TAG, "resolveToLocalFileForRead: copied res/raw '" + s + "' -> " + out.getAbsolutePath());
402
412
  return out;
403
413
  }
404
414
  }
@@ -408,7 +418,7 @@ public class DaVoiceTTSBridge extends ReactContextBaseJavaModule {
408
418
  if (s.startsWith("assets_")) {
409
419
  File out = copyRawResourceToCache(s, defaultExt);
410
420
  if (out != null && out.exists()) {
411
- Log.i(TAG, "resolveToLocalFileForRead: copied res/raw '" + s + "' -> " + out.getAbsolutePath());
421
+ infoLog(TAG, "resolveToLocalFileForRead: copied res/raw '" + s + "' -> " + out.getAbsolutePath());
412
422
  return out;
413
423
  }
414
424
  Log.w(TAG, "resolveToLocalFileForRead: res/raw lookup failed for '" + s + "'");
@@ -623,7 +633,7 @@ public class DaVoiceTTSBridge extends ReactContextBaseJavaModule {
623
633
  @ReactMethod
624
634
  public void playWav(String pathOrURL, boolean markAsLast, Promise promise) {
625
635
  final String TAG = "TTS";
626
- Log.d(TAG, "playWav() called with: " + pathOrURL + " | markAsLast=" + markAsLast);
636
+ debugLog(TAG, "playWav() called with: " + pathOrURL + " | markAsLast=" + markAsLast);
627
637
  // 1️⃣ Handle RN dev server URLs (http://localhost:8081/...) by downloading them to cache first
628
638
  try {
629
639
  File f = resolveToLocalFileForRead(pathOrURL, "wav");
@@ -635,7 +645,7 @@ public class DaVoiceTTSBridge extends ReactContextBaseJavaModule {
635
645
  promise.reject("file_missing", "WAV file does not exist at path: " + f.getAbsolutePath());
636
646
  return;
637
647
  }
638
- Log.d(TAG, "Playing WAV from: " + f.getAbsolutePath());
648
+ debugLog(TAG, "Playing WAV from: " + f.getAbsolutePath());
639
649
  tts.playWav(f, markAsLast);
640
650
  promise.resolve("queued");
641
651
  } catch (Exception e) {
@@ -10,6 +10,18 @@
10
10
  #import <AVFAudio/AVFAudio.h>
11
11
  #import <Speech/Speech.h>
12
12
 
13
+ static const BOOL SBBridgeDebugLogsEnabled = NO;
14
+
15
+ static void SBDebugLog(NSString *format, ...) NS_FORMAT_FUNCTION(1, 2);
16
+ static void SBDebugLog(NSString *format, ...)
17
+ {
18
+ if (!SBBridgeDebugLogsEnabled) return;
19
+ va_list args;
20
+ va_start(args, format);
21
+ NSLogv(format, args);
22
+ va_end(args);
23
+ }
24
+
13
25
  static NSData *SB_Base64Decode(NSString *b64) {
14
26
  if (!b64 || (id)b64 == [NSNull null]) return nil;
15
27
  return [[NSData alloc] initWithBase64EncodedString:b64 options:0];
@@ -444,7 +456,7 @@ RCT_EXPORT_METHOD(setAudioRoutingConfig:(NSString *)jsonConfig
444
456
  return;
445
457
  }
446
458
 
447
- RCTLogInfo(@"[SpeechBridge] stored direct audio routing config before initialization");
459
+ SBDebugLog(@"[SpeechBridge] stored direct audio routing config before initialization");
448
460
  resolve(@"ok");
449
461
  }
450
462
 
@@ -518,7 +530,7 @@ RCT_EXPORT_METHOD(initAll:(NSDictionary *)opts
518
530
 
519
531
  // ✅ Fallback for bare .dm: if resolution failed, let native core search (same as .onnx behavior).
520
532
  if (!modelURL && isBareDmName) {
521
- NSLog(@"[TTS] INIT: bare .dm name could not be resolved, falling back to bare path: %@", modelPath);
533
+ SBDebugLog(@"[TTS] INIT: bare .dm name could not be resolved, falling back to bare path: %@", modelPath);
522
534
  modelURL = [NSURL fileURLWithPath:modelPath];
523
535
  }
524
536
 
@@ -539,7 +551,7 @@ RCT_EXPORT_METHOD(initAll:(NSDictionary *)opts
539
551
  return;
540
552
  }
541
553
  }
542
- NSLog(@"[TTS] INIT: modelURL == %@", modelURL);
554
+ SBDebugLog(@"[TTS] INIT: modelURL == %@", modelURL);
543
555
 
544
556
  if (self.tts) {
545
557
  @try { [self.tts stopSpeaking]; [self.tts destroy]; } @catch (__unused id e) {}
@@ -645,11 +657,11 @@ RCT_EXPORT_METHOD(pauseSpeechRecognitionLiteAsync:(nonnull NSNumber *)timeoutMs
645
657
  NSNumber *t = timeoutMs ?: @(1500);
646
658
  if (t.doubleValue <= 0) t = @(1500);
647
659
  CFTimeInterval startedAt = CACurrentMediaTime();
648
- RCTLogInfo(@"[SpeechBridge] %@ pauseSpeechRecognitionLiteAsync begin timeoutMs=%@ stt=%@", SBNowString(), t, self.stt);
660
+ SBDebugLog(@"[SpeechBridge] %@ pauseSpeechRecognitionLiteAsync begin timeoutMs=%@ stt=%@", SBNowString(), t, self.stt);
649
661
 
650
662
  if ([(id)self.stt respondsToSelector:@selector(pauseSpeechRecognitionLiteAndWait:completion:)]) {
651
663
  [(id)self.stt pauseSpeechRecognitionLiteAndWait:t completion:^(BOOL ok, NSString * _Nullable reason) {
652
- RCTLogInfo(@"[SpeechBridge] %@ pauseSpeechRecognitionLiteAsync resolved elapsedMs=%.1f ok=%@ reason=%@",
664
+ SBDebugLog(@"[SpeechBridge] %@ pauseSpeechRecognitionLiteAsync resolved elapsedMs=%.1f ok=%@ reason=%@",
653
665
  SBNowString(),
654
666
  (CACurrentMediaTime() - startedAt) * 1000.0,
655
667
  SBBoolString(ok),
@@ -659,7 +671,7 @@ RCT_EXPORT_METHOD(pauseSpeechRecognitionLiteAsync:(nonnull NSNumber *)timeoutMs
659
671
  return;
660
672
  }
661
673
 
662
- RCTLogInfo(@"[SpeechBridge] %@ pauseSpeechRecognitionLiteAsync fallback no-wait", SBNowString());
674
+ SBDebugLog(@"[SpeechBridge] %@ pauseSpeechRecognitionLiteAsync fallback no-wait", SBNowString());
663
675
  [self.stt pauseSpeechRecognitionLite];
664
676
  resolve(@{@"ok": @(YES), @"reason": @"bridge_fallback_no_wait_method"});
665
677
  }
@@ -696,7 +708,7 @@ RCT_EXPORT_METHOD(unPauseSpeechRecognitionLiteAsync:(nonnull NSNumber *)times
696
708
  NSNumber *pf = preFetch ?: @(0);
697
709
  if (pf.doubleValue < 0) pf = @(0);
698
710
  CFTimeInterval startedAt = CACurrentMediaTime();
699
- RCTLogInfo(@"[SpeechBridge] %@ unPauseSpeechRecognitionLiteAsync begin times=%@ preFetchMs=%@ timeoutMs=%@ stt=%@ initialized=%@ initializing=%@",
711
+ SBDebugLog(@"[SpeechBridge] %@ unPauseSpeechRecognitionLiteAsync begin times=%@ preFetchMs=%@ timeoutMs=%@ stt=%@ initialized=%@ initializing=%@",
700
712
  SBNowString(),
701
713
  times,
702
714
  pf,
@@ -710,7 +722,7 @@ RCT_EXPORT_METHOD(unPauseSpeechRecognitionLiteAsync:(nonnull NSNumber *)times
710
722
  preFetch:pf
711
723
  timeoutMs:t
712
724
  completion:^(BOOL ok, NSString * _Nullable reason) {
713
- RCTLogInfo(@"[SpeechBridge] %@ unPauseSpeechRecognitionLiteAsync resolved elapsedMs=%.1f ok=%@ reason=%@",
725
+ SBDebugLog(@"[SpeechBridge] %@ unPauseSpeechRecognitionLiteAsync resolved elapsedMs=%.1f ok=%@ reason=%@",
714
726
  SBNowString(),
715
727
  (CACurrentMediaTime() - startedAt) * 1000.0,
716
728
  SBBoolString(ok),
@@ -720,7 +732,7 @@ RCT_EXPORT_METHOD(unPauseSpeechRecognitionLiteAsync:(nonnull NSNumber *)times
720
732
  return;
721
733
  }
722
734
 
723
- RCTLogInfo(@"[SpeechBridge] %@ unPauseSpeechRecognitionLiteAsync fallback no-wait", SBNowString());
735
+ SBDebugLog(@"[SpeechBridge] %@ unPauseSpeechRecognitionLiteAsync fallback no-wait", SBNowString());
724
736
  [self.stt unPauseSpeechRecognitionLite:times preFetch:pf];
725
737
  resolve(@{@"ok": @(YES), @"reason": @"bridge_fallback_no_wait_method"});
726
738
  }
@@ -981,7 +993,7 @@ RCT_EXPORT_METHOD(playWav:(NSString *)pathOrURL
981
993
 
982
994
  // 1️⃣ Handle http(s) URLs — download to temporary file first
983
995
  if ([pathOrURL hasPrefix:@"http://"] || [pathOrURL hasPrefix:@"https://"]) {
984
- NSLog(@"[TTS] Downloading asset from URL: %@", pathOrURL);
996
+ SBDebugLog(@"[TTS] Downloading asset from URL: %@", pathOrURL);
985
997
  NSURL *remoteURL = [NSURL URLWithString:pathOrURL];
986
998
  if (!remoteURL) {
987
999
  reject(@"bad_url", @"Invalid remote URL", nil);
@@ -1001,13 +1013,13 @@ RCT_EXPORT_METHOD(playWav:(NSString *)pathOrURL
1001
1013
  return;
1002
1014
  }
1003
1015
  fileURL = [NSURL fileURLWithPath:tempPath];
1004
- NSLog(@"[TTS] Downloaded to temp file: %@", tempPath);
1016
+ SBDebugLog(@"[TTS] Downloaded to temp file: %@", tempPath);
1005
1017
  }
1006
1018
 
1007
1019
  // 2️⃣ Handle bundled asset:/ paths (copied from main bundle)
1008
1020
  else if ([pathOrURL hasPrefix:@"asset:/"]) {
1009
1021
  NSString *assetName = [pathOrURL stringByReplacingOccurrencesOfString:@"asset:/" withString:@""];
1010
- NSLog(@"[TTS] Detected bundled asset: %@", assetName);
1022
+ SBDebugLog(@"[TTS] Detected bundled asset: %@", assetName);
1011
1023
  NSString *bundlePath = [[NSBundle mainBundle] pathForResource:[assetName stringByDeletingPathExtension]
1012
1024
  ofType:[assetName pathExtension]];
1013
1025
  if (!bundlePath) {
@@ -1024,7 +1036,7 @@ RCT_EXPORT_METHOD(playWav:(NSString *)pathOrURL
1024
1036
  return;
1025
1037
  }
1026
1038
  fileURL = [NSURL fileURLWithPath:tempPath];
1027
- NSLog(@"[TTS] Copied bundled asset to temp: %@", tempPath);
1039
+ SBDebugLog(@"[TTS] Copied bundled asset to temp: %@", tempPath);
1028
1040
  }
1029
1041
 
1030
1042
  // 3️⃣ Handle file:// URLs
@@ -1044,7 +1056,7 @@ RCT_EXPORT_METHOD(playWav:(NSString *)pathOrURL
1044
1056
  }
1045
1057
 
1046
1058
  // 6️⃣ Play through TTS engine (queued)
1047
- NSLog(@"[TTS] Playing file via DaVoiceTTS: %@", fileURL.path);
1059
+ SBDebugLog(@"[TTS] Playing file via DaVoiceTTS: %@", fileURL.path);
1048
1060
  [self.tts playWav:fileURL markAsLastUtterance:markAsLast.boolValue];
1049
1061
  resolve(@"queued");
1050
1062
  }
@@ -4,6 +4,18 @@
4
4
  #import <React/RCTConvert.h>
5
5
  #import <AVFAudio/AVFAudio.h>
6
6
 
7
+ static const BOOL DTTSBridgeDebugLogsEnabled = NO;
8
+
9
+ static void DTTSBridgeDebugLog(NSString *format, ...) NS_FORMAT_FUNCTION(1, 2);
10
+ static void DTTSBridgeDebugLog(NSString *format, ...)
11
+ {
12
+ if (!DTTSBridgeDebugLogsEnabled) return;
13
+ va_list args;
14
+ va_start(args, format);
15
+ NSLogv(format, args);
16
+ va_end(args);
17
+ }
18
+
7
19
  static NSData *DTTSBase64Decode(NSString *base64) {
8
20
  if (!base64 || (id)base64 == [NSNull null]) return nil;
9
21
  return [[NSData alloc] initWithBase64EncodedString:base64 options:0];
@@ -69,8 +81,7 @@ static AVAudioPCMBuffer *DTTSMakeMonoF32Buffer(NSData *raw,
69
81
  RCT_EXPORT_MODULE();
70
82
 
71
83
  + (BOOL)requiresMainQueueSetup {
72
- RCTLogInfo(@"[DaVoiceTTSBridge] requiresMainQueueSetup called (module loaded).");
73
- NSLog(@"[DaVoiceTTSBridge] requiresMainQueueSetup called (module loaded).");
84
+ DTTSBridgeDebugLog(@"[DaVoiceTTSBridge] requiresMainQueueSetup called (module loaded).");
74
85
 
75
86
  return YES;
76
87
  }
@@ -106,8 +117,7 @@ RCT_EXPORT_MODULE();
106
117
  - (instancetype)init {
107
118
  self = [super init];
108
119
  if (self) {
109
- RCTLogInfo(@"[DaVoiceTTSBridge] init called.");
110
- NSLog(@"[DaVoiceTTSBridge] init called.");
120
+ DTTSBridgeDebugLog(@"[DaVoiceTTSBridge] init called.");
111
121
  }
112
122
  return self;
113
123
  }
@@ -173,8 +183,7 @@ RCT_EXPORT_METHOD(initTTS:(NSDictionary *)configDict
173
183
  resolver:(RCTPromiseResolveBlock)resolve
174
184
  rejecter:(RCTPromiseRejectBlock)reject)
175
185
  {
176
- RCTLogInfo(@"[DaVoiceTTSBridge] initTTS called with configDict: %@", configDict);
177
- NSLog(@"[DaVoiceTTSBridge] initTTS called with configDict: %@", configDict);
186
+ DTTSBridgeDebugLog(@"[DaVoiceTTSBridge] initTTS called with configDict: %@", configDict);
178
187
  NSString *modelPath = configDict[@"model"];
179
188
 
180
189
  if (!modelPath) {