@gmessier/nitro-speech 0.1.2 → 0.2.0

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 (41) hide show
  1. package/README.md +64 -11
  2. package/android/build.gradle +2 -0
  3. package/android/src/main/java/com/margelo/nitro/nitrospeech/recognizer/HapticImpact.kt +11 -1
  4. package/android/src/main/java/com/margelo/nitro/nitrospeech/recognizer/HybridRecognizer.kt +12 -6
  5. package/android/src/main/java/com/margelo/nitro/nitrospeech/recognizer/RecognitionListenerSession.kt +73 -7
  6. package/ios/AnylyzerTranscriber.swift +331 -0
  7. package/ios/AutoStopper.swift +9 -10
  8. package/ios/BufferUtil.swift +80 -0
  9. package/ios/HapticImpact.swift +12 -3
  10. package/ios/HybridNitroSpeech.swift +10 -1
  11. package/ios/HybridRecognizer.swift +139 -167
  12. package/ios/LegacySpeechRecognizer.swift +161 -0
  13. package/lib/commonjs/index.js +54 -5
  14. package/lib/commonjs/index.js.map +1 -1
  15. package/lib/module/index.js +52 -3
  16. package/lib/module/index.js.map +1 -1
  17. package/lib/tsconfig.tsbuildinfo +1 -1
  18. package/lib/typescript/index.d.ts +25 -8
  19. package/lib/typescript/index.d.ts.map +1 -1
  20. package/lib/typescript/specs/NitroSpeech.nitro.d.ts +24 -12
  21. package/lib/typescript/specs/NitroSpeech.nitro.d.ts.map +1 -1
  22. package/nitrogen/generated/android/c++/JHapticFeedbackStyle.hpp +3 -0
  23. package/nitrogen/generated/android/c++/JHybridRecognizerSpec.cpp +22 -0
  24. package/nitrogen/generated/android/c++/JHybridRecognizerSpec.hpp +3 -0
  25. package/nitrogen/generated/android/c++/JSpeechToTextParams.hpp +4 -4
  26. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrospeech/HapticFeedbackStyle.kt +2 -1
  27. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrospeech/HybridRecognizerSpec.kt +18 -0
  28. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrospeech/SpeechToTextParams.kt +3 -3
  29. package/nitrogen/generated/ios/NitroSpeech-Swift-Cxx-Bridge.hpp +24 -0
  30. package/nitrogen/generated/ios/c++/HybridRecognizerSpecSwift.hpp +15 -0
  31. package/nitrogen/generated/ios/swift/HapticFeedbackStyle.swift +4 -0
  32. package/nitrogen/generated/ios/swift/HybridRecognizerSpec.swift +2 -0
  33. package/nitrogen/generated/ios/swift/HybridRecognizerSpec_cxx.swift +44 -0
  34. package/nitrogen/generated/ios/swift/SpeechToTextParams.swift +6 -6
  35. package/nitrogen/generated/shared/c++/HapticFeedbackStyle.hpp +4 -0
  36. package/nitrogen/generated/shared/c++/HybridRecognizerSpec.cpp +3 -0
  37. package/nitrogen/generated/shared/c++/HybridRecognizerSpec.hpp +3 -0
  38. package/nitrogen/generated/shared/c++/SpeechToTextParams.hpp +5 -5
  39. package/package.json +7 -7
  40. package/src/index.ts +59 -2
  41. package/src/specs/NitroSpeech.nitro.ts +25 -12
package/src/index.ts CHANGED
@@ -1,4 +1,3 @@
1
- /* eslint-disable react-hooks/exhaustive-deps */
2
1
  import React from 'react'
3
2
  import { NitroModules } from 'react-native-nitro-modules'
4
3
  import type {
@@ -23,6 +22,7 @@ type RecognizerCallbacks = Pick<
23
22
  | 'onAutoFinishProgress'
24
23
  | 'onError'
25
24
  | 'onPermissionDenied'
25
+ | 'onVolumeChange'
26
26
  >
27
27
 
28
28
  type RecognizerHandlers = Pick<
@@ -31,6 +31,7 @@ type RecognizerHandlers = Pick<
31
31
  | 'stopListening'
32
32
  | 'addAutoFinishTime'
33
33
  | 'updateAutoFinishTime'
34
+ | 'getIsActive'
34
35
  >
35
36
 
36
37
  const recognizerStartListening = (params: SpeechToTextParams) => {
@@ -52,6 +53,51 @@ const recognizerUpdateAutoFinishTime = (
52
53
  RecognizerSession.updateAutoFinishTime(newTimeMs, withRefresh)
53
54
  }
54
55
 
56
+ const recognizerGetIsActive = () => {
57
+ return RecognizerSession.getIsActive()
58
+ }
59
+
60
+ const subscribers = new Set<RecognizerSpec['onVolumeChange']>()
61
+ let currentVolume = 0
62
+
63
+ /**
64
+ * Subscription to the voice input volume changes
65
+ *
66
+ * Updates with arbitrary frequency (many times per second) while audio recording is active.
67
+ *
68
+ * @returns The current voice input volume normalized to a range of 0 to 1.
69
+ */
70
+ export const useVoiceInputVolume = () => {
71
+ return React.useSyncExternalStore(
72
+ (subscriber) => {
73
+ subscribers.add(subscriber)
74
+ return () => subscribers.delete(subscriber)
75
+ },
76
+ () => currentVolume
77
+ )
78
+ }
79
+
80
+ const handleVolumeChange: RecognizerSpec['onVolumeChange'] = (normVolume) => {
81
+ if (normVolume === currentVolume) return
82
+ currentVolume = normVolume
83
+ subscribers.forEach((subscriber) => subscriber?.(normVolume))
84
+ }
85
+
86
+ /**
87
+ * Unsafe access to default Recognizer Session's volume change handler.
88
+ *
89
+ * In case you use static Recognizer Session:
90
+ *
91
+ * ```typescript
92
+ * import { unsafe_onVolumeChange } from '@gmessier/nitro-speech'
93
+ *
94
+ * RecognizerSession.onVolumeChange = unsafe_onVolumeChange
95
+ * ... // do something
96
+ * RecognizerSession.startListening({ locale: 'en-US' })
97
+ * ```
98
+ */
99
+ export const unsafe_onVolumeChange = handleVolumeChange
100
+
55
101
  /**
56
102
  * Safe, lifecycle-aware hook to use the recognizer.
57
103
  *
@@ -70,6 +116,13 @@ export const useRecognizer = (
70
116
  destroyDeps: React.DependencyList = []
71
117
  ): RecognizerHandlers => {
72
118
  React.useEffect(() => {
119
+ if (callbacks.onVolumeChange) {
120
+ RecognizerSession.onVolumeChange = (normVolume: number) => {
121
+ callbacks.onVolumeChange?.(normVolume)
122
+ }
123
+ } else {
124
+ RecognizerSession.onVolumeChange = handleVolumeChange
125
+ }
73
126
  RecognizerSession.onReadyForSpeech = () => {
74
127
  callbacks.onReadyForSpeech?.()
75
128
  }
@@ -95,6 +148,7 @@ export const useRecognizer = (
95
148
  RecognizerSession.onAutoFinishProgress = undefined
96
149
  RecognizerSession.onError = undefined
97
150
  RecognizerSession.onPermissionDenied = undefined
151
+ RecognizerSession.onVolumeChange = undefined
98
152
  }
99
153
  }, [callbacks])
100
154
 
@@ -102,6 +156,7 @@ export const useRecognizer = (
102
156
  return () => {
103
157
  RecognizerSession.stopListening()
104
158
  }
159
+ // eslint-disable-next-line react-hooks/exhaustive-deps
105
160
  }, [...destroyDeps])
106
161
 
107
162
  return {
@@ -109,17 +164,19 @@ export const useRecognizer = (
109
164
  stopListening: recognizerStopListening,
110
165
  addAutoFinishTime: recognizerAddAutoFinishTime,
111
166
  updateAutoFinishTime: recognizerUpdateAutoFinishTime,
167
+ getIsActive: recognizerGetIsActive,
112
168
  }
113
169
  }
114
170
 
115
171
  /**
116
172
  * Safe reference to the Recognizer methods.
117
173
  */
118
- export const RecognizerRef = {
174
+ export const RecognizerRef: RecognizerHandlers = {
119
175
  startListening: recognizerStartListening,
120
176
  stopListening: recognizerStopListening,
121
177
  addAutoFinishTime: recognizerAddAutoFinishTime,
122
178
  updateAutoFinishTime: recognizerUpdateAutoFinishTime,
179
+ getIsActive: recognizerGetIsActive,
123
180
  }
124
181
 
125
182
  export type { RecognizerCallbacks, RecognizerHandlers, SpeechToTextParams }
@@ -1,18 +1,12 @@
1
1
  import { type HybridObject } from 'react-native-nitro-modules'
2
2
 
3
3
  interface ParamsAndroid {
4
- /**
5
- * Default - false
6
- *
7
- * Min Android 13
8
- */
9
- androidMaskOffensiveWords?: boolean
10
4
  /**
11
5
  * Default - false
12
6
  *
13
7
  * Prefer quality over latency (may break autofinish timing, depends on engine)
14
8
  *
15
- * Min Android 13
9
+ * Android 13+
16
10
  */
17
11
  androidFormattingPreferQuality?: boolean
18
12
  /**
@@ -39,12 +33,12 @@ interface ParamsIOS {
39
33
  *
40
34
  * Adds punctuation to speech recognition results
41
35
  *
42
- * Min iOS 16
36
+ * iOS 16+
43
37
  */
44
38
  iosAddPunctuation?: boolean
45
39
  }
46
40
 
47
- type HapticFeedbackStyle = 'light' | 'medium' | 'heavy'
41
+ type HapticFeedbackStyle = 'light' | 'medium' | 'heavy' | 'none'
48
42
 
49
43
  export interface SpeechToTextParams extends ParamsAndroid, ParamsIOS {
50
44
  /**
@@ -68,17 +62,25 @@ export interface SpeechToTextParams extends ParamsAndroid, ParamsIOS {
68
62
  */
69
63
  contextualStrings?: string[]
70
64
  /**
71
- * Default - null
65
+ * Default - "medium"
72
66
  *
73
67
  * Haptic feedback style when microphone starts recording.
74
68
  */
75
69
  startHapticFeedbackStyle?: HapticFeedbackStyle
76
70
  /**
77
- * Default - null
71
+ * Default - "medium"
78
72
  *
79
73
  * Haptic feedback style when microphone stops recording.
80
74
  */
81
75
  stopHapticFeedbackStyle?: HapticFeedbackStyle
76
+ /**
77
+ * Default - false
78
+ *
79
+ * Android 13+
80
+ *
81
+ * iOS 26+ (iOS <26: always `false`)
82
+ */
83
+ maskOffensiveWords?: boolean
82
84
  }
83
85
 
84
86
  export interface Recognizer extends HybridObject<{
@@ -119,12 +121,17 @@ export interface Recognizer extends HybridObject<{
119
121
  */
120
122
  updateAutoFinishTime(newTimeMs: number, withRefresh?: boolean): void
121
123
 
124
+ /**
125
+ * Returns true if the speech recognition is active.
126
+ */
127
+ getIsActive(): boolean
128
+
122
129
  /**
123
130
  * The speech recognition has started.
124
131
  */
125
132
  onReadyForSpeech?: () => void
126
133
  /**
127
- * Audio recording has stopped. (may be called multiple times for one recording)
134
+ * Audio recording has stopped.
128
135
  */
129
136
  onRecordingStopped?: () => void
130
137
  /**
@@ -147,6 +154,12 @@ export interface Recognizer extends HybridObject<{
147
154
  * Permission to record audio has been denied.
148
155
  */
149
156
  onPermissionDenied?: () => void
157
+ /**
158
+ * Called with arbitrary frequency (many times per second) while audio recording is active.
159
+ *
160
+ * Voice input volume normalized to a range of 0 to 1.
161
+ */
162
+ onVolumeChange?: (normVolume: number) => void
150
163
  }
151
164
 
152
165
  export interface NitroSpeech extends HybridObject<{