react-native-davoice-tts 1.0.409 → 1.0.411
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 +20 -0
- 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 +67 -0
- package/ios/SpeechBridge/SpeechBridge.m +40 -0
- package/ios/TTSRNBridge/DaVoiceTTSBridge.m +40 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64/DavoiceTTS.framework/DavoiceTTS +0 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64/DavoiceTTS.framework/Headers/DavoiceTTS-Swift.h +30 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios.abi.json +435 -60
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios.private.swiftinterface +4 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios.swiftinterface +4 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/DavoiceTTS +0 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Headers/DavoiceTTS-Swift.h +60 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.abi.json +435 -60
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +4 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftinterface +4 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.abi.json +435 -60
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +4 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +4 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/_CodeSignature/CodeDirectory +0 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/_CodeSignature/CodeRequirements-1 +0 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/_CodeSignature/CodeResources +33 -33
- package/package.json +1 -1
- package/speech/index.d.ts +39 -0
- package/speech/index.ts +73 -0
|
@@ -161,6 +161,10 @@ public enum AudioPlaybackHook {
|
|
|
161
161
|
}
|
|
162
162
|
@objc final public func getAllVoices() -> [Swift.String]
|
|
163
163
|
@objc final public func getVoiceAbilities(_ name: Swift.String) -> [Swift.String]
|
|
164
|
+
#if compiler(>=5.3) && $NonescapableTypes
|
|
165
|
+
@objc(setExternalVoicesPath:completion:) final public func setExternalVoicesPath(_ path: Swift.String?, completion: (([Swift.String]) -> Swift.Void)? = nil)
|
|
166
|
+
#endif
|
|
167
|
+
@objc public static func createVoiceClone(_ inputAudioPath: Swift.String, outputPath: Swift.String, embedderPath: Swift.String) throws -> [Swift.String : Any]
|
|
164
168
|
@objc(changeVoice:completion:) final public func changeVoice(_ name: Swift.String, completion: @escaping (Swift.Int) -> Swift.Void)
|
|
165
169
|
@objc final public var onLastUtteranceFinished: (() -> Swift.Void)?
|
|
166
170
|
@objc deinit
|
|
Binary file
|
|
@@ -161,6 +161,10 @@ public enum AudioPlaybackHook {
|
|
|
161
161
|
}
|
|
162
162
|
@objc final public func getAllVoices() -> [Swift.String]
|
|
163
163
|
@objc final public func getVoiceAbilities(_ name: Swift.String) -> [Swift.String]
|
|
164
|
+
#if compiler(>=5.3) && $NonescapableTypes
|
|
165
|
+
@objc(setExternalVoicesPath:completion:) final public func setExternalVoicesPath(_ path: Swift.String?, completion: (([Swift.String]) -> Swift.Void)? = nil)
|
|
166
|
+
#endif
|
|
167
|
+
@objc public static func createVoiceClone(_ inputAudioPath: Swift.String, outputPath: Swift.String, embedderPath: Swift.String) throws -> [Swift.String : Any]
|
|
164
168
|
@objc(changeVoice:completion:) final public func changeVoice(_ name: Swift.String, completion: @escaping (Swift.Int) -> Swift.Void)
|
|
165
169
|
@objc final public var onLastUtteranceFinished: (() -> Swift.Void)?
|
|
166
170
|
@objc deinit
|
|
Binary file
|
|
Binary file
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<dict>
|
|
7
7
|
<key>Headers/DavoiceTTS-Swift.h</key>
|
|
8
8
|
<data>
|
|
9
|
-
|
|
9
|
+
sBeBhBzj/r1GrbXqcLsAirfQIKQ=
|
|
10
10
|
</data>
|
|
11
11
|
<key>Info.plist</key>
|
|
12
12
|
<data>
|
|
@@ -14,43 +14,43 @@
|
|
|
14
14
|
</data>
|
|
15
15
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.abi.json</key>
|
|
16
16
|
<data>
|
|
17
|
-
|
|
17
|
+
NZOQSk+oyJ0wjXl83FP/8CfQY9Q=
|
|
18
18
|
</data>
|
|
19
19
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface</key>
|
|
20
20
|
<data>
|
|
21
|
-
|
|
21
|
+
+SjLLdC9wzcmmVKdK3OspIIfl4c=
|
|
22
22
|
</data>
|
|
23
23
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftdoc</key>
|
|
24
24
|
<data>
|
|
25
|
-
|
|
25
|
+
5Ssm9whRQvwOrYUSWUeqAmJlBCk=
|
|
26
26
|
</data>
|
|
27
27
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftinterface</key>
|
|
28
28
|
<data>
|
|
29
|
-
|
|
29
|
+
+SjLLdC9wzcmmVKdK3OspIIfl4c=
|
|
30
30
|
</data>
|
|
31
31
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftmodule</key>
|
|
32
32
|
<data>
|
|
33
|
-
|
|
33
|
+
IUrwKe5bYNqrgkU5fQDMrzwCF2A=
|
|
34
34
|
</data>
|
|
35
35
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.abi.json</key>
|
|
36
36
|
<data>
|
|
37
|
-
|
|
37
|
+
NZOQSk+oyJ0wjXl83FP/8CfQY9Q=
|
|
38
38
|
</data>
|
|
39
39
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface</key>
|
|
40
40
|
<data>
|
|
41
|
-
|
|
41
|
+
CCVbMysPRrLBmlDQ1ev8miGvbX4=
|
|
42
42
|
</data>
|
|
43
43
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftdoc</key>
|
|
44
44
|
<data>
|
|
45
|
-
|
|
45
|
+
mGZKyR1CWLd+ITTHoFSKKVlTcxQ=
|
|
46
46
|
</data>
|
|
47
47
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftinterface</key>
|
|
48
48
|
<data>
|
|
49
|
-
|
|
49
|
+
CCVbMysPRrLBmlDQ1ev8miGvbX4=
|
|
50
50
|
</data>
|
|
51
51
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftmodule</key>
|
|
52
52
|
<data>
|
|
53
|
-
|
|
53
|
+
cA4vZqE2K7PeK7Oc4Josd+Vt/Ls=
|
|
54
54
|
</data>
|
|
55
55
|
<key>Modules/module.modulemap</key>
|
|
56
56
|
<data>
|
|
@@ -63,121 +63,121 @@
|
|
|
63
63
|
<dict>
|
|
64
64
|
<key>hash</key>
|
|
65
65
|
<data>
|
|
66
|
-
|
|
66
|
+
sBeBhBzj/r1GrbXqcLsAirfQIKQ=
|
|
67
67
|
</data>
|
|
68
68
|
<key>hash2</key>
|
|
69
69
|
<data>
|
|
70
|
-
|
|
70
|
+
WIZa1mRKiVZ+bP5gKEKczEKDF8R9zEhTU3SFieC0fO8=
|
|
71
71
|
</data>
|
|
72
72
|
</dict>
|
|
73
73
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.abi.json</key>
|
|
74
74
|
<dict>
|
|
75
75
|
<key>hash</key>
|
|
76
76
|
<data>
|
|
77
|
-
|
|
77
|
+
NZOQSk+oyJ0wjXl83FP/8CfQY9Q=
|
|
78
78
|
</data>
|
|
79
79
|
<key>hash2</key>
|
|
80
80
|
<data>
|
|
81
|
-
|
|
81
|
+
dImQrwOEdDV/E4EJqL/m2QqEGw0dPMKHybTSk2TKAkQ=
|
|
82
82
|
</data>
|
|
83
83
|
</dict>
|
|
84
84
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface</key>
|
|
85
85
|
<dict>
|
|
86
86
|
<key>hash</key>
|
|
87
87
|
<data>
|
|
88
|
-
|
|
88
|
+
+SjLLdC9wzcmmVKdK3OspIIfl4c=
|
|
89
89
|
</data>
|
|
90
90
|
<key>hash2</key>
|
|
91
91
|
<data>
|
|
92
|
-
|
|
92
|
+
e9/3r3eXLtlmcPkmnRU0xYdk/hzgUy0Rpv8GzYPXK2o=
|
|
93
93
|
</data>
|
|
94
94
|
</dict>
|
|
95
95
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftdoc</key>
|
|
96
96
|
<dict>
|
|
97
97
|
<key>hash</key>
|
|
98
98
|
<data>
|
|
99
|
-
|
|
99
|
+
5Ssm9whRQvwOrYUSWUeqAmJlBCk=
|
|
100
100
|
</data>
|
|
101
101
|
<key>hash2</key>
|
|
102
102
|
<data>
|
|
103
|
-
|
|
103
|
+
dtLnnJQR8LoDEVnD1tg06i/kKRwcaXwxJ/jHdnDmhEI=
|
|
104
104
|
</data>
|
|
105
105
|
</dict>
|
|
106
106
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftinterface</key>
|
|
107
107
|
<dict>
|
|
108
108
|
<key>hash</key>
|
|
109
109
|
<data>
|
|
110
|
-
|
|
110
|
+
+SjLLdC9wzcmmVKdK3OspIIfl4c=
|
|
111
111
|
</data>
|
|
112
112
|
<key>hash2</key>
|
|
113
113
|
<data>
|
|
114
|
-
|
|
114
|
+
e9/3r3eXLtlmcPkmnRU0xYdk/hzgUy0Rpv8GzYPXK2o=
|
|
115
115
|
</data>
|
|
116
116
|
</dict>
|
|
117
117
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftmodule</key>
|
|
118
118
|
<dict>
|
|
119
119
|
<key>hash</key>
|
|
120
120
|
<data>
|
|
121
|
-
|
|
121
|
+
IUrwKe5bYNqrgkU5fQDMrzwCF2A=
|
|
122
122
|
</data>
|
|
123
123
|
<key>hash2</key>
|
|
124
124
|
<data>
|
|
125
|
-
|
|
125
|
+
S/nm0VmvBX9ZvqiP8S6Y9LBt62/or63J0jrUsMBV5X0=
|
|
126
126
|
</data>
|
|
127
127
|
</dict>
|
|
128
128
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.abi.json</key>
|
|
129
129
|
<dict>
|
|
130
130
|
<key>hash</key>
|
|
131
131
|
<data>
|
|
132
|
-
|
|
132
|
+
NZOQSk+oyJ0wjXl83FP/8CfQY9Q=
|
|
133
133
|
</data>
|
|
134
134
|
<key>hash2</key>
|
|
135
135
|
<data>
|
|
136
|
-
|
|
136
|
+
dImQrwOEdDV/E4EJqL/m2QqEGw0dPMKHybTSk2TKAkQ=
|
|
137
137
|
</data>
|
|
138
138
|
</dict>
|
|
139
139
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface</key>
|
|
140
140
|
<dict>
|
|
141
141
|
<key>hash</key>
|
|
142
142
|
<data>
|
|
143
|
-
|
|
143
|
+
CCVbMysPRrLBmlDQ1ev8miGvbX4=
|
|
144
144
|
</data>
|
|
145
145
|
<key>hash2</key>
|
|
146
146
|
<data>
|
|
147
|
-
|
|
147
|
+
zs5TSJY3M0yp73wG3kcfebXGiEGjaBbjDvBJN1eDcEg=
|
|
148
148
|
</data>
|
|
149
149
|
</dict>
|
|
150
150
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftdoc</key>
|
|
151
151
|
<dict>
|
|
152
152
|
<key>hash</key>
|
|
153
153
|
<data>
|
|
154
|
-
|
|
154
|
+
mGZKyR1CWLd+ITTHoFSKKVlTcxQ=
|
|
155
155
|
</data>
|
|
156
156
|
<key>hash2</key>
|
|
157
157
|
<data>
|
|
158
|
-
|
|
158
|
+
Iqp+5eTycIlB+l9STROeFAxcZ/W9bSUDLqAMYDkMbCw=
|
|
159
159
|
</data>
|
|
160
160
|
</dict>
|
|
161
161
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftinterface</key>
|
|
162
162
|
<dict>
|
|
163
163
|
<key>hash</key>
|
|
164
164
|
<data>
|
|
165
|
-
|
|
165
|
+
CCVbMysPRrLBmlDQ1ev8miGvbX4=
|
|
166
166
|
</data>
|
|
167
167
|
<key>hash2</key>
|
|
168
168
|
<data>
|
|
169
|
-
|
|
169
|
+
zs5TSJY3M0yp73wG3kcfebXGiEGjaBbjDvBJN1eDcEg=
|
|
170
170
|
</data>
|
|
171
171
|
</dict>
|
|
172
172
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftmodule</key>
|
|
173
173
|
<dict>
|
|
174
174
|
<key>hash</key>
|
|
175
175
|
<data>
|
|
176
|
-
|
|
176
|
+
cA4vZqE2K7PeK7Oc4Josd+Vt/Ls=
|
|
177
177
|
</data>
|
|
178
178
|
<key>hash2</key>
|
|
179
179
|
<data>
|
|
180
|
-
|
|
180
|
+
QAjZ2CvyRKa72Kv5Ki3OOS/Q6EuERdLQwHK9/M4yO6Y=
|
|
181
181
|
</data>
|
|
182
182
|
</dict>
|
|
183
183
|
<key>Modules/module.modulemap</key>
|
package/package.json
CHANGED
package/speech/index.d.ts
CHANGED
|
@@ -37,6 +37,18 @@ export type NewSpeechWAVEvent = {
|
|
|
37
37
|
};
|
|
38
38
|
export type RNAssetLike = any;
|
|
39
39
|
export type ModelRef = string | RNAssetLike;
|
|
40
|
+
/** createVoiceClone() result. */
|
|
41
|
+
export type VoiceCloneResult = {
|
|
42
|
+
/** The .emd written (its file name without .emd is the voice name). */
|
|
43
|
+
path: string;
|
|
44
|
+
voice: string;
|
|
45
|
+
/** Length of the reference clip that was embedded. */
|
|
46
|
+
seconds: number;
|
|
47
|
+
/** Non-empty when less than 4 s of speech remained or the cut fell inside speech. */
|
|
48
|
+
warnings: string[];
|
|
49
|
+
/** What the preparation did (silence trimmed, pauses shortened, cut point). */
|
|
50
|
+
report: string[];
|
|
51
|
+
};
|
|
40
52
|
/** iOS AVAudioSession routing entry shared by STT and TTS. */
|
|
41
53
|
export type PreferredAudioInput = 'bluetoothHighQualityMic' | 'builtInMic' | 'none';
|
|
42
54
|
export type RouteConfigEntry = {
|
|
@@ -155,6 +167,32 @@ declare class Speech {
|
|
|
155
167
|
* Resolves [] for voices without variants or when unavailable.
|
|
156
168
|
*/
|
|
157
169
|
getVoiceAbilities(name: string): Promise<string[]>;
|
|
170
|
+
/** Also look for voices in the folder `path`: <name>.emd files made by
|
|
171
|
+
* createVoiceClone() (or .npy). They are listed by getAllVoices() after
|
|
172
|
+
* the bundled voices and selected with changeVoice() like them; a bundled
|
|
173
|
+
* voice wins over a file with the same name. Call again to pick up new files;
|
|
174
|
+
* null or "" removes them. Resolves the external voice names found.
|
|
175
|
+
*/
|
|
176
|
+
setExternalVoicesPath(path: string | null): Promise<string[]>;
|
|
177
|
+
/** Creates a voice clone from reference audio and saves it as a
|
|
178
|
+
* scrambled .emd at `outputPath`.
|
|
179
|
+
*
|
|
180
|
+
* - inputAudio: path/URI of a wav, mp3, m4a/aac, ogg, flac, ... recording. The
|
|
181
|
+
* best ~6 s of speech is used: silence trimmed, long pauses shortened, cut at
|
|
182
|
+
* a gap between words (never inside a word).
|
|
183
|
+
* - outputPath: the .emd file to write (".emd" is added when missing), or a
|
|
184
|
+
* folder ending in "/" (-> <folder>/<input name>.emd). The file name is the
|
|
185
|
+
* voice name.
|
|
186
|
+
* - embedder: the language's voice encoder embedder_<code>.dm, e.g.
|
|
187
|
+
* require('./assets/models/embedder_en.dm') or a path; it is unscrambled in
|
|
188
|
+
* memory only.
|
|
189
|
+
*
|
|
190
|
+
* Resolves { path, voice, seconds, warnings, report }; warnings is non-empty
|
|
191
|
+
* when less than 4 s of speech remained or the cut had to fall inside speech.
|
|
192
|
+
* When the .emd lands in the folder given to setExternalVoicesPath(), the new
|
|
193
|
+
* voice is usable right away.
|
|
194
|
+
*/
|
|
195
|
+
createVoiceClone(inputAudio: ModelRef, outputPath: string, embedder: ModelRef): Promise<VoiceCloneResult>;
|
|
158
196
|
/** Reference voice, matched case-insensitively without .wav.
|
|
159
197
|
* Returns 0 on match; -1 on fallback/unavailability. Missing names select the
|
|
160
198
|
* first WAV (alphabetical order). Already generated audio keeps its voice.
|
|
@@ -176,6 +214,7 @@ declare class Speech {
|
|
|
176
214
|
private hasCompletedFullInit;
|
|
177
215
|
private hasCompletedTtsInit;
|
|
178
216
|
private iosTtsOnly;
|
|
217
|
+
private externalVoicesPath;
|
|
179
218
|
private logCall;
|
|
180
219
|
private resolveModelExt;
|
|
181
220
|
private resolveModelToPath;
|
package/speech/index.ts
CHANGED
|
@@ -137,6 +137,19 @@ export type NewSpeechWAVEvent = { path: string };
|
|
|
137
137
|
export type RNAssetLike = any; // keep permissive (Metro asset numbers/objects vary)
|
|
138
138
|
export type ModelRef = string | RNAssetLike;
|
|
139
139
|
|
|
140
|
+
/** createVoiceClone() result. */
|
|
141
|
+
export type VoiceCloneResult = {
|
|
142
|
+
/** The .emd written (its file name without .emd is the voice name). */
|
|
143
|
+
path: string;
|
|
144
|
+
voice: string;
|
|
145
|
+
/** Length of the reference clip that was embedded. */
|
|
146
|
+
seconds: number;
|
|
147
|
+
/** Non-empty when less than 4 s of speech remained or the cut fell inside speech. */
|
|
148
|
+
warnings: string[];
|
|
149
|
+
/** What the preparation did (silence trimmed, pauses shortened, cut point). */
|
|
150
|
+
report: string[];
|
|
151
|
+
};
|
|
152
|
+
|
|
140
153
|
/** iOS AVAudioSession routing entry shared by STT and TTS. */
|
|
141
154
|
export type PreferredAudioInput =
|
|
142
155
|
| 'bluetoothHighQualityMic'
|
|
@@ -337,6 +350,65 @@ class Speech {
|
|
|
337
350
|
}
|
|
338
351
|
}
|
|
339
352
|
|
|
353
|
+
/** Also look for voices in the folder `path`: <name>.emd files made by
|
|
354
|
+
* createVoiceClone() (or .npy). They are listed by getAllVoices() after
|
|
355
|
+
* the bundled voices and selected with changeVoice() like them; a bundled
|
|
356
|
+
* voice wins over a file with the same name. Call again to pick up new files;
|
|
357
|
+
* null or "" removes them. Resolves the external voice names found.
|
|
358
|
+
*/
|
|
359
|
+
async setExternalVoicesPath(path: string | null): Promise<string[]> {
|
|
360
|
+
const bridge = Platform.OS === 'ios' && !this.iosTtsOnly && this.hasCompletedFullInit
|
|
361
|
+
? NativeSpeech : NativeTTS;
|
|
362
|
+
if ((Platform.OS !== 'android' && Platform.OS !== 'ios') || typeof bridge?.setExternalVoicesPath !== 'function') return [];
|
|
363
|
+
this.externalVoicesPath = path || null;
|
|
364
|
+
try {
|
|
365
|
+
const names = await bridge.setExternalVoicesPath(path || null);
|
|
366
|
+
return Array.isArray(names) ? names.filter((v: unknown): v is string => typeof v === 'string') : [];
|
|
367
|
+
} catch {
|
|
368
|
+
return [];
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/** Creates a voice clone from reference audio and saves it as a
|
|
373
|
+
* scrambled .emd at `outputPath`.
|
|
374
|
+
*
|
|
375
|
+
* - inputAudio: path/URI of a wav, mp3, m4a/aac, ogg, flac, ... recording. The
|
|
376
|
+
* best ~6 s of speech is used: silence trimmed, long pauses shortened, cut at
|
|
377
|
+
* a gap between words (never inside a word).
|
|
378
|
+
* - outputPath: the .emd file to write (".emd" is added when missing), or a
|
|
379
|
+
* folder ending in "/" (-> <folder>/<input name>.emd). The file name is the
|
|
380
|
+
* voice name.
|
|
381
|
+
* - embedder: the language's voice encoder embedder_<code>.dm, e.g.
|
|
382
|
+
* require('./assets/models/embedder_en.dm') or a path; it is unscrambled in
|
|
383
|
+
* memory only.
|
|
384
|
+
*
|
|
385
|
+
* Resolves { path, voice, seconds, warnings, report }; warnings is non-empty
|
|
386
|
+
* when less than 4 s of speech remained or the cut had to fall inside speech.
|
|
387
|
+
* When the .emd lands in the folder given to setExternalVoicesPath(), the new
|
|
388
|
+
* voice is usable right away.
|
|
389
|
+
*/
|
|
390
|
+
async createVoiceClone(inputAudio: ModelRef, outputPath: string, embedder: ModelRef): Promise<VoiceCloneResult> {
|
|
391
|
+
const bridge = (typeof NativeTTS?.createVoiceClone === 'function') ? NativeTTS : NativeSpeech;
|
|
392
|
+
if (typeof bridge?.createVoiceClone !== 'function') {
|
|
393
|
+
throw new Error('createVoiceClone is not available on this platform');
|
|
394
|
+
}
|
|
395
|
+
const result = await bridge.createVoiceClone(
|
|
396
|
+
this.resolveModelToPath(inputAudio), String(outputPath), this.resolveModelToPath(embedder));
|
|
397
|
+
const folder = this.externalVoicesPath;
|
|
398
|
+
if (folder && typeof result?.path === 'string') {
|
|
399
|
+
const strip = (p: string) => p.replace(/^file:\/\//, '').replace(/\/+$/, '');
|
|
400
|
+
const parent = result.path.substring(0, result.path.lastIndexOf('/'));
|
|
401
|
+
if (strip(parent) === strip(folder)) await this.setExternalVoicesPath(folder);
|
|
402
|
+
}
|
|
403
|
+
return {
|
|
404
|
+
path: String(result?.path ?? ''),
|
|
405
|
+
voice: String(result?.voice ?? ''),
|
|
406
|
+
seconds: Number(result?.seconds ?? 0),
|
|
407
|
+
warnings: Array.isArray(result?.warnings) ? result.warnings.map(String) : [],
|
|
408
|
+
report: Array.isArray(result?.report) ? result.report.map(String) : [],
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
|
|
340
412
|
/** Reference voice, matched case-insensitively without .wav.
|
|
341
413
|
* Returns 0 on match; -1 on fallback/unavailability. Missing names select the
|
|
342
414
|
* first WAV (alphabetical order). Already generated audio keeps its voice.
|
|
@@ -423,6 +495,7 @@ class Speech {
|
|
|
423
495
|
private hasCompletedFullInit = false;
|
|
424
496
|
private hasCompletedTtsInit = false;
|
|
425
497
|
private iosTtsOnly = false; // when true, use NativeTTS directly on iOS
|
|
498
|
+
private externalVoicesPath: string | null = null; // setExternalVoicesPath()
|
|
426
499
|
|
|
427
500
|
|
|
428
501
|
private logCall(name: string, payload?: any) {
|