react-native-davoice-tts 1.0.74 → 1.0.76
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 +2 -1
- package/ios/SpeechBridge/SpeechBridge.h +7 -0
- package/ios/SpeechBridge/SpeechBridge.m +220 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/Info.plist +5 -5
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64/DavoiceTTS.framework/DavoiceTTS +0 -0
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios.abi.json +191 -191
- 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/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.abi.json +1952 -1952
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +19 -19
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftinterface +19 -19
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.abi.json +1952 -1952
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +19 -19
- package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +19 -19
- 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 +24 -24
- package/package.json +2 -1
- package/speech/index.ts +314 -0
|
@@ -14,25 +14,6 @@ import _StringProcessing
|
|
|
14
14
|
import _SwiftConcurrencyShims
|
|
15
15
|
import onnxruntime_objc
|
|
16
16
|
import phonemes
|
|
17
|
-
@objc public protocol STTDelegate {
|
|
18
|
-
@objc func stt(_ stt: DavoiceTTS.STT, didEmitEvent name: Swift.String, body: [Swift.String : Any]?)
|
|
19
|
-
}
|
|
20
|
-
@objc @_inheritsConvenienceInitializers @objcMembers final public class STT : ObjectiveC.NSObject, Speech.SFSpeechRecognizerDelegate {
|
|
21
|
-
@objc weak final public var delegate: (any DavoiceTTS.STTDelegate)?
|
|
22
|
-
@objc final public var continuous: Swift.Bool
|
|
23
|
-
@objc public static let supportedEvents: [Swift.String]
|
|
24
|
-
@objc final public func isSpeechAvailable(_ completion: @escaping (Swift.Bool) -> Swift.Void)
|
|
25
|
-
@objc final public func isRecognizing() -> Swift.Bool
|
|
26
|
-
@objc final public func startSpeech(localeStr: Swift.String?)
|
|
27
|
-
@objc final public func stopSpeech(_ completion: ((Swift.Bool) -> Swift.Void)? = nil)
|
|
28
|
-
@objc final public func cancelSpeech(_ completion: ((Swift.Bool) -> Swift.Void)? = nil)
|
|
29
|
-
@objc final public func destroySpeech(_ completion: ((Swift.Bool) -> Swift.Void)? = nil)
|
|
30
|
-
@objc final public func teardown()
|
|
31
|
-
@objc final public func teardown2()
|
|
32
|
-
@objc final public func speechRecognizer(_ speechRecognizer: Speech.SFSpeechRecognizer, availabilityDidChange available: Swift.Bool)
|
|
33
|
-
@objc override dynamic public init()
|
|
34
|
-
@objc deinit
|
|
35
|
-
}
|
|
36
17
|
@objc @_inheritsConvenienceInitializers @_hasMissingDesignatedInitializers final public class SwiftSoundQueue : ObjectiveC.NSObject, AVFAudio.AVAudioPlayerDelegate {
|
|
37
18
|
@objc deinit
|
|
38
19
|
public static let shared: DavoiceTTS.SwiftSoundQueue
|
|
@@ -69,3 +50,22 @@ public enum AudioPlaybackHook {
|
|
|
69
50
|
public static var isEngineReady: DavoiceTTS.IsEngineReady?
|
|
70
51
|
public static var useOnlyEnginePlayback: DavoiceTTS.useOnlyEnginePlayback?
|
|
71
52
|
}
|
|
53
|
+
@objc public protocol STTDelegate {
|
|
54
|
+
@objc func stt(_ stt: DavoiceTTS.STT, didEmitEvent name: Swift.String, body: [Swift.String : Any]?)
|
|
55
|
+
}
|
|
56
|
+
@objc @_inheritsConvenienceInitializers @objcMembers final public class STT : ObjectiveC.NSObject, Speech.SFSpeechRecognizerDelegate {
|
|
57
|
+
@objc weak final public var delegate: (any DavoiceTTS.STTDelegate)?
|
|
58
|
+
@objc final public var continuous: Swift.Bool
|
|
59
|
+
@objc public static let supportedEvents: [Swift.String]
|
|
60
|
+
@objc final public func isSpeechAvailable(_ completion: @escaping (Swift.Bool) -> Swift.Void)
|
|
61
|
+
@objc final public func isRecognizing() -> Swift.Bool
|
|
62
|
+
@objc final public func startSpeech(localeStr: Swift.String?)
|
|
63
|
+
@objc final public func stopSpeech(_ completion: ((Swift.Bool) -> Swift.Void)? = nil)
|
|
64
|
+
@objc final public func cancelSpeech(_ completion: ((Swift.Bool) -> Swift.Void)? = nil)
|
|
65
|
+
@objc final public func destroySpeech(_ completion: ((Swift.Bool) -> Swift.Void)? = nil)
|
|
66
|
+
@objc final public func teardown()
|
|
67
|
+
@objc final public func teardown2()
|
|
68
|
+
@objc final public func speechRecognizer(_ speechRecognizer: Speech.SFSpeechRecognizer, availabilityDidChange available: Swift.Bool)
|
|
69
|
+
@objc override dynamic public init()
|
|
70
|
+
@objc deinit
|
|
71
|
+
}
|
|
@@ -14,25 +14,6 @@ import _StringProcessing
|
|
|
14
14
|
import _SwiftConcurrencyShims
|
|
15
15
|
import onnxruntime_objc
|
|
16
16
|
import phonemes
|
|
17
|
-
@objc public protocol STTDelegate {
|
|
18
|
-
@objc func stt(_ stt: DavoiceTTS.STT, didEmitEvent name: Swift.String, body: [Swift.String : Any]?)
|
|
19
|
-
}
|
|
20
|
-
@objc @_inheritsConvenienceInitializers @objcMembers final public class STT : ObjectiveC.NSObject, Speech.SFSpeechRecognizerDelegate {
|
|
21
|
-
@objc weak final public var delegate: (any DavoiceTTS.STTDelegate)?
|
|
22
|
-
@objc final public var continuous: Swift.Bool
|
|
23
|
-
@objc public static let supportedEvents: [Swift.String]
|
|
24
|
-
@objc final public func isSpeechAvailable(_ completion: @escaping (Swift.Bool) -> Swift.Void)
|
|
25
|
-
@objc final public func isRecognizing() -> Swift.Bool
|
|
26
|
-
@objc final public func startSpeech(localeStr: Swift.String?)
|
|
27
|
-
@objc final public func stopSpeech(_ completion: ((Swift.Bool) -> Swift.Void)? = nil)
|
|
28
|
-
@objc final public func cancelSpeech(_ completion: ((Swift.Bool) -> Swift.Void)? = nil)
|
|
29
|
-
@objc final public func destroySpeech(_ completion: ((Swift.Bool) -> Swift.Void)? = nil)
|
|
30
|
-
@objc final public func teardown()
|
|
31
|
-
@objc final public func teardown2()
|
|
32
|
-
@objc final public func speechRecognizer(_ speechRecognizer: Speech.SFSpeechRecognizer, availabilityDidChange available: Swift.Bool)
|
|
33
|
-
@objc override dynamic public init()
|
|
34
|
-
@objc deinit
|
|
35
|
-
}
|
|
36
17
|
@objc @_inheritsConvenienceInitializers @_hasMissingDesignatedInitializers final public class SwiftSoundQueue : ObjectiveC.NSObject, AVFAudio.AVAudioPlayerDelegate {
|
|
37
18
|
@objc deinit
|
|
38
19
|
public static let shared: DavoiceTTS.SwiftSoundQueue
|
|
@@ -69,3 +50,22 @@ public enum AudioPlaybackHook {
|
|
|
69
50
|
public static var isEngineReady: DavoiceTTS.IsEngineReady?
|
|
70
51
|
public static var useOnlyEnginePlayback: DavoiceTTS.useOnlyEnginePlayback?
|
|
71
52
|
}
|
|
53
|
+
@objc public protocol STTDelegate {
|
|
54
|
+
@objc func stt(_ stt: DavoiceTTS.STT, didEmitEvent name: Swift.String, body: [Swift.String : Any]?)
|
|
55
|
+
}
|
|
56
|
+
@objc @_inheritsConvenienceInitializers @objcMembers final public class STT : ObjectiveC.NSObject, Speech.SFSpeechRecognizerDelegate {
|
|
57
|
+
@objc weak final public var delegate: (any DavoiceTTS.STTDelegate)?
|
|
58
|
+
@objc final public var continuous: Swift.Bool
|
|
59
|
+
@objc public static let supportedEvents: [Swift.String]
|
|
60
|
+
@objc final public func isSpeechAvailable(_ completion: @escaping (Swift.Bool) -> Swift.Void)
|
|
61
|
+
@objc final public func isRecognizing() -> Swift.Bool
|
|
62
|
+
@objc final public func startSpeech(localeStr: Swift.String?)
|
|
63
|
+
@objc final public func stopSpeech(_ completion: ((Swift.Bool) -> Swift.Void)? = nil)
|
|
64
|
+
@objc final public func cancelSpeech(_ completion: ((Swift.Bool) -> Swift.Void)? = nil)
|
|
65
|
+
@objc final public func destroySpeech(_ completion: ((Swift.Bool) -> Swift.Void)? = nil)
|
|
66
|
+
@objc final public func teardown()
|
|
67
|
+
@objc final public func teardown2()
|
|
68
|
+
@objc final public func speechRecognizer(_ speechRecognizer: Speech.SFSpeechRecognizer, availabilityDidChange available: Swift.Bool)
|
|
69
|
+
@objc override dynamic public init()
|
|
70
|
+
@objc deinit
|
|
71
|
+
}
|
|
Binary file
|
|
Binary file
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
</data>
|
|
19
19
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.abi.json</key>
|
|
20
20
|
<data>
|
|
21
|
-
|
|
21
|
+
fivfg8eVNZsAD8O5/A9Y+uONgEE=
|
|
22
22
|
</data>
|
|
23
23
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface</key>
|
|
24
24
|
<data>
|
|
25
|
-
|
|
25
|
+
8Y3XQLeIfwaoU+7uGOI/ejnQmzU=
|
|
26
26
|
</data>
|
|
27
27
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftdoc</key>
|
|
28
28
|
<data>
|
|
@@ -30,19 +30,19 @@
|
|
|
30
30
|
</data>
|
|
31
31
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftinterface</key>
|
|
32
32
|
<data>
|
|
33
|
-
|
|
33
|
+
8Y3XQLeIfwaoU+7uGOI/ejnQmzU=
|
|
34
34
|
</data>
|
|
35
35
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftmodule</key>
|
|
36
36
|
<data>
|
|
37
|
-
|
|
37
|
+
bqdpNARZYCm+k3I6TD9apxWxOo8=
|
|
38
38
|
</data>
|
|
39
39
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.abi.json</key>
|
|
40
40
|
<data>
|
|
41
|
-
|
|
41
|
+
fivfg8eVNZsAD8O5/A9Y+uONgEE=
|
|
42
42
|
</data>
|
|
43
43
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface</key>
|
|
44
44
|
<data>
|
|
45
|
-
|
|
45
|
+
OdKnfC2sehdVMtSqGdsJsUvKDy0=
|
|
46
46
|
</data>
|
|
47
47
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftdoc</key>
|
|
48
48
|
<data>
|
|
@@ -50,11 +50,11 @@
|
|
|
50
50
|
</data>
|
|
51
51
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftinterface</key>
|
|
52
52
|
<data>
|
|
53
|
-
|
|
53
|
+
OdKnfC2sehdVMtSqGdsJsUvKDy0=
|
|
54
54
|
</data>
|
|
55
55
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftmodule</key>
|
|
56
56
|
<data>
|
|
57
|
-
|
|
57
|
+
pbGalSuDKtFBK6ju5uqFtv4nWj4=
|
|
58
58
|
</data>
|
|
59
59
|
<key>Modules/module.modulemap</key>
|
|
60
60
|
<data>
|
|
@@ -89,22 +89,22 @@
|
|
|
89
89
|
<dict>
|
|
90
90
|
<key>hash</key>
|
|
91
91
|
<data>
|
|
92
|
-
|
|
92
|
+
fivfg8eVNZsAD8O5/A9Y+uONgEE=
|
|
93
93
|
</data>
|
|
94
94
|
<key>hash2</key>
|
|
95
95
|
<data>
|
|
96
|
-
|
|
96
|
+
rNQyPRNJMuApbMq1gyjjFmGFsLiDnRoxQgK1WWhckY8=
|
|
97
97
|
</data>
|
|
98
98
|
</dict>
|
|
99
99
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface</key>
|
|
100
100
|
<dict>
|
|
101
101
|
<key>hash</key>
|
|
102
102
|
<data>
|
|
103
|
-
|
|
103
|
+
8Y3XQLeIfwaoU+7uGOI/ejnQmzU=
|
|
104
104
|
</data>
|
|
105
105
|
<key>hash2</key>
|
|
106
106
|
<data>
|
|
107
|
-
|
|
107
|
+
4/BSQSjWbbppLdBvyxu62gblBNBKQ/MoCJuBC5OioL4=
|
|
108
108
|
</data>
|
|
109
109
|
</dict>
|
|
110
110
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftdoc</key>
|
|
@@ -122,44 +122,44 @@
|
|
|
122
122
|
<dict>
|
|
123
123
|
<key>hash</key>
|
|
124
124
|
<data>
|
|
125
|
-
|
|
125
|
+
8Y3XQLeIfwaoU+7uGOI/ejnQmzU=
|
|
126
126
|
</data>
|
|
127
127
|
<key>hash2</key>
|
|
128
128
|
<data>
|
|
129
|
-
|
|
129
|
+
4/BSQSjWbbppLdBvyxu62gblBNBKQ/MoCJuBC5OioL4=
|
|
130
130
|
</data>
|
|
131
131
|
</dict>
|
|
132
132
|
<key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftmodule</key>
|
|
133
133
|
<dict>
|
|
134
134
|
<key>hash</key>
|
|
135
135
|
<data>
|
|
136
|
-
|
|
136
|
+
bqdpNARZYCm+k3I6TD9apxWxOo8=
|
|
137
137
|
</data>
|
|
138
138
|
<key>hash2</key>
|
|
139
139
|
<data>
|
|
140
|
-
|
|
140
|
+
IvVtse9l29epDyofiapE3u4ODUSbx16fxMnK+B1W0NA=
|
|
141
141
|
</data>
|
|
142
142
|
</dict>
|
|
143
143
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.abi.json</key>
|
|
144
144
|
<dict>
|
|
145
145
|
<key>hash</key>
|
|
146
146
|
<data>
|
|
147
|
-
|
|
147
|
+
fivfg8eVNZsAD8O5/A9Y+uONgEE=
|
|
148
148
|
</data>
|
|
149
149
|
<key>hash2</key>
|
|
150
150
|
<data>
|
|
151
|
-
|
|
151
|
+
rNQyPRNJMuApbMq1gyjjFmGFsLiDnRoxQgK1WWhckY8=
|
|
152
152
|
</data>
|
|
153
153
|
</dict>
|
|
154
154
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface</key>
|
|
155
155
|
<dict>
|
|
156
156
|
<key>hash</key>
|
|
157
157
|
<data>
|
|
158
|
-
|
|
158
|
+
OdKnfC2sehdVMtSqGdsJsUvKDy0=
|
|
159
159
|
</data>
|
|
160
160
|
<key>hash2</key>
|
|
161
161
|
<data>
|
|
162
|
-
|
|
162
|
+
Oxh3jQ93jMvHo99sWfY1bBtwfF5x/EbM+GhI0EugZs8=
|
|
163
163
|
</data>
|
|
164
164
|
</dict>
|
|
165
165
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftdoc</key>
|
|
@@ -177,22 +177,22 @@
|
|
|
177
177
|
<dict>
|
|
178
178
|
<key>hash</key>
|
|
179
179
|
<data>
|
|
180
|
-
|
|
180
|
+
OdKnfC2sehdVMtSqGdsJsUvKDy0=
|
|
181
181
|
</data>
|
|
182
182
|
<key>hash2</key>
|
|
183
183
|
<data>
|
|
184
|
-
|
|
184
|
+
Oxh3jQ93jMvHo99sWfY1bBtwfF5x/EbM+GhI0EugZs8=
|
|
185
185
|
</data>
|
|
186
186
|
</dict>
|
|
187
187
|
<key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftmodule</key>
|
|
188
188
|
<dict>
|
|
189
189
|
<key>hash</key>
|
|
190
190
|
<data>
|
|
191
|
-
|
|
191
|
+
pbGalSuDKtFBK6ju5uqFtv4nWj4=
|
|
192
192
|
</data>
|
|
193
193
|
<key>hash2</key>
|
|
194
194
|
<data>
|
|
195
|
-
|
|
195
|
+
XhUEJ5zGDgJwSvZwDv4OAX9lfe0uT3U2LpyFR+C5tNI=
|
|
196
196
|
</data>
|
|
197
197
|
</dict>
|
|
198
198
|
<key>Modules/module.modulemap</key>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-davoice-tts",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.76",
|
|
4
4
|
"description": "tts library for React Native",
|
|
5
5
|
"main": "tts/index.js",
|
|
6
6
|
"types": "tts/index.d.ts",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"files": [
|
|
13
13
|
"tts/",
|
|
14
14
|
"stt/",
|
|
15
|
+
"speech/",
|
|
15
16
|
"android/",
|
|
16
17
|
"ios/",
|
|
17
18
|
"phonemes_dir",
|
package/speech/index.ts
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { NativeModules, NativeEventEmitter, Platform } from 'react-native';
|
|
2
|
+
|
|
3
|
+
// Native handles
|
|
4
|
+
const NativeSpeech = NativeModules.SpeechBridge; // iOS unified (if present)
|
|
5
|
+
const NativeSTT =
|
|
6
|
+
NativeModules.STT ||
|
|
7
|
+
NativeModules.RCTSTT ||
|
|
8
|
+
NativeModules.Voice ||
|
|
9
|
+
NativeModules.RCTVoice;
|
|
10
|
+
const NativeTTS = NativeModules.DaVoiceTTSBridge;
|
|
11
|
+
|
|
12
|
+
// ---- Types ----
|
|
13
|
+
export type SpeechStartEvent = {};
|
|
14
|
+
export type SpeechEndEvent = {};
|
|
15
|
+
export type SpeechRecognizedEvent = { isFinal: boolean };
|
|
16
|
+
export type SpeechErrorEvent = { error: { code?: string; message?: string } };
|
|
17
|
+
export type SpeechResultsEvent = { value: string[] };
|
|
18
|
+
export type SpeechVolumeChangeEvent = { value: number };
|
|
19
|
+
|
|
20
|
+
export type UnifiedEvents = {
|
|
21
|
+
// STT
|
|
22
|
+
onSpeechStart?: (e: SpeechStartEvent) => void;
|
|
23
|
+
onSpeechRecognized?: (e: SpeechRecognizedEvent) => void;
|
|
24
|
+
onSpeechEnd?: (e: SpeechEndEvent) => void;
|
|
25
|
+
onSpeechError?: (e: SpeechErrorEvent) => void;
|
|
26
|
+
onSpeechResults?: (e: SpeechResultsEvent) => void;
|
|
27
|
+
onSpeechPartialResults?: (e: SpeechResultsEvent) => void;
|
|
28
|
+
onSpeechVolumeChanged?: (e: SpeechVolumeChangeEvent) => void;
|
|
29
|
+
// TTS
|
|
30
|
+
onFinishedSpeaking?: () => void;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
type NativeEventName =
|
|
34
|
+
| 'onSpeechStart'
|
|
35
|
+
| 'onSpeechRecognized'
|
|
36
|
+
| 'onSpeechEnd'
|
|
37
|
+
| 'onSpeechError'
|
|
38
|
+
| 'onSpeechResults'
|
|
39
|
+
| 'onSpeechPartialResults'
|
|
40
|
+
| 'onSpeechVolumeChanged'
|
|
41
|
+
| 'onFinishedSpeaking';
|
|
42
|
+
|
|
43
|
+
class Speech {
|
|
44
|
+
private sttEmitter: NativeEventEmitter | null = null;
|
|
45
|
+
private ttsEmitter: NativeEventEmitter | null = null;
|
|
46
|
+
private unifiedEmitter: NativeEventEmitter | null = null;
|
|
47
|
+
private subs: Array<{ remove: () => void }> = [];
|
|
48
|
+
private handlers: Required<UnifiedEvents>;
|
|
49
|
+
|
|
50
|
+
constructor() {
|
|
51
|
+
this.handlers = {
|
|
52
|
+
onSpeechStart: () => {},
|
|
53
|
+
onSpeechRecognized: () => {},
|
|
54
|
+
onSpeechEnd: () => {},
|
|
55
|
+
onSpeechError: () => {},
|
|
56
|
+
onSpeechResults: () => {},
|
|
57
|
+
onSpeechPartialResults: () => {},
|
|
58
|
+
onSpeechVolumeChanged: () => {},
|
|
59
|
+
onFinishedSpeaking: () => {},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Emitters per-platform
|
|
63
|
+
if (Platform.OS !== 'web') {
|
|
64
|
+
if (Platform.OS === 'ios' && NativeSpeech) {
|
|
65
|
+
this.unifiedEmitter = new NativeEventEmitter(NativeSpeech);
|
|
66
|
+
} else {
|
|
67
|
+
// Android (and iOS fallback): separate modules
|
|
68
|
+
if (NativeSTT) this.sttEmitter = new NativeEventEmitter(NativeSTT);
|
|
69
|
+
if (NativeTTS) this.ttsEmitter = new NativeEventEmitter(NativeTTS);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ---------- Init / Destroy ----------
|
|
75
|
+
/**
|
|
76
|
+
* iOS: initialize STT then TTS via native SpeechBridge if available.
|
|
77
|
+
* Android: no special init needed; optionally preload TTS (if you want).
|
|
78
|
+
*/
|
|
79
|
+
async initAll(opts: { locale: string; model: string; timeoutMs?: number }) {
|
|
80
|
+
if (Platform.OS === 'ios' && NativeSpeech?.initAll) {
|
|
81
|
+
return NativeSpeech.initAll(opts);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Fallback (Android or iOS w/o SpeechBridge):
|
|
85
|
+
// 1) Start STT (engine hot will happen internally); 2) init TTS.
|
|
86
|
+
if (!NativeSTT || !NativeTTS) {
|
|
87
|
+
throw new Error('Missing native bridges (STT/TTS).');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Start STT (best-effort; no-op if already running)
|
|
91
|
+
await new Promise<void>((resolve, reject) => {
|
|
92
|
+
try {
|
|
93
|
+
// iOS fallback signature: (locale, cb)
|
|
94
|
+
// Android signature: (locale, extras, cb)
|
|
95
|
+
if (Platform.OS === 'android' && NativeSTT.startSpeech.length >= 3) {
|
|
96
|
+
NativeSTT.startSpeech(
|
|
97
|
+
opts.locale,
|
|
98
|
+
{
|
|
99
|
+
EXTRA_LANGUAGE_MODEL: 'LANGUAGE_MODEL_FREE_FORM',
|
|
100
|
+
EXTRA_MAX_RESULTS: 5,
|
|
101
|
+
EXTRA_PARTIAL_RESULTS: true,
|
|
102
|
+
REQUEST_PERMISSIONS_AUTO: true,
|
|
103
|
+
},
|
|
104
|
+
(err: string) => (err ? reject(new Error(err)) : resolve()),
|
|
105
|
+
);
|
|
106
|
+
} else {
|
|
107
|
+
NativeSTT.startSpeech(opts.locale, (err: string) =>
|
|
108
|
+
err ? reject(new Error(err)) : resolve(),
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
} catch (e) {
|
|
112
|
+
reject(e as any);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Init TTS
|
|
117
|
+
await NativeTTS.initTTS({ model: opts.model });
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async destroyAll() {
|
|
121
|
+
// iOS unified
|
|
122
|
+
if (Platform.OS === 'ios' && NativeSpeech?.destroyAll) {
|
|
123
|
+
const r = await NativeSpeech.destroyAll();
|
|
124
|
+
this.teardownListeners();
|
|
125
|
+
return r;
|
|
126
|
+
}
|
|
127
|
+
// Fallback: destroy TTS -> STT
|
|
128
|
+
try { await NativeTTS?.destroy?.(); } catch {}
|
|
129
|
+
try {
|
|
130
|
+
await new Promise<void>((res) => {
|
|
131
|
+
if (!NativeSTT?.destroySpeech) return res();
|
|
132
|
+
NativeSTT.destroySpeech(() => res());
|
|
133
|
+
});
|
|
134
|
+
} catch {}
|
|
135
|
+
this.teardownListeners();
|
|
136
|
+
return 'Destroyed';
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ---------- STT ----------
|
|
140
|
+
async start(locale: string, options: Record<string, any> = {}) {
|
|
141
|
+
this.ensureListeners();
|
|
142
|
+
// Prefer unified on iOS
|
|
143
|
+
if (Platform.OS === 'ios' && NativeSpeech?.startSpeech) {
|
|
144
|
+
return new Promise<void>((resolve) => NativeSpeech.startSpeech(locale, () => resolve()));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Android + iOS fallback
|
|
148
|
+
return new Promise<void>((resolve, reject) => {
|
|
149
|
+
if (!NativeSTT?.startSpeech) return reject(new Error('startSpeech not available'));
|
|
150
|
+
if (Platform.OS === 'android' && NativeSTT.startSpeech.length >= 3) {
|
|
151
|
+
NativeSTT.startSpeech(
|
|
152
|
+
locale,
|
|
153
|
+
{
|
|
154
|
+
EXTRA_LANGUAGE_MODEL: 'LANGUAGE_MODEL_FREE_FORM',
|
|
155
|
+
EXTRA_MAX_RESULTS: 5,
|
|
156
|
+
EXTRA_PARTIAL_RESULTS: true,
|
|
157
|
+
REQUEST_PERMISSIONS_AUTO: true,
|
|
158
|
+
...options,
|
|
159
|
+
},
|
|
160
|
+
(err: string) => (err ? reject(new Error(err)) : resolve()),
|
|
161
|
+
);
|
|
162
|
+
} else {
|
|
163
|
+
NativeSTT.startSpeech(locale, (err: string) =>
|
|
164
|
+
err ? reject(new Error(err)) : resolve(),
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
stop(): Promise<void> {
|
|
171
|
+
if (Platform.OS === 'ios' && NativeSpeech?.stopSpeech) {
|
|
172
|
+
return new Promise((res) => NativeSpeech.stopSpeech(() => res()));
|
|
173
|
+
}
|
|
174
|
+
if (!NativeSTT?.stopSpeech) return Promise.resolve();
|
|
175
|
+
return new Promise((res) => NativeSTT.stopSpeech(() => res()));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
cancel(): Promise<void> {
|
|
179
|
+
if (Platform.OS === 'ios' && NativeSpeech?.cancelSpeech) {
|
|
180
|
+
return new Promise((res) => NativeSpeech.cancelSpeech(() => res()));
|
|
181
|
+
}
|
|
182
|
+
if (!NativeSTT?.cancelSpeech) return Promise.resolve();
|
|
183
|
+
return new Promise((res) => NativeSTT.cancelSpeech(() => res()));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
isAvailable(): Promise<0 | 1> {
|
|
187
|
+
// Prefer unified
|
|
188
|
+
if (Platform.OS === 'ios' && NativeSpeech?.isSpeechAvailable) {
|
|
189
|
+
return new Promise((resolve, reject) =>
|
|
190
|
+
NativeSpeech.isSpeechAvailable((ok: 0 | 1, err: string) =>
|
|
191
|
+
err ? reject(new Error(err)) : resolve(ok),
|
|
192
|
+
),
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
if (NativeSTT?.isSpeechAvailable) {
|
|
196
|
+
return new Promise((resolve) =>
|
|
197
|
+
NativeSTT.isSpeechAvailable((ok: 0 | 1) => resolve(ok)),
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
return Promise.resolve(1);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
isRecognizing(): Promise<0 | 1> {
|
|
204
|
+
if (Platform.OS === 'ios' && NativeSpeech?.isRecognizing) {
|
|
205
|
+
return new Promise((resolve) =>
|
|
206
|
+
NativeSpeech.isRecognizing((v: 0 | 1) => resolve(v)),
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
if (NativeSTT?.isRecognizing) {
|
|
210
|
+
return new Promise((resolve) =>
|
|
211
|
+
NativeSTT.isRecognizing((v: 0 | 1) => resolve(v)),
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
return Promise.resolve(0);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// ---------- TTS ----------
|
|
218
|
+
async initTTS(modelOrConfig: string | { model: string }) {
|
|
219
|
+
// iOS unified asks you to use initAll
|
|
220
|
+
if (Platform.OS === 'ios' && NativeSpeech?.initAll) {
|
|
221
|
+
throw new Error('Use initAll() on iOS unified bridge.');
|
|
222
|
+
}
|
|
223
|
+
const cfg = typeof modelOrConfig === 'string' ? { model: modelOrConfig } : modelOrConfig;
|
|
224
|
+
if (!cfg?.model) throw new Error("initTTS: missing 'model'");
|
|
225
|
+
return NativeTTS.initTTS(cfg);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
async speak(text: string, speakerId = 0) {
|
|
229
|
+
if (Platform.OS === 'ios' && NativeSpeech?.speak) {
|
|
230
|
+
return NativeSpeech.speak(text, speakerId);
|
|
231
|
+
}
|
|
232
|
+
if (!NativeTTS?.speak) throw new Error('TTS speak not available');
|
|
233
|
+
return NativeTTS.speak(text, speakerId);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
async stopSpeaking() {
|
|
237
|
+
if (Platform.OS === 'ios' && NativeSpeech?.stopSpeaking) {
|
|
238
|
+
return NativeSpeech.stopSpeaking();
|
|
239
|
+
}
|
|
240
|
+
if (!NativeTTS?.stopSpeaking) return;
|
|
241
|
+
return NativeTTS.stopSpeaking();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// ---------- Events ----------
|
|
245
|
+
private ensureListeners() {
|
|
246
|
+
if (this.subs.length) return;
|
|
247
|
+
|
|
248
|
+
// iOS unified: subscribe once on the unified emitter
|
|
249
|
+
if (Platform.OS === 'ios' && this.unifiedEmitter) {
|
|
250
|
+
const map: Record<NativeEventName, (...args: any[]) => void> = {
|
|
251
|
+
onSpeechStart: (e) => this.handlers.onSpeechStart(e),
|
|
252
|
+
onSpeechRecognized: (e) => this.handlers.onSpeechRecognized(e),
|
|
253
|
+
onSpeechEnd: (e) => this.handlers.onSpeechEnd(e),
|
|
254
|
+
onSpeechError: (e) => this.handlers.onSpeechError(e),
|
|
255
|
+
onSpeechResults: (e) => this.handlers.onSpeechResults(e),
|
|
256
|
+
onSpeechPartialResults: (e) => this.handlers.onSpeechPartialResults(e),
|
|
257
|
+
onSpeechVolumeChanged: (e) => this.handlers.onSpeechVolumeChanged(e),
|
|
258
|
+
onFinishedSpeaking: () => this.handlers.onFinishedSpeaking(),
|
|
259
|
+
};
|
|
260
|
+
(Object.keys(map) as NativeEventName[]).forEach((name) => {
|
|
261
|
+
try {
|
|
262
|
+
const sub = this.unifiedEmitter!.addListener(name, map[name]);
|
|
263
|
+
this.subs.push(sub);
|
|
264
|
+
} catch {}
|
|
265
|
+
});
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Android (and iOS fallback): subscribe to both STT and TTS emitters
|
|
270
|
+
if (this.sttEmitter) {
|
|
271
|
+
const sttMap = {
|
|
272
|
+
onSpeechStart: (e: any) => this.handlers.onSpeechStart(e),
|
|
273
|
+
onSpeechRecognized: (e: any) => this.handlers.onSpeechRecognized(e),
|
|
274
|
+
onSpeechEnd: (e: any) => this.handlers.onSpeechEnd(e),
|
|
275
|
+
onSpeechError: (e: any) => this.handlers.onSpeechError(e),
|
|
276
|
+
onSpeechResults: (e: any) => this.handlers.onSpeechResults(e),
|
|
277
|
+
onSpeechPartialResults: (e: any) => this.handlers.onSpeechPartialResults(e),
|
|
278
|
+
onSpeechVolumeChanged: (e: any) => this.handlers.onSpeechVolumeChanged(e),
|
|
279
|
+
};
|
|
280
|
+
(Object.keys(sttMap) as (keyof typeof sttMap)[]).forEach((name) => {
|
|
281
|
+
try {
|
|
282
|
+
const sub = this.sttEmitter!.addListener(name, sttMap[name]);
|
|
283
|
+
this.subs.push(sub);
|
|
284
|
+
} catch {}
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
if (this.ttsEmitter) {
|
|
288
|
+
try {
|
|
289
|
+
const sub = this.ttsEmitter.addListener('onFinishedSpeaking', () =>
|
|
290
|
+
this.handlers.onFinishedSpeaking(),
|
|
291
|
+
);
|
|
292
|
+
this.subs.push(sub);
|
|
293
|
+
} catch {}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
private teardownListeners() {
|
|
298
|
+
this.subs.forEach(s => { try { s.remove(); } catch {} });
|
|
299
|
+
this.subs = [];
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// ---------- Friendly setters ----------
|
|
303
|
+
set onSpeechStart(fn: (e: SpeechStartEvent) => void) { this.handlers.onSpeechStart = fn; this.ensureListeners(); }
|
|
304
|
+
set onSpeechRecognized(fn: (e: SpeechRecognizedEvent) => void) { this.handlers.onSpeechRecognized = fn; this.ensureListeners(); }
|
|
305
|
+
set onSpeechEnd(fn: (e: SpeechEndEvent) => void) { this.handlers.onSpeechEnd = fn; this.ensureListeners(); }
|
|
306
|
+
set onSpeechError(fn: (e: SpeechErrorEvent) => void) { this.handlers.onSpeechError = fn; this.ensureListeners(); }
|
|
307
|
+
set onSpeechResults(fn: (e: SpeechResultsEvent) => void) { this.handlers.onSpeechResults = fn; this.ensureListeners(); }
|
|
308
|
+
set onSpeechPartialResults(fn: (e: SpeechResultsEvent) => void) { this.handlers.onSpeechPartialResults = fn; this.ensureListeners(); }
|
|
309
|
+
set onSpeechVolumeChanged(fn: (e: SpeechVolumeChangeEvent) => void) { this.handlers.onSpeechVolumeChanged = fn; this.ensureListeners(); }
|
|
310
|
+
set onFinishedSpeaking(fn: () => void) { this.handlers.onFinishedSpeaking = fn; this.ensureListeners(); }
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const SpeechInstance = new Speech();
|
|
314
|
+
export default SpeechInstance;
|