@gmessier/nitro-speech 0.4.0 → 0.4.2
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 +56 -16
- package/android/src/main/java/com/margelo/nitro/nitrospeech/recognizer/AutoStopper.kt +7 -7
- package/android/src/main/java/com/margelo/nitro/nitrospeech/recognizer/HybridRecognizer.kt +29 -14
- package/android/src/main/java/com/margelo/nitro/nitrospeech/recognizer/Logger.kt +16 -0
- package/android/src/main/java/com/margelo/nitro/nitrospeech/recognizer/RecognitionListenerSession.kt +11 -12
- package/ios/Audio/AudioLevelTracker.swift +16 -22
- package/ios/Engines/RecognizerEngine.swift +16 -13
- package/ios/HybridRecognizer.swift +8 -0
- package/ios/Shared/AutoStopper.swift +1 -1
- package/lib/Recognizer/RecognizerRef.d.ts +2 -0
- package/lib/Recognizer/RecognizerRef.js +5 -1
- package/lib/Recognizer/SpeechRecognizer.d.ts +2 -1
- package/lib/Recognizer/SpeechRecognizer.js +2 -1
- package/lib/Recognizer/methods.d.ts +5 -3
- package/lib/Recognizer/methods.js +8 -0
- package/lib/Recognizer/types.d.ts +3 -3
- package/lib/Recognizer/useRecognizer.js +10 -9
- package/lib/Recognizer/useRecognizerIsActive.d.ts +25 -0
- package/lib/Recognizer/useRecognizerIsActive.js +40 -0
- package/lib/Recognizer/useVoiceInputVolume.d.ts +1 -1
- package/lib/index.d.ts +7 -6
- package/lib/index.js +7 -6
- package/lib/specs/Recognizer.nitro.d.ts +26 -11
- package/nitrogen/generated/android/c++/JHybridRecognizerSpec.cpp +5 -0
- package/nitrogen/generated/android/c++/JHybridRecognizerSpec.hpp +1 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrospeech/HybridRecognizerSpec.kt +4 -0
- package/nitrogen/generated/ios/NitroSpeech-Swift-Cxx-Bridge.hpp +9 -0
- package/nitrogen/generated/ios/c++/HybridRecognizerSpecSwift.hpp +8 -0
- package/nitrogen/generated/ios/swift/HybridRecognizerSpec.swift +1 -0
- package/nitrogen/generated/ios/swift/HybridRecognizerSpec_cxx.swift +12 -0
- package/nitrogen/generated/shared/c++/HybridRecognizerSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridRecognizerSpec.hpp +1 -0
- package/package.json +1 -1
- package/src/Recognizer/RecognizerRef.ts +6 -0
- package/src/Recognizer/SpeechRecognizer.ts +2 -1
- package/src/Recognizer/methods.ts +16 -3
- package/src/Recognizer/types.ts +7 -1
- package/src/Recognizer/useRecognizer.ts +11 -7
- package/src/Recognizer/useRecognizerIsActive.ts +49 -0
- package/src/Recognizer/useVoiceInputVolume.ts +1 -1
- package/src/index.ts +20 -6
- package/src/specs/Recognizer.nitro.ts +27 -11
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import type { SpeechRecognitionConfig } from './types';
|
|
2
|
-
export declare const
|
|
1
|
+
import type { MutableSpeechRecognitionConfig, SpeechRecognitionConfig } from './types';
|
|
2
|
+
export declare const recognizerPrewarm: (params?: SpeechRecognitionConfig) => Promise<void>;
|
|
3
|
+
export declare const recognizerStartListening: (params?: SpeechRecognitionConfig) => void;
|
|
3
4
|
export declare const recognizerStopListening: () => void;
|
|
4
5
|
export declare const recognizerResetAutoFinishTime: () => void;
|
|
5
6
|
export declare const recognizerAddAutoFinishTime: (additionalTimeMs?: number) => void;
|
|
6
|
-
export declare const recognizerUpdateConfig: (newConfig
|
|
7
|
+
export declare const recognizerUpdateConfig: (newConfig?: MutableSpeechRecognitionConfig, resetAutoFinishTime?: boolean) => void;
|
|
7
8
|
export declare const recognizerGetIsActive: () => boolean;
|
|
9
|
+
export declare const recognizerGetVoiceInputVolume: () => import("./types").VolumeChangeEvent;
|
|
8
10
|
export declare const recognizerGetSupportedLocalesIOS: () => string[];
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { SpeechRecognizer } from './SpeechRecognizer';
|
|
2
|
+
export const recognizerPrewarm = (params) => {
|
|
3
|
+
'worklet';
|
|
4
|
+
return SpeechRecognizer.prewarm(params);
|
|
5
|
+
};
|
|
2
6
|
export const recognizerStartListening = (params) => {
|
|
3
7
|
'worklet';
|
|
4
8
|
SpeechRecognizer.startListening(params);
|
|
@@ -23,6 +27,10 @@ export const recognizerGetIsActive = () => {
|
|
|
23
27
|
'worklet';
|
|
24
28
|
return SpeechRecognizer.getIsActive();
|
|
25
29
|
};
|
|
30
|
+
export const recognizerGetVoiceInputVolume = () => {
|
|
31
|
+
'worklet';
|
|
32
|
+
return SpeechRecognizer.getVoiceInputVolume();
|
|
33
|
+
};
|
|
26
34
|
export const recognizerGetSupportedLocalesIOS = () => {
|
|
27
35
|
'worklet';
|
|
28
36
|
return SpeechRecognizer.getSupportedLocalesIOS().sort();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Recognizer as RecognizerSpec } from '../specs/Recognizer.nitro';
|
|
2
|
-
import type { SpeechRecognitionConfig } from '../specs/SpeechRecognitionConfig';
|
|
2
|
+
import type { MutableSpeechRecognitionConfig, SpeechRecognitionConfig } from '../specs/SpeechRecognitionConfig';
|
|
3
3
|
import type { VolumeChangeEvent } from '../specs/VolumeChangeEvent';
|
|
4
4
|
type RecognizerCallbacks = Pick<RecognizerSpec, 'onReadyForSpeech' | 'onRecordingStopped' | 'onResult' | 'onAutoFinishProgress' | 'onError' | 'onPermissionDenied' | 'onVolumeChange'>;
|
|
5
|
-
type RecognizerMethods = Pick<RecognizerSpec, 'startListening' | 'stopListening' | 'resetAutoFinishTime' | 'addAutoFinishTime' | 'updateConfig' | 'getIsActive' | 'getSupportedLocalesIOS'>;
|
|
6
|
-
export type { RecognizerSpec, SpeechRecognitionConfig, VolumeChangeEvent, RecognizerCallbacks, RecognizerMethods, };
|
|
5
|
+
type RecognizerMethods = Pick<RecognizerSpec, 'prewarm' | 'startListening' | 'stopListening' | 'resetAutoFinishTime' | 'addAutoFinishTime' | 'updateConfig' | 'getIsActive' | 'getVoiceInputVolume' | 'getSupportedLocalesIOS'>;
|
|
6
|
+
export type { RecognizerSpec, SpeechRecognitionConfig, MutableSpeechRecognitionConfig, VolumeChangeEvent, RecognizerCallbacks, RecognizerMethods, };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { useEffect } from 'react';
|
|
2
|
-
import { recognizerResetAutoFinishTime, recognizerAddAutoFinishTime, recognizerUpdateConfig, recognizerGetIsActive, recognizerGetSupportedLocalesIOS, recognizerStartListening, recognizerStopListening, } from './methods';
|
|
2
|
+
import { recognizerResetAutoFinishTime, recognizerAddAutoFinishTime, recognizerUpdateConfig, recognizerGetIsActive, recognizerGetSupportedLocalesIOS, recognizerStartListening, recognizerStopListening, recognizerGetVoiceInputVolume, recognizerPrewarm, } from './methods';
|
|
3
3
|
import { SpeechRecognizer } from './SpeechRecognizer';
|
|
4
4
|
import { speechRecognizerVolumeChangeHandler } from './useVoiceInputVolume';
|
|
5
|
+
import { speechRecognizerActiveStateHandler } from './useRecognizerIsActive';
|
|
5
6
|
/**
|
|
6
7
|
* Safe, lifecycle-aware hook to use the recognizer.
|
|
7
8
|
*
|
|
@@ -17,18 +18,12 @@ import { speechRecognizerVolumeChangeHandler } from './useVoiceInputVolume';
|
|
|
17
18
|
*/
|
|
18
19
|
export const useRecognizer = (callbacks, destroyDeps = []) => {
|
|
19
20
|
useEffect(() => {
|
|
20
|
-
if (callbacks.onVolumeChange) {
|
|
21
|
-
SpeechRecognizer.onVolumeChange = (event) => {
|
|
22
|
-
callbacks.onVolumeChange?.(event);
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
SpeechRecognizer.onVolumeChange = speechRecognizerVolumeChangeHandler;
|
|
27
|
-
}
|
|
28
21
|
SpeechRecognizer.onReadyForSpeech = () => {
|
|
22
|
+
speechRecognizerActiveStateHandler(true);
|
|
29
23
|
callbacks.onReadyForSpeech?.();
|
|
30
24
|
};
|
|
31
25
|
SpeechRecognizer.onRecordingStopped = () => {
|
|
26
|
+
speechRecognizerActiveStateHandler(false);
|
|
32
27
|
callbacks.onRecordingStopped?.();
|
|
33
28
|
};
|
|
34
29
|
SpeechRecognizer.onResult = (resultBatches) => {
|
|
@@ -43,6 +38,10 @@ export const useRecognizer = (callbacks, destroyDeps = []) => {
|
|
|
43
38
|
SpeechRecognizer.onPermissionDenied = () => {
|
|
44
39
|
callbacks.onPermissionDenied?.();
|
|
45
40
|
};
|
|
41
|
+
SpeechRecognizer.onVolumeChange = (event) => {
|
|
42
|
+
speechRecognizerVolumeChangeHandler(event);
|
|
43
|
+
callbacks.onVolumeChange?.(event);
|
|
44
|
+
};
|
|
46
45
|
return () => {
|
|
47
46
|
SpeechRecognizer.onReadyForSpeech = undefined;
|
|
48
47
|
SpeechRecognizer.onRecordingStopped = undefined;
|
|
@@ -60,12 +59,14 @@ export const useRecognizer = (callbacks, destroyDeps = []) => {
|
|
|
60
59
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
61
60
|
}, [...destroyDeps]);
|
|
62
61
|
return {
|
|
62
|
+
prewarm: recognizerPrewarm,
|
|
63
63
|
startListening: recognizerStartListening,
|
|
64
64
|
stopListening: recognizerStopListening,
|
|
65
65
|
resetAutoFinishTime: recognizerResetAutoFinishTime,
|
|
66
66
|
addAutoFinishTime: recognizerAddAutoFinishTime,
|
|
67
67
|
updateConfig: recognizerUpdateConfig,
|
|
68
68
|
getIsActive: recognizerGetIsActive,
|
|
69
|
+
getVoiceInputVolume: recognizerGetVoiceInputVolume,
|
|
69
70
|
getSupportedLocalesIOS: recognizerGetSupportedLocalesIOS,
|
|
70
71
|
};
|
|
71
72
|
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
type OnActiveStateChange = (isActive: boolean) => void;
|
|
2
|
+
/**
|
|
3
|
+
* Returns true if the speech recognition session is active.
|
|
4
|
+
*/
|
|
5
|
+
export declare const useRecognizerIsActive: () => boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Direct access to default Speech Recognizer isActive state change handler.
|
|
8
|
+
*
|
|
9
|
+
* In case you use static Speech Recognizer:
|
|
10
|
+
*
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { speechRecognizerActiveStateHandler } from '@gmessier/nitro-speech'
|
|
13
|
+
*
|
|
14
|
+
* SpeechRecognizer.onReadyForSpeech = () => {
|
|
15
|
+
* speechRecognizerActiveStateHandler(true)
|
|
16
|
+
* }
|
|
17
|
+
* SpeechRecognizer.onRecordingStopped = () => {
|
|
18
|
+
* speechRecognizerActiveStateHandler(false)
|
|
19
|
+
* }
|
|
20
|
+
* ... // setup everything else
|
|
21
|
+
* SpeechRecognizer.startListening({ locale: 'en-US' })
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare const speechRecognizerActiveStateHandler: OnActiveStateChange;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useSyncExternalStore } from 'react';
|
|
2
|
+
const subscribers = new Set();
|
|
3
|
+
let recognizerIsActive = false;
|
|
4
|
+
const getSnapshot = () => {
|
|
5
|
+
return recognizerIsActive;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Returns true if the speech recognition session is active.
|
|
9
|
+
*/
|
|
10
|
+
export const useRecognizerIsActive = () => {
|
|
11
|
+
return useSyncExternalStore((subscriber) => {
|
|
12
|
+
subscribers.add(subscriber);
|
|
13
|
+
return () => subscribers.delete(subscriber);
|
|
14
|
+
}, getSnapshot);
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Direct access to default Speech Recognizer isActive state change handler.
|
|
18
|
+
*
|
|
19
|
+
* In case you use static Speech Recognizer:
|
|
20
|
+
*
|
|
21
|
+
* ```typescript
|
|
22
|
+
* import { speechRecognizerActiveStateHandler } from '@gmessier/nitro-speech'
|
|
23
|
+
*
|
|
24
|
+
* SpeechRecognizer.onReadyForSpeech = () => {
|
|
25
|
+
* speechRecognizerActiveStateHandler(true)
|
|
26
|
+
* }
|
|
27
|
+
* SpeechRecognizer.onRecordingStopped = () => {
|
|
28
|
+
* speechRecognizerActiveStateHandler(false)
|
|
29
|
+
* }
|
|
30
|
+
* ... // setup everything else
|
|
31
|
+
* SpeechRecognizer.startListening({ locale: 'en-US' })
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export const speechRecognizerActiveStateHandler = (isActive) => {
|
|
35
|
+
if (isActive === recognizerIsActive) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
recognizerIsActive = isActive;
|
|
39
|
+
subscribers.forEach((subscriber) => subscriber?.(isActive));
|
|
40
|
+
};
|
package/lib/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
1
|
+
export { useRecognizer } from './Recognizer/useRecognizer';
|
|
2
|
+
export { useVoiceInputVolume, speechRecognizerVolumeChangeHandler, } from './Recognizer/useVoiceInputVolume';
|
|
3
|
+
export { useRecognizerIsActive, speechRecognizerActiveStateHandler, } from './Recognizer/useRecognizerIsActive';
|
|
4
|
+
export { SpeechRecognizer } from './Recognizer/SpeechRecognizer';
|
|
5
|
+
export { RecognizerRef } from './Recognizer/RecognizerRef';
|
|
6
|
+
export { NitroSpeech } from './NitroSpeech';
|
|
7
|
+
export { type RecognizerSpec, type SpeechRecognitionConfig, type MutableSpeechRecognitionConfig, type VolumeChangeEvent, type RecognizerCallbacks, type RecognizerMethods, } from './Recognizer/types';
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
1
|
+
export { useRecognizer } from './Recognizer/useRecognizer';
|
|
2
|
+
export { useVoiceInputVolume, speechRecognizerVolumeChangeHandler, } from './Recognizer/useVoiceInputVolume';
|
|
3
|
+
export { useRecognizerIsActive, speechRecognizerActiveStateHandler, } from './Recognizer/useRecognizerIsActive';
|
|
4
|
+
export { SpeechRecognizer } from './Recognizer/SpeechRecognizer';
|
|
5
|
+
export { RecognizerRef } from './Recognizer/RecognizerRef';
|
|
6
|
+
export { NitroSpeech } from './NitroSpeech';
|
|
7
|
+
export {} from './Recognizer/types';
|
|
@@ -8,9 +8,24 @@ export interface Recognizer extends HybridObject<{
|
|
|
8
8
|
/**
|
|
9
9
|
* Prepare the speech recognition engine and the model for the given parameters.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* @notes
|
|
12
|
+
* - Not required, {@linkcode startListening} will prewarm automatically.
|
|
13
|
+
*
|
|
14
|
+
* - Omit the {@linkcode Promise} result if you want to run synchronously.
|
|
12
15
|
* {@linkcode startListening} will start and resolve it automatically.
|
|
13
|
-
*
|
|
16
|
+
*
|
|
17
|
+
* - Only `await` if run beforehand and you want to react to the success
|
|
18
|
+
*
|
|
19
|
+
* @worklet **Do not** use `await` on Worklet or UI runtimes. It will not work properly.
|
|
20
|
+
*
|
|
21
|
+
* You can run it synchronously:
|
|
22
|
+
* ```typescript
|
|
23
|
+
* scheduleOnRuntime(workletRuntime, () => {
|
|
24
|
+
* RecognizerRef.prewarm({
|
|
25
|
+
* // your config to prepare
|
|
26
|
+
* });
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
14
29
|
*/
|
|
15
30
|
prewarm(defaultParams?: SpeechRecognitionConfig): Promise<void>;
|
|
16
31
|
/**
|
|
@@ -24,9 +39,9 @@ export interface Recognizer extends HybridObject<{
|
|
|
24
39
|
*/
|
|
25
40
|
startListening(params?: SpeechRecognitionConfig): void;
|
|
26
41
|
/**
|
|
27
|
-
* Stops the speech recognition.
|
|
42
|
+
* Stops the speech recognition. If not started, does nothing.
|
|
28
43
|
*
|
|
29
|
-
* Not a sync operation for
|
|
44
|
+
* Not a sync operation for Android, delay about 250ms to polish the result.
|
|
30
45
|
*
|
|
31
46
|
* Use {@linkcode onRecordingStopped} to handle the stop event.
|
|
32
47
|
*/
|
|
@@ -52,6 +67,10 @@ export interface Recognizer extends HybridObject<{
|
|
|
52
67
|
* Returns true if the speech recognition is active.
|
|
53
68
|
*/
|
|
54
69
|
getIsActive(): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Returns the current voice input volume.
|
|
72
|
+
*/
|
|
73
|
+
getVoiceInputVolume(): VolumeChangeEvent;
|
|
55
74
|
/**
|
|
56
75
|
* Returns a list of supported locales.
|
|
57
76
|
*
|
|
@@ -67,15 +86,13 @@ export interface Recognizer extends HybridObject<{
|
|
|
67
86
|
*/
|
|
68
87
|
onRecordingStopped?: () => void;
|
|
69
88
|
/**
|
|
70
|
-
*
|
|
89
|
+
* Fires each time either a new batch has been added or the last batch has been updated.
|
|
71
90
|
*/
|
|
72
91
|
onResult?: (resultBatches: string[]) => void;
|
|
73
92
|
/**
|
|
74
|
-
*
|
|
93
|
+
* Fires every {@linkcode SpeechRecognitionConfig.autoFinishProgressIntervalMs} or 1000ms
|
|
75
94
|
*
|
|
76
95
|
* Time left in milliseconds until the timer stops.
|
|
77
|
-
*
|
|
78
|
-
* @note not implemented for Android yet.
|
|
79
96
|
*/
|
|
80
97
|
onAutoFinishProgress?: (timeLeftMs: number) => void;
|
|
81
98
|
/**
|
|
@@ -87,9 +104,7 @@ export interface Recognizer extends HybridObject<{
|
|
|
87
104
|
*/
|
|
88
105
|
onPermissionDenied?: () => void;
|
|
89
106
|
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* @warning overriding it will disable the built-in `useVoiceInputVolume` hook.
|
|
107
|
+
* Fires with high and arbitrary frequency (many times per second) while audio recording is active.
|
|
93
108
|
*/
|
|
94
109
|
onVolumeChange?: (event: VolumeChangeEvent) => void;
|
|
95
110
|
}
|
|
@@ -233,6 +233,11 @@ namespace margelo::nitro::nitrospeech {
|
|
|
233
233
|
auto __result = method(_javaPart);
|
|
234
234
|
return static_cast<bool>(__result);
|
|
235
235
|
}
|
|
236
|
+
VolumeChangeEvent JHybridRecognizerSpec::getVoiceInputVolume() {
|
|
237
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JVolumeChangeEvent>()>("getVoiceInputVolume");
|
|
238
|
+
auto __result = method(_javaPart);
|
|
239
|
+
return __result->toCpp();
|
|
240
|
+
}
|
|
236
241
|
std::vector<std::string> JHybridRecognizerSpec::getSupportedLocalesIOS() {
|
|
237
242
|
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JArrayClass<jni::JString>>()>("getSupportedLocalesIOS");
|
|
238
243
|
auto __result = method(_javaPart);
|
|
@@ -74,6 +74,7 @@ namespace margelo::nitro::nitrospeech {
|
|
|
74
74
|
void addAutoFinishTime(std::optional<double> additionalTimeMs) override;
|
|
75
75
|
void updateConfig(const std::optional<MutableSpeechRecognitionConfig>& newConfig, std::optional<bool> resetAutoFinishTime) override;
|
|
76
76
|
bool getIsActive() override;
|
|
77
|
+
VolumeChangeEvent getVoiceInputVolume() override;
|
|
77
78
|
std::vector<std::string> getSupportedLocalesIOS() override;
|
|
78
79
|
|
|
79
80
|
private:
|
package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrospeech/HybridRecognizerSpec.kt
CHANGED
|
@@ -153,6 +153,10 @@ abstract class HybridRecognizerSpec: HybridObject() {
|
|
|
153
153
|
@Keep
|
|
154
154
|
abstract fun getIsActive(): Boolean
|
|
155
155
|
|
|
156
|
+
@DoNotStrip
|
|
157
|
+
@Keep
|
|
158
|
+
abstract fun getVoiceInputVolume(): VolumeChangeEvent
|
|
159
|
+
|
|
156
160
|
@DoNotStrip
|
|
157
161
|
@Keep
|
|
158
162
|
abstract fun getSupportedLocalesIOS(): Array<String>
|
|
@@ -454,6 +454,15 @@ namespace margelo::nitro::nitrospeech::bridge::swift {
|
|
|
454
454
|
return Result<bool>::withError(error);
|
|
455
455
|
}
|
|
456
456
|
|
|
457
|
+
// pragma MARK: Result<VolumeChangeEvent>
|
|
458
|
+
using Result_VolumeChangeEvent_ = Result<VolumeChangeEvent>;
|
|
459
|
+
inline Result_VolumeChangeEvent_ create_Result_VolumeChangeEvent_(const VolumeChangeEvent& value) noexcept {
|
|
460
|
+
return Result<VolumeChangeEvent>::withValue(value);
|
|
461
|
+
}
|
|
462
|
+
inline Result_VolumeChangeEvent_ create_Result_VolumeChangeEvent_(const std::exception_ptr& error) noexcept {
|
|
463
|
+
return Result<VolumeChangeEvent>::withError(error);
|
|
464
|
+
}
|
|
465
|
+
|
|
457
466
|
// pragma MARK: Result<std::vector<std::string>>
|
|
458
467
|
using Result_std__vector_std__string__ = Result<std::vector<std::string>>;
|
|
459
468
|
inline Result_std__vector_std__string__ create_Result_std__vector_std__string__(const std::vector<std::string>& value) noexcept {
|
|
@@ -178,6 +178,14 @@ namespace margelo::nitro::nitrospeech {
|
|
|
178
178
|
auto __value = std::move(__result.value());
|
|
179
179
|
return __value;
|
|
180
180
|
}
|
|
181
|
+
inline VolumeChangeEvent getVoiceInputVolume() override {
|
|
182
|
+
auto __result = _swiftPart.getVoiceInputVolume();
|
|
183
|
+
if (__result.hasError()) [[unlikely]] {
|
|
184
|
+
std::rethrow_exception(__result.error());
|
|
185
|
+
}
|
|
186
|
+
auto __value = std::move(__result.value());
|
|
187
|
+
return __value;
|
|
188
|
+
}
|
|
181
189
|
inline std::vector<std::string> getSupportedLocalesIOS() override {
|
|
182
190
|
auto __result = _swiftPart.getSupportedLocalesIOS();
|
|
183
191
|
if (__result.hasError()) [[unlikely]] {
|
|
@@ -26,6 +26,7 @@ public protocol HybridRecognizerSpec_protocol: HybridObject {
|
|
|
26
26
|
func addAutoFinishTime(additionalTimeMs: Double?) throws -> Void
|
|
27
27
|
func updateConfig(newConfig: MutableSpeechRecognitionConfig?, resetAutoFinishTime: Bool?) throws -> Void
|
|
28
28
|
func getIsActive() throws -> Bool
|
|
29
|
+
func getVoiceInputVolume() throws -> VolumeChangeEvent
|
|
29
30
|
func getSupportedLocalesIOS() throws -> [String]
|
|
30
31
|
}
|
|
31
32
|
|
|
@@ -452,6 +452,18 @@ open class HybridRecognizerSpec_cxx {
|
|
|
452
452
|
}
|
|
453
453
|
}
|
|
454
454
|
|
|
455
|
+
@inline(__always)
|
|
456
|
+
public final func getVoiceInputVolume() -> bridge.Result_VolumeChangeEvent_ {
|
|
457
|
+
do {
|
|
458
|
+
let __result = try self.__implementation.getVoiceInputVolume()
|
|
459
|
+
let __resultCpp = __result
|
|
460
|
+
return bridge.create_Result_VolumeChangeEvent_(__resultCpp)
|
|
461
|
+
} catch (let __error) {
|
|
462
|
+
let __exceptionPtr = __error.toCpp()
|
|
463
|
+
return bridge.create_Result_VolumeChangeEvent_(__exceptionPtr)
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
455
467
|
@inline(__always)
|
|
456
468
|
public final func getSupportedLocalesIOS() -> bridge.Result_std__vector_std__string__ {
|
|
457
469
|
do {
|
|
@@ -35,6 +35,7 @@ namespace margelo::nitro::nitrospeech {
|
|
|
35
35
|
prototype.registerHybridMethod("addAutoFinishTime", &HybridRecognizerSpec::addAutoFinishTime);
|
|
36
36
|
prototype.registerHybridMethod("updateConfig", &HybridRecognizerSpec::updateConfig);
|
|
37
37
|
prototype.registerHybridMethod("getIsActive", &HybridRecognizerSpec::getIsActive);
|
|
38
|
+
prototype.registerHybridMethod("getVoiceInputVolume", &HybridRecognizerSpec::getVoiceInputVolume);
|
|
38
39
|
prototype.registerHybridMethod("getSupportedLocalesIOS", &HybridRecognizerSpec::getSupportedLocalesIOS);
|
|
39
40
|
});
|
|
40
41
|
}
|
|
@@ -80,6 +80,7 @@ namespace margelo::nitro::nitrospeech {
|
|
|
80
80
|
virtual void addAutoFinishTime(std::optional<double> additionalTimeMs) = 0;
|
|
81
81
|
virtual void updateConfig(const std::optional<MutableSpeechRecognitionConfig>& newConfig, std::optional<bool> resetAutoFinishTime) = 0;
|
|
82
82
|
virtual bool getIsActive() = 0;
|
|
83
|
+
virtual VolumeChangeEvent getVoiceInputVolume() = 0;
|
|
83
84
|
virtual std::vector<std::string> getSupportedLocalesIOS() = 0;
|
|
84
85
|
|
|
85
86
|
protected:
|
package/package.json
CHANGED
|
@@ -7,17 +7,23 @@ import {
|
|
|
7
7
|
recognizerStartListening,
|
|
8
8
|
recognizerStopListening,
|
|
9
9
|
recognizerUpdateConfig,
|
|
10
|
+
recognizerGetVoiceInputVolume,
|
|
11
|
+
recognizerPrewarm,
|
|
10
12
|
} from './methods'
|
|
11
13
|
|
|
12
14
|
/**
|
|
13
15
|
* Safe cross-component reference to the Speech Recognizer methods.
|
|
16
|
+
*
|
|
17
|
+
* All methods support worklets and UI thread calls
|
|
14
18
|
*/
|
|
15
19
|
export const RecognizerRef: RecognizerMethods = {
|
|
20
|
+
prewarm: recognizerPrewarm,
|
|
16
21
|
startListening: recognizerStartListening,
|
|
17
22
|
stopListening: recognizerStopListening,
|
|
18
23
|
resetAutoFinishTime: recognizerResetAutoFinishTime,
|
|
19
24
|
addAutoFinishTime: recognizerAddAutoFinishTime,
|
|
20
25
|
updateConfig: recognizerUpdateConfig,
|
|
21
26
|
getIsActive: recognizerGetIsActive,
|
|
27
|
+
getVoiceInputVolume: recognizerGetVoiceInputVolume,
|
|
22
28
|
getSupportedLocalesIOS: recognizerGetSupportedLocalesIOS,
|
|
23
29
|
}
|
|
@@ -5,6 +5,7 @@ import { NitroSpeech } from '../NitroSpeech'
|
|
|
5
5
|
*
|
|
6
6
|
* Direct access to the all Speech Recognizer methods and callbacks.
|
|
7
7
|
*
|
|
8
|
-
* @note
|
|
8
|
+
* @note Unsafe, might lead to race conditions
|
|
9
|
+
* @warning Since it reflects the original hybrid object, its API may change in the future.
|
|
9
10
|
*/
|
|
10
11
|
export const SpeechRecognizer = NitroSpeech.recognizer
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { SpeechRecognizer } from './SpeechRecognizer'
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
MutableSpeechRecognitionConfig,
|
|
4
|
+
SpeechRecognitionConfig,
|
|
5
|
+
} from './types'
|
|
3
6
|
|
|
4
|
-
export const
|
|
7
|
+
export const recognizerPrewarm = (params?: SpeechRecognitionConfig) => {
|
|
8
|
+
'worklet'
|
|
9
|
+
return SpeechRecognizer.prewarm(params)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const recognizerStartListening = (params?: SpeechRecognitionConfig) => {
|
|
5
13
|
'worklet'
|
|
6
14
|
SpeechRecognizer.startListening(params)
|
|
7
15
|
}
|
|
@@ -22,7 +30,7 @@ export const recognizerAddAutoFinishTime = (additionalTimeMs?: number) => {
|
|
|
22
30
|
}
|
|
23
31
|
|
|
24
32
|
export const recognizerUpdateConfig = (
|
|
25
|
-
newConfig
|
|
33
|
+
newConfig?: MutableSpeechRecognitionConfig,
|
|
26
34
|
resetAutoFinishTime?: boolean
|
|
27
35
|
) => {
|
|
28
36
|
'worklet'
|
|
@@ -34,6 +42,11 @@ export const recognizerGetIsActive = () => {
|
|
|
34
42
|
return SpeechRecognizer.getIsActive()
|
|
35
43
|
}
|
|
36
44
|
|
|
45
|
+
export const recognizerGetVoiceInputVolume = () => {
|
|
46
|
+
'worklet'
|
|
47
|
+
return SpeechRecognizer.getVoiceInputVolume()
|
|
48
|
+
}
|
|
49
|
+
|
|
37
50
|
export const recognizerGetSupportedLocalesIOS = () => {
|
|
38
51
|
'worklet'
|
|
39
52
|
return SpeechRecognizer.getSupportedLocalesIOS().sort()
|
package/src/Recognizer/types.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { Recognizer as RecognizerSpec } from '../specs/Recognizer.nitro'
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
MutableSpeechRecognitionConfig,
|
|
4
|
+
SpeechRecognitionConfig,
|
|
5
|
+
} from '../specs/SpeechRecognitionConfig'
|
|
3
6
|
import type { VolumeChangeEvent } from '../specs/VolumeChangeEvent'
|
|
4
7
|
|
|
5
8
|
type RecognizerCallbacks = Pick<
|
|
@@ -15,18 +18,21 @@ type RecognizerCallbacks = Pick<
|
|
|
15
18
|
|
|
16
19
|
type RecognizerMethods = Pick<
|
|
17
20
|
RecognizerSpec,
|
|
21
|
+
| 'prewarm'
|
|
18
22
|
| 'startListening'
|
|
19
23
|
| 'stopListening'
|
|
20
24
|
| 'resetAutoFinishTime'
|
|
21
25
|
| 'addAutoFinishTime'
|
|
22
26
|
| 'updateConfig'
|
|
23
27
|
| 'getIsActive'
|
|
28
|
+
| 'getVoiceInputVolume'
|
|
24
29
|
| 'getSupportedLocalesIOS'
|
|
25
30
|
>
|
|
26
31
|
|
|
27
32
|
export type {
|
|
28
33
|
RecognizerSpec,
|
|
29
34
|
SpeechRecognitionConfig,
|
|
35
|
+
MutableSpeechRecognitionConfig,
|
|
30
36
|
VolumeChangeEvent,
|
|
31
37
|
RecognizerCallbacks,
|
|
32
38
|
RecognizerMethods,
|
|
@@ -7,10 +7,13 @@ import {
|
|
|
7
7
|
recognizerGetSupportedLocalesIOS,
|
|
8
8
|
recognizerStartListening,
|
|
9
9
|
recognizerStopListening,
|
|
10
|
+
recognizerGetVoiceInputVolume,
|
|
11
|
+
recognizerPrewarm,
|
|
10
12
|
} from './methods'
|
|
11
13
|
import type { RecognizerCallbacks, RecognizerMethods } from './types'
|
|
12
14
|
import { SpeechRecognizer } from './SpeechRecognizer'
|
|
13
15
|
import { speechRecognizerVolumeChangeHandler } from './useVoiceInputVolume'
|
|
16
|
+
import { speechRecognizerActiveStateHandler } from './useRecognizerIsActive'
|
|
14
17
|
|
|
15
18
|
/**
|
|
16
19
|
* Safe, lifecycle-aware hook to use the recognizer.
|
|
@@ -30,17 +33,12 @@ export const useRecognizer = (
|
|
|
30
33
|
destroyDeps: DependencyList = []
|
|
31
34
|
): RecognizerMethods => {
|
|
32
35
|
useEffect(() => {
|
|
33
|
-
if (callbacks.onVolumeChange) {
|
|
34
|
-
SpeechRecognizer.onVolumeChange = (event) => {
|
|
35
|
-
callbacks.onVolumeChange?.(event)
|
|
36
|
-
}
|
|
37
|
-
} else {
|
|
38
|
-
SpeechRecognizer.onVolumeChange = speechRecognizerVolumeChangeHandler
|
|
39
|
-
}
|
|
40
36
|
SpeechRecognizer.onReadyForSpeech = () => {
|
|
37
|
+
speechRecognizerActiveStateHandler(true)
|
|
41
38
|
callbacks.onReadyForSpeech?.()
|
|
42
39
|
}
|
|
43
40
|
SpeechRecognizer.onRecordingStopped = () => {
|
|
41
|
+
speechRecognizerActiveStateHandler(false)
|
|
44
42
|
callbacks.onRecordingStopped?.()
|
|
45
43
|
}
|
|
46
44
|
SpeechRecognizer.onResult = (resultBatches: string[]) => {
|
|
@@ -55,6 +53,10 @@ export const useRecognizer = (
|
|
|
55
53
|
SpeechRecognizer.onPermissionDenied = () => {
|
|
56
54
|
callbacks.onPermissionDenied?.()
|
|
57
55
|
}
|
|
56
|
+
SpeechRecognizer.onVolumeChange = (event) => {
|
|
57
|
+
speechRecognizerVolumeChangeHandler(event)
|
|
58
|
+
callbacks.onVolumeChange?.(event)
|
|
59
|
+
}
|
|
58
60
|
return () => {
|
|
59
61
|
SpeechRecognizer.onReadyForSpeech = undefined
|
|
60
62
|
SpeechRecognizer.onRecordingStopped = undefined
|
|
@@ -74,12 +76,14 @@ export const useRecognizer = (
|
|
|
74
76
|
}, [...destroyDeps])
|
|
75
77
|
|
|
76
78
|
return {
|
|
79
|
+
prewarm: recognizerPrewarm,
|
|
77
80
|
startListening: recognizerStartListening,
|
|
78
81
|
stopListening: recognizerStopListening,
|
|
79
82
|
resetAutoFinishTime: recognizerResetAutoFinishTime,
|
|
80
83
|
addAutoFinishTime: recognizerAddAutoFinishTime,
|
|
81
84
|
updateConfig: recognizerUpdateConfig,
|
|
82
85
|
getIsActive: recognizerGetIsActive,
|
|
86
|
+
getVoiceInputVolume: recognizerGetVoiceInputVolume,
|
|
83
87
|
getSupportedLocalesIOS: recognizerGetSupportedLocalesIOS,
|
|
84
88
|
}
|
|
85
89
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { useSyncExternalStore } from 'react'
|
|
2
|
+
|
|
3
|
+
type OnActiveStateChange = (isActive: boolean) => void
|
|
4
|
+
|
|
5
|
+
const subscribers = new Set<OnActiveStateChange>()
|
|
6
|
+
|
|
7
|
+
let recognizerIsActive = false
|
|
8
|
+
|
|
9
|
+
const getSnapshot = () => {
|
|
10
|
+
return recognizerIsActive
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Returns true if the speech recognition session is active.
|
|
15
|
+
*/
|
|
16
|
+
export const useRecognizerIsActive = () => {
|
|
17
|
+
return useSyncExternalStore((subscriber) => {
|
|
18
|
+
subscribers.add(subscriber)
|
|
19
|
+
return () => subscribers.delete(subscriber)
|
|
20
|
+
}, getSnapshot)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Direct access to default Speech Recognizer isActive state change handler.
|
|
25
|
+
*
|
|
26
|
+
* In case you use static Speech Recognizer:
|
|
27
|
+
*
|
|
28
|
+
* ```typescript
|
|
29
|
+
* import { speechRecognizerActiveStateHandler } from '@gmessier/nitro-speech'
|
|
30
|
+
*
|
|
31
|
+
* SpeechRecognizer.onReadyForSpeech = () => {
|
|
32
|
+
* speechRecognizerActiveStateHandler(true)
|
|
33
|
+
* }
|
|
34
|
+
* SpeechRecognizer.onRecordingStopped = () => {
|
|
35
|
+
* speechRecognizerActiveStateHandler(false)
|
|
36
|
+
* }
|
|
37
|
+
* ... // setup everything else
|
|
38
|
+
* SpeechRecognizer.startListening({ locale: 'en-US' })
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export const speechRecognizerActiveStateHandler: OnActiveStateChange = (
|
|
42
|
+
isActive
|
|
43
|
+
) => {
|
|
44
|
+
if (isActive === recognizerIsActive) {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
recognizerIsActive = isActive
|
|
48
|
+
subscribers.forEach((subscriber) => subscriber?.(isActive))
|
|
49
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useSyncExternalStore } from 'react'
|
|
2
2
|
import type { RecognizerSpec, VolumeChangeEvent } from './types'
|
|
3
3
|
|
|
4
|
-
type OnVolumeChange = RecognizerSpec['onVolumeChange']
|
|
4
|
+
type OnVolumeChange = Exclude<RecognizerSpec['onVolumeChange'], undefined>
|
|
5
5
|
|
|
6
6
|
const subscribers = new Set<OnVolumeChange>()
|
|
7
7
|
|