react-native-davoice-tts 1.0.275 → 1.0.277
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/TTSRNBridge.podspec +1 -1
- package/android/libs/com/davoice/tts/1.0.0/tts-1.0.0.aar +0 -0
- package/android/libs/com/davoice/tts/1.0.0/tts-1.0.0.aar.md5 +1 -1
- package/android/libs/com/davoice/tts/1.0.0/tts-1.0.0.aar.sha1 +1 -1
- package/android/src/main/java/com/davoice/tts/rn/DaVoiceTTSBridge.java +89 -4
- package/package.json +1 -1
- package/speech/index.ts +5 -0
package/TTSRNBridge.podspec
CHANGED
|
@@ -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.
|
|
5
|
+
s.version = "1.0.150" # 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 .
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
faa5cade26dcaf91c23989be5442e102 tts-1.0.0.aar
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
d00ea3703391db2243e11526aebb47f37e146b97 tts-1.0.0.aar
|
|
@@ -24,10 +24,14 @@ import android.content.res.AssetFileDescriptor;
|
|
|
24
24
|
import java.io.IOException;
|
|
25
25
|
import java.net.URL;
|
|
26
26
|
import java.net.URLConnection;
|
|
27
|
+
import com.google.android.play.core.assetpacks.AssetPackLocation;
|
|
28
|
+
import com.google.android.play.core.assetpacks.AssetPackManager;
|
|
29
|
+
import com.google.android.play.core.assetpacks.AssetPackManagerFactory;
|
|
27
30
|
|
|
28
31
|
|
|
29
32
|
import com.davoice.tts.DaVoiceTTSInterface;
|
|
30
33
|
|
|
34
|
+
|
|
31
35
|
public class DaVoiceTTSBridge extends ReactContextBaseJavaModule {
|
|
32
36
|
|
|
33
37
|
private final DaVoiceTTSInterface tts;
|
|
@@ -160,13 +164,19 @@ public class DaVoiceTTSBridge extends ReactContextBaseJavaModule {
|
|
|
160
164
|
!s.toLowerCase(Locale.US).startsWith("file:") &&
|
|
161
165
|
!s.toLowerCase(Locale.US).startsWith("content:") &&
|
|
162
166
|
!s.toLowerCase(Locale.US).startsWith("asset:") &&
|
|
163
|
-
// ✅ IMPORTANT: RN release resource names are NOT AssetManager assets
|
|
164
|
-
!s.startsWith("assets_");
|
|
167
|
+
// ✅ IMPORTANT: RN release resource names are NOT AssetManager assets (res/raw)
|
|
168
|
+
!s.startsWith("assets_") && !s.startsWith("src_assets_");
|
|
169
|
+
|
|
165
170
|
|
|
166
171
|
final String modelName;
|
|
167
172
|
if (looksLikePlainAssetPath) {
|
|
168
|
-
|
|
169
|
-
|
|
173
|
+
File f = resolvePlainModelToFile(s, modelExt != null ? modelExt : "onnx");
|
|
174
|
+
if (f != null) {
|
|
175
|
+
modelName = f.getAbsolutePath(); // pass a real filesystem path to the engine
|
|
176
|
+
} else {
|
|
177
|
+
// Last resort: keep old behavior (in case engine itself can open via AssetManager)
|
|
178
|
+
modelName = s;
|
|
179
|
+
}
|
|
170
180
|
} else {
|
|
171
181
|
// Use provided extension when RN gave us assets_* (no ext), otherwise fall back safely.
|
|
172
182
|
final String ext = (modelExt != null && !modelExt.isEmpty()) ? modelExt : "onnx";
|
|
@@ -197,6 +207,53 @@ public class DaVoiceTTSBridge extends ReactContextBaseJavaModule {
|
|
|
197
207
|
}
|
|
198
208
|
}
|
|
199
209
|
|
|
210
|
+
/** models_pack → absolute file (if installed), else null */
|
|
211
|
+
@Nullable
|
|
212
|
+
private File getFileFromAssetPack(String relative) {
|
|
213
|
+
try {
|
|
214
|
+
AssetPackManager apm = AssetPackManagerFactory.getInstance(reactCtx.getApplicationContext());
|
|
215
|
+
AssetPackLocation loc = apm.getPackLocation("models_pack");
|
|
216
|
+
if (loc == null) return null;
|
|
217
|
+
String root = loc.assetsPath(); // .../assets
|
|
218
|
+
if (root == null) return null;
|
|
219
|
+
|
|
220
|
+
// Accept both "model.onnx" and "models/model.onnx"
|
|
221
|
+
String rel = relative.startsWith("models/") ? relative : ("models/" + relative);
|
|
222
|
+
File f = new File(root, rel);
|
|
223
|
+
return f.exists() ? f : null;
|
|
224
|
+
} catch (Throwable t) {
|
|
225
|
+
Log.w(TAG, "getFileFromAssetPack failed: " + t.getMessage());
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/** If in res/raw, copy to cache and return File; else null. */
|
|
231
|
+
@Nullable
|
|
232
|
+
private File tryResolveFromResRawToCache(String nameMaybeWithExt, @Nullable String defaultExt) {
|
|
233
|
+
// Accept "model.onnx" or "model"
|
|
234
|
+
String rawName = nameMaybeWithExt;
|
|
235
|
+
if (rawName == null) return null;
|
|
236
|
+
rawName = rawName.trim();
|
|
237
|
+
if (rawName.isEmpty()) return null;
|
|
238
|
+
int dot = rawName.lastIndexOf('.');
|
|
239
|
+
if (dot > 0) rawName = rawName.substring(0, dot);
|
|
240
|
+
return copyRawResourceToCache(rawName, defaultExt);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/** For plain names, resolve to an absolute File using res/raw or asset-pack. */
|
|
244
|
+
@Nullable
|
|
245
|
+
private File resolvePlainModelToFile(String plain, @Nullable String defaultExt) {
|
|
246
|
+
// 1) res/raw (RN may map bundled assets there in release)
|
|
247
|
+
File fromRaw = tryResolveFromResRawToCache(plain, defaultExt);
|
|
248
|
+
if (fromRaw != null && fromRaw.exists()) return fromRaw;
|
|
249
|
+
|
|
250
|
+
// 2) fast-follow asset pack
|
|
251
|
+
File fromPack = getFileFromAssetPack(plain);
|
|
252
|
+
if (fromPack != null && fromPack.exists()) return fromPack;
|
|
253
|
+
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
|
|
200
257
|
@ReactMethod
|
|
201
258
|
public void speak(String text, int speakerId, double speed, Promise promise) {
|
|
202
259
|
try {
|
|
@@ -241,6 +298,24 @@ public class DaVoiceTTSBridge extends ReactContextBaseJavaModule {
|
|
|
241
298
|
}
|
|
242
299
|
}
|
|
243
300
|
|
|
301
|
+
private File tryCopyRawToCacheIfExists(String name, @Nullable String defaultExt) {
|
|
302
|
+
if (name == null) return null;
|
|
303
|
+
final String s = name.trim();
|
|
304
|
+
if (s.isEmpty()) return null;
|
|
305
|
+
|
|
306
|
+
// Only reasonable resource entry names (no scheme, no slashes)
|
|
307
|
+
if (s.contains("://") || s.contains("/") || s.contains("\\") || s.startsWith(".")) return null;
|
|
308
|
+
|
|
309
|
+
// IMPORTANT: res/raw entry names have NO extension in Android resources
|
|
310
|
+
// If caller passed "foo.wav", strip extension for resource lookup.
|
|
311
|
+
String rawName = s;
|
|
312
|
+
int dot = rawName.lastIndexOf('.');
|
|
313
|
+
if (dot > 0) rawName = rawName.substring(0, dot);
|
|
314
|
+
|
|
315
|
+
File out = copyRawResourceToCache(rawName, defaultExt);
|
|
316
|
+
return (out != null && out.exists()) ? out : null;
|
|
317
|
+
}
|
|
318
|
+
|
|
244
319
|
// Resolve pathOrURL -> local readable File (supports http(s), asset:/, file://, plain path)
|
|
245
320
|
// defaultExt can be "wav", "onnx", etc (used for tmp file naming when extension missing)
|
|
246
321
|
private File resolveToLocalFileForRead(String pathOrURL, @Nullable String defaultExt) throws Exception {
|
|
@@ -248,6 +323,16 @@ public class DaVoiceTTSBridge extends ReactContextBaseJavaModule {
|
|
|
248
323
|
final String s = pathOrURL.trim();
|
|
249
324
|
if (s.isEmpty()) return null;
|
|
250
325
|
|
|
326
|
+
// 0) RN bundled assets on Android are usually in res/raw and resolve to a resource entry name
|
|
327
|
+
// like "assets_*" OR "src_assets_*" (no extension). Try res/raw first.
|
|
328
|
+
{
|
|
329
|
+
File out = tryCopyRawToCacheIfExists(s, defaultExt);
|
|
330
|
+
if (out != null) {
|
|
331
|
+
Log.i(TAG, "resolveToLocalFileForRead: copied res/raw '" + s + "' -> " + out.getAbsolutePath());
|
|
332
|
+
return out;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
251
336
|
// 0) RN bundled assets resolve to res/raw names like "assets_cashregistersound" (NO extension).
|
|
252
337
|
// They are NOT APK /assets files. Handle exactly like react-native-sound: Resources.getIdentifier(..., "raw", ...)
|
|
253
338
|
if (s.startsWith("assets_")) {
|
package/package.json
CHANGED
package/speech/index.ts
CHANGED
|
@@ -761,6 +761,11 @@ class Speech {
|
|
|
761
761
|
console.log('[Speech.playWav] resolveAssetSource ->', asset);
|
|
762
762
|
|
|
763
763
|
let realPath = asset?.uri ?? pathOrURL;
|
|
764
|
+
if (Platform.OS === 'android' && typeof asset?.uri === 'string') {
|
|
765
|
+
// Pass raw resource entry name through (native will resolve via res/raw)
|
|
766
|
+
realPath = asset.uri;
|
|
767
|
+
}
|
|
768
|
+
|
|
764
769
|
console.log('[Speech.playWav] resolved realPath:', realPath);
|
|
765
770
|
|
|
766
771
|
if (typeof realPath !== 'string') {
|