react-native-voice-ts 1.0.1 → 1.0.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.
@@ -35,6 +35,18 @@ export interface VoiceMicrophoneProps {
35
35
  * @default true
36
36
  */
37
37
  enablePartialResults?: boolean;
38
+ /**
39
+ * Whether to continue listening after getting results (continuous mode)
40
+ * When enabled, the microphone will automatically restart after getting results
41
+ * @default false
42
+ */
43
+ continuous?: boolean;
44
+ /**
45
+ * Maximum silence duration in milliseconds before stopping (continuous mode)
46
+ * Only applies when continuous mode is enabled
47
+ * @default 5000 (5 seconds)
48
+ */
49
+ maxSilenceDuration?: number;
38
50
  /**
39
51
  * Custom render function for the component
40
52
  * Receives isRecording state and control functions
@@ -1 +1 @@
1
- {"version":3,"file":"VoiceMicrophone.d.ts","sourceRoot":"","sources":["../../src/components/VoiceMicrophone.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAIhE,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAExC;;OAEG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAEzC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAErB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;QACjB,WAAW,EAAE,OAAO,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;KACtB,KAAK,KAAK,CAAC,SAAS,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAiJnD,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"VoiceMicrophone.d.ts","sourceRoot":"","sources":["../../src/components/VoiceMicrophone.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAIhE,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAExC;;OAEG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAEzC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAErB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;QACjB,WAAW,EAAE,OAAO,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;KACtB,KAAK,KAAK,CAAC,SAAS,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA8OnD,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -27,33 +27,77 @@ import Voice from '../index';
27
27
  * </VoiceMicrophone>
28
28
  * ```
29
29
  */
30
- const VoiceMicrophone = ({ onSpeechResult, onPartialResult, onStart, onStop, onError, locale = 'en-US', autoStart = false, enablePartialResults = true, children, }) => {
30
+ const VoiceMicrophone = ({ onSpeechResult, onPartialResult, onStart, onStop, onError, locale = 'en-US', autoStart = false, enablePartialResults = true, continuous = false, maxSilenceDuration = 5000, children, }) => {
31
31
  const [isRecording, setIsRecording] = useState(false);
32
32
  const [recognizedText, setRecognizedText] = useState('');
33
33
  const [partialText, setPartialText] = useState('');
34
34
  const [error, setError] = useState(null);
35
+ const [shouldContinue, setShouldContinue] = useState(false);
36
+ const silenceTimerRef = React.useRef(null);
37
+ useEffect(() => {
38
+ // Clear any existing timers on cleanup
39
+ return () => {
40
+ if (silenceTimerRef.current) {
41
+ clearTimeout(silenceTimerRef.current);
42
+ }
43
+ };
44
+ }, []);
35
45
  useEffect(() => {
36
46
  // Set up event listeners
37
47
  Voice.onSpeechStart = () => {
38
48
  setIsRecording(true);
39
49
  setError(null);
50
+ if (silenceTimerRef.current) {
51
+ clearTimeout(silenceTimerRef.current);
52
+ }
40
53
  onStart?.();
41
54
  };
42
- Voice.onSpeechEnd = () => {
55
+ Voice.onSpeechEnd = async () => {
43
56
  setIsRecording(false);
44
- onStop?.();
57
+ // In continuous mode, restart listening after results
58
+ if (continuous && shouldContinue) {
59
+ // Small delay before restarting
60
+ setTimeout(async () => {
61
+ if (shouldContinue) {
62
+ try {
63
+ await Voice.start(locale, {
64
+ EXTRA_PARTIAL_RESULTS: enablePartialResults,
65
+ });
66
+ }
67
+ catch (err) {
68
+ console.error('Failed to restart voice recognition:', err);
69
+ }
70
+ }
71
+ }, 100);
72
+ }
73
+ else {
74
+ onStop?.();
75
+ }
45
76
  };
46
77
  Voice.onSpeechError = (e) => {
47
78
  const errorMessage = e.error?.message || 'Unknown error';
48
79
  setError(errorMessage);
49
80
  setIsRecording(false);
81
+ setShouldContinue(false);
82
+ if (silenceTimerRef.current) {
83
+ clearTimeout(silenceTimerRef.current);
84
+ }
50
85
  onError?.(errorMessage);
51
86
  };
52
87
  Voice.onSpeechResults = (e) => {
53
88
  if (e.value && e.value.length > 0) {
54
89
  const text = e.value[0];
55
- setRecognizedText(text);
56
- onSpeechResult?.(text);
90
+ // In continuous mode, append new text to existing
91
+ if (continuous && recognizedText) {
92
+ const updatedText = recognizedText + ' ' + text;
93
+ setRecognizedText(updatedText);
94
+ onSpeechResult?.(updatedText);
95
+ }
96
+ else {
97
+ setRecognizedText(text);
98
+ onSpeechResult?.(text);
99
+ }
100
+ setPartialText('');
57
101
  }
58
102
  };
59
103
  if (enablePartialResults) {
@@ -62,6 +106,15 @@ const VoiceMicrophone = ({ onSpeechResult, onPartialResult, onStart, onStop, onE
62
106
  const text = e.value[0];
63
107
  setPartialText(text);
64
108
  onPartialResult?.(text);
109
+ // Reset silence timer on partial results (user is speaking)
110
+ if (continuous && silenceTimerRef.current) {
111
+ clearTimeout(silenceTimerRef.current);
112
+ silenceTimerRef.current = setTimeout(() => {
113
+ if (shouldContinue) {
114
+ stop();
115
+ }
116
+ }, maxSilenceDuration);
117
+ }
65
118
  }
66
119
  };
67
120
  }
@@ -76,6 +129,11 @@ const VoiceMicrophone = ({ onSpeechResult, onPartialResult, onStart, onStop, onE
76
129
  onStop,
77
130
  onError,
78
131
  enablePartialResults,
132
+ continuous,
133
+ shouldContinue,
134
+ recognizedText,
135
+ locale,
136
+ maxSilenceDuration,
79
137
  ]);
80
138
  // Auto-start if enabled
81
139
  useEffect(() => {
@@ -87,8 +145,11 @@ const VoiceMicrophone = ({ onSpeechResult, onPartialResult, onStart, onStop, onE
87
145
  const start = useCallback(async () => {
88
146
  try {
89
147
  setError(null);
90
- setRecognizedText('');
91
- setPartialText('');
148
+ if (!continuous) {
149
+ setRecognizedText('');
150
+ setPartialText('');
151
+ }
152
+ setShouldContinue(true);
92
153
  // Check permission (Android only)
93
154
  const hasPermission = await Voice.checkMicrophonePermission();
94
155
  if (!hasPermission) {
@@ -101,25 +162,52 @@ const VoiceMicrophone = ({ onSpeechResult, onPartialResult, onStart, onStop, onE
101
162
  await Voice.start(locale, {
102
163
  EXTRA_PARTIAL_RESULTS: enablePartialResults,
103
164
  });
165
+ // Start silence timer if in continuous mode
166
+ if (continuous) {
167
+ silenceTimerRef.current = setTimeout(() => {
168
+ if (shouldContinue) {
169
+ stop();
170
+ }
171
+ }, maxSilenceDuration);
172
+ }
104
173
  }
105
174
  catch (e) {
106
175
  const errorMessage = e instanceof Error ? e.message : 'Failed to start recording';
107
176
  setError(errorMessage);
177
+ setShouldContinue(false);
108
178
  onError?.(errorMessage);
109
179
  }
110
- }, [locale, enablePartialResults, onError]);
180
+ }, [
181
+ locale,
182
+ enablePartialResults,
183
+ onError,
184
+ continuous,
185
+ maxSilenceDuration,
186
+ shouldContinue,
187
+ ]);
111
188
  const stop = useCallback(async () => {
112
189
  try {
190
+ setShouldContinue(false);
191
+ if (silenceTimerRef.current) {
192
+ clearTimeout(silenceTimerRef.current);
193
+ silenceTimerRef.current = null;
194
+ }
113
195
  await Voice.stop();
196
+ onStop?.();
114
197
  }
115
198
  catch (e) {
116
199
  const errorMessage = e instanceof Error ? e.message : 'Failed to stop recording';
117
200
  setError(errorMessage);
118
201
  onError?.(errorMessage);
119
202
  }
120
- }, [onError]);
203
+ }, [onError, onStop]);
121
204
  const cancel = useCallback(async () => {
122
205
  try {
206
+ setShouldContinue(false);
207
+ if (silenceTimerRef.current) {
208
+ clearTimeout(silenceTimerRef.current);
209
+ silenceTimerRef.current = null;
210
+ }
123
211
  await Voice.cancel();
124
212
  setRecognizedText('');
125
213
  setPartialText('');
@@ -1 +1 @@
1
- {"version":3,"file":"VoiceMicrophone.js","sourceRoot":"","sources":["../../src/components/VoiceMicrophone.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"VoiceMicrophone.js","sourceRoot":"","sources":["../../src/components/VoiceMicrophone.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAChE,OAAO,KAAK,MAAM,UAAU,CAAC;AA4E7B;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,eAAe,GAAmC,CAAC,EACvD,cAAc,EACd,eAAe,EACf,OAAO,EACP,MAAM,EACN,OAAO,EACP,MAAM,GAAG,OAAO,EAChB,SAAS,GAAG,KAAK,EACjB,oBAAoB,GAAG,IAAI,EAC3B,UAAU,GAAG,KAAK,EAClB,kBAAkB,GAAG,IAAI,EACzB,QAAQ,GACT,EAAE,EAAE;IACH,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzD,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACxD,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5D,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,CAAwB,IAAI,CAAC,CAAC;IAElE,SAAS,CAAC,GAAG,EAAE;QACb,uCAAuC;QACvC,OAAO,GAAG,EAAE;YACV,IAAI,eAAe,CAAC,OAAO,EAAE,CAAC;gBAC5B,YAAY,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YACxC,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,SAAS,CAAC,GAAG,EAAE;QACb,yBAAyB;QACzB,KAAK,CAAC,aAAa,GAAG,GAAG,EAAE;YACzB,cAAc,CAAC,IAAI,CAAC,CAAC;YACrB,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,IAAI,eAAe,CAAC,OAAO,EAAE,CAAC;gBAC5B,YAAY,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YACxC,CAAC;YACD,OAAO,EAAE,EAAE,CAAC;QACd,CAAC,CAAC;QAEF,KAAK,CAAC,WAAW,GAAG,KAAK,IAAI,EAAE;YAC7B,cAAc,CAAC,KAAK,CAAC,CAAC;YAEtB,sDAAsD;YACtD,IAAI,UAAU,IAAI,cAAc,EAAE,CAAC;gBACjC,gCAAgC;gBAChC,UAAU,CAAC,KAAK,IAAI,EAAE;oBACpB,IAAI,cAAc,EAAE,CAAC;wBACnB,IAAI,CAAC;4BACH,MAAM,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE;gCACxB,qBAAqB,EAAE,oBAAoB;6BAC5C,CAAC,CAAC;wBACL,CAAC;wBAAC,OAAO,GAAG,EAAE,CAAC;4BACb,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,GAAG,CAAC,CAAC;wBAC7D,CAAC;oBACH,CAAC;gBACH,CAAC,EAAE,GAAG,CAAC,CAAC;YACV,CAAC;iBAAM,CAAC;gBACN,MAAM,EAAE,EAAE,CAAC;YACb,CAAC;QACH,CAAC,CAAC;QAEF,KAAK,CAAC,aAAa,GAAG,CAAC,CAAmB,EAAE,EAAE;YAC5C,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,EAAE,OAAO,IAAI,eAAe,CAAC;YACzD,QAAQ,CAAC,YAAY,CAAC,CAAC;YACvB,cAAc,CAAC,KAAK,CAAC,CAAC;YACtB,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACzB,IAAI,eAAe,CAAC,OAAO,EAAE,CAAC;gBAC5B,YAAY,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YACxC,CAAC;YACD,OAAO,EAAE,CAAC,YAAY,CAAC,CAAC;QAC1B,CAAC,CAAC;QAEF,KAAK,CAAC,eAAe,GAAG,CAAC,CAAqB,EAAE,EAAE;YAChD,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAClC,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAExB,kDAAkD;gBAClD,IAAI,UAAU,IAAI,cAAc,EAAE,CAAC;oBACjC,MAAM,WAAW,GAAG,cAAc,GAAG,GAAG,GAAG,IAAI,CAAC;oBAChD,iBAAiB,CAAC,WAAW,CAAC,CAAC;oBAC/B,cAAc,EAAE,CAAC,WAAW,CAAC,CAAC;gBAChC,CAAC;qBAAM,CAAC;oBACN,iBAAiB,CAAC,IAAI,CAAC,CAAC;oBACxB,cAAc,EAAE,CAAC,IAAI,CAAC,CAAC;gBACzB,CAAC;gBAED,cAAc,CAAC,EAAE,CAAC,CAAC;YACrB,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,oBAAoB,EAAE,CAAC;YACzB,KAAK,CAAC,sBAAsB,GAAG,CAAC,CAAqB,EAAE,EAAE;gBACvD,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAClC,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;oBACxB,cAAc,CAAC,IAAI,CAAC,CAAC;oBACrB,eAAe,EAAE,CAAC,IAAI,CAAC,CAAC;oBAExB,4DAA4D;oBAC5D,IAAI,UAAU,IAAI,eAAe,CAAC,OAAO,EAAE,CAAC;wBAC1C,YAAY,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;wBACtC,eAAe,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;4BACxC,IAAI,cAAc,EAAE,CAAC;gCACnB,IAAI,EAAE,CAAC;4BACT,CAAC;wBACH,CAAC,EAAE,kBAAkB,CAAC,CAAC;oBACzB,CAAC;gBACH,CAAC;YACH,CAAC,CAAC;QACJ,CAAC;QAED,UAAU;QACV,OAAO,GAAG,EAAE;YACV,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACjD,CAAC,CAAC;IACJ,CAAC,EAAE;QACD,cAAc;QACd,eAAe;QACf,OAAO;QACP,MAAM;QACN,OAAO;QACP,oBAAoB;QACpB,UAAU;QACV,cAAc;QACd,cAAc;QACd,MAAM;QACN,kBAAkB;KACnB,CAAC,CAAC;IAEH,wBAAwB;IACxB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS,EAAE,CAAC;YACd,KAAK,EAAE,CAAC;QACV,CAAC;QACD,uDAAuD;IACzD,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;IAEhB,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACnC,IAAI,CAAC;YACH,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,iBAAiB,CAAC,EAAE,CAAC,CAAC;gBACtB,cAAc,CAAC,EAAE,CAAC,CAAC;YACrB,CAAC;YACD,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAExB,kCAAkC;YAClC,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,yBAAyB,EAAE,CAAC;YAC9D,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnB,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,2BAA2B,EAAE,CAAC;gBAC1D,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,QAAQ,CAAC,8BAA8B,CAAC,CAAC;oBACzC,OAAO;gBACT,CAAC;YACH,CAAC;YAED,MAAM,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE;gBACxB,qBAAqB,EAAE,oBAAoB;aAC5C,CAAC,CAAC;YAEH,4CAA4C;YAC5C,IAAI,UAAU,EAAE,CAAC;gBACf,eAAe,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;oBACxC,IAAI,cAAc,EAAE,CAAC;wBACnB,IAAI,EAAE,CAAC;oBACT,CAAC;gBACH,CAAC,EAAE,kBAAkB,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,YAAY,GAChB,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC;YAC/D,QAAQ,CAAC,YAAY,CAAC,CAAC;YACvB,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACzB,OAAO,EAAE,CAAC,YAAY,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,EAAE;QACD,MAAM;QACN,oBAAoB;QACpB,OAAO;QACP,UAAU;QACV,kBAAkB;QAClB,cAAc;KACf,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAClC,IAAI,CAAC;YACH,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACzB,IAAI,eAAe,CAAC,OAAO,EAAE,CAAC;gBAC5B,YAAY,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;gBACtC,eAAe,CAAC,OAAO,GAAG,IAAI,CAAC;YACjC,CAAC;YACD,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,MAAM,EAAE,EAAE,CAAC;QACb,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,YAAY,GAChB,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC;YAC9D,QAAQ,CAAC,YAAY,CAAC,CAAC;YACvB,OAAO,EAAE,CAAC,YAAY,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAEtB,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACpC,IAAI,CAAC;YACH,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACzB,IAAI,eAAe,CAAC,OAAO,EAAE,CAAC;gBAC5B,YAAY,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;gBACtC,eAAe,CAAC,OAAO,GAAG,IAAI,CAAC;YACjC,CAAC;YACD,MAAM,KAAK,CAAC,MAAM,EAAE,CAAC;YACrB,iBAAiB,CAAC,EAAE,CAAC,CAAC;YACtB,cAAc,CAAC,EAAE,CAAC,CAAC;QACrB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,YAAY,GAChB,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC;YAChE,QAAQ,CAAC,YAAY,CAAC,CAAC;YACvB,OAAO,EAAE,CAAC,YAAY,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,8CAA8C;IAC9C,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CACL,EACE;QAAA,CAAC,QAAQ,CAAC;gBACR,WAAW;gBACX,cAAc;gBACd,WAAW;gBACX,KAAK;gBACL,IAAI;gBACJ,MAAM;gBACN,KAAK;aACN,CAAC,CACJ;MAAA,GAAG,CACJ,CAAC;IACJ,CAAC;IAED,+CAA+C;IAC/C,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -9,6 +9,18 @@ export interface UseVoiceRecognitionOptions {
9
9
  * @default true
10
10
  */
11
11
  enablePartialResults?: boolean;
12
+ /**
13
+ * Whether to continue listening after getting results (continuous mode)
14
+ * When enabled, the microphone will automatically restart after getting results
15
+ * @default false
16
+ */
17
+ continuous?: boolean;
18
+ /**
19
+ * Maximum silence duration in milliseconds before stopping (continuous mode)
20
+ * Only applies when continuous mode is enabled
21
+ * @default 5000 (5 seconds)
22
+ */
23
+ maxSilenceDuration?: number;
12
24
  /**
13
25
  * Callback fired when speech is recognized
14
26
  */
@@ -1 +1 @@
1
- {"version":3,"file":"useVoiceRecognition.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoiceRecognition.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,yBAAyB;IACxC;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;IAElB;;OAEG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IAEzB;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAErB;;OAEG;IACH,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3B;;OAEG;IACH,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1B;;OAEG;IACH,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;OAEG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,mBAAmB,GAC9B,UAAS,0BAA+B,KACvC,yBA2HF,CAAC"}
1
+ {"version":3,"file":"useVoiceRecognition.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoiceRecognition.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,yBAAyB;IACxC;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;IAElB;;OAEG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IAEzB;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAErB;;OAEG;IACH,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3B;;OAEG;IACH,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1B;;OAEG;IACH,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;OAEG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,mBAAmB,GAC9B,UAAS,0BAA+B,KACvC,yBAiOF,CAAC"}
@@ -1,4 +1,4 @@
1
- import { useEffect, useState, useCallback } from 'react';
1
+ import React, { useEffect, useState, useCallback } from 'react';
2
2
  import Voice from '../index';
3
3
  /**
4
4
  * Custom hook for voice recognition
@@ -22,32 +22,76 @@ import Voice from '../index';
22
22
  * ```
23
23
  */
24
24
  export const useVoiceRecognition = (options = {}) => {
25
- const { locale = 'en-US', enablePartialResults = true, onResult, onError, } = options;
25
+ const { locale = 'en-US', enablePartialResults = true, continuous = false, maxSilenceDuration = 5000, onResult, onError, } = options;
26
26
  const [isRecording, setIsRecording] = useState(false);
27
27
  const [results, setResults] = useState([]);
28
28
  const [partialResults, setPartialResults] = useState([]);
29
29
  const [error, setError] = useState(null);
30
+ const [shouldContinue, setShouldContinue] = useState(false);
31
+ const silenceTimerRef = React.useRef(null);
32
+ const accumulatedTextRef = React.useRef('');
33
+ useEffect(() => {
34
+ // Clear any existing timers on cleanup
35
+ return () => {
36
+ if (silenceTimerRef.current) {
37
+ clearTimeout(silenceTimerRef.current);
38
+ }
39
+ };
40
+ }, []);
30
41
  useEffect(() => {
31
42
  // Set up event listeners
32
43
  Voice.onSpeechStart = () => {
33
44
  setIsRecording(true);
34
45
  setError(null);
46
+ if (silenceTimerRef.current) {
47
+ clearTimeout(silenceTimerRef.current);
48
+ }
35
49
  };
36
- Voice.onSpeechEnd = () => {
50
+ Voice.onSpeechEnd = async () => {
37
51
  setIsRecording(false);
52
+ // In continuous mode, restart listening after results
53
+ if (continuous && shouldContinue) {
54
+ setTimeout(async () => {
55
+ if (shouldContinue) {
56
+ try {
57
+ await Voice.start(locale, {
58
+ EXTRA_PARTIAL_RESULTS: enablePartialResults,
59
+ });
60
+ }
61
+ catch (err) {
62
+ console.error('Failed to restart voice recognition:', err);
63
+ }
64
+ }
65
+ }, 100);
66
+ }
38
67
  };
39
68
  Voice.onSpeechError = (e) => {
40
69
  const errorMessage = e.error?.message || 'Unknown error';
41
70
  setError(errorMessage);
42
71
  setIsRecording(false);
72
+ setShouldContinue(false);
73
+ if (silenceTimerRef.current) {
74
+ clearTimeout(silenceTimerRef.current);
75
+ }
43
76
  onError?.(errorMessage);
44
77
  };
45
78
  Voice.onSpeechResults = (e) => {
46
79
  if (e.value && e.value.length > 0) {
47
- setResults(e.value);
48
- const firstResult = e.value[0];
49
- if (firstResult) {
50
- onResult?.(firstResult);
80
+ if (continuous) {
81
+ // Append new text to accumulated text
82
+ const newText = e.value[0];
83
+ accumulatedTextRef.current = accumulatedTextRef.current
84
+ ? accumulatedTextRef.current + ' ' + newText
85
+ : newText;
86
+ setResults([accumulatedTextRef.current, ...e.value.slice(1)]);
87
+ onResult?.(accumulatedTextRef.current);
88
+ }
89
+ else {
90
+ setResults(e.value);
91
+ const firstResult = e.value[0];
92
+ if (firstResult) {
93
+ onResult?.(firstResult);
94
+ }
51
95
  }
52
96
  }
53
97
  };
@@ -55,6 +99,15 @@ export const useVoiceRecognition = (options = {}) => {
55
99
  Voice.onSpeechPartialResults = (e) => {
56
100
  if (e.value && e.value.length > 0) {
57
101
  setPartialResults(e.value);
102
+ // Reset silence timer on partial results (user is speaking)
103
+ if (continuous && silenceTimerRef.current) {
104
+ clearTimeout(silenceTimerRef.current);
105
+ silenceTimerRef.current = setTimeout(() => {
106
+ if (shouldContinue) {
107
+ stop();
108
+ }
109
+ }, maxSilenceDuration);
110
+ }
58
111
  }
59
112
  };
60
113
  }
@@ -62,12 +115,24 @@ export const useVoiceRecognition = (options = {}) => {
62
115
  return () => {
63
116
  Voice.destroy().then(Voice.removeAllListeners);
64
117
  };
65
- }, [enablePartialResults, onResult, onError]);
118
+ }, [
119
+ enablePartialResults,
120
+ onResult,
121
+ onError,
122
+ continuous,
123
+ shouldContinue,
124
+ locale,
125
+ maxSilenceDuration,
126
+ ]);
66
127
  const start = useCallback(async () => {
67
128
  try {
68
129
  setError(null);
69
- setResults([]);
70
- setPartialResults([]);
130
+ if (!continuous) {
131
+ setResults([]);
132
+ setPartialResults([]);
133
+ accumulatedTextRef.current = '';
134
+ }
135
+ setShouldContinue(true);
71
136
  // Check permission (Android only)
72
137
  const hasPermission = await Voice.checkMicrophonePermission();
73
138
  if (!hasPermission) {
@@ -80,15 +145,36 @@ export const useVoiceRecognition = (options = {}) => {
80
145
  await Voice.start(locale, {
81
146
  EXTRA_PARTIAL_RESULTS: enablePartialResults,
82
147
  });
148
+ // Start silence timer if in continuous mode
149
+ if (continuous) {
150
+ silenceTimerRef.current = setTimeout(() => {
151
+ if (shouldContinue) {
152
+ stop();
153
+ }
154
+ }, maxSilenceDuration);
155
+ }
83
156
  }
84
157
  catch (e) {
85
158
  const errorMessage = e instanceof Error ? e.message : 'Failed to start recording';
86
159
  setError(errorMessage);
160
+ setShouldContinue(false);
87
161
  onError?.(errorMessage);
88
162
  }
89
- }, [locale, enablePartialResults, onError]);
163
+ }, [
164
+ locale,
165
+ enablePartialResults,
166
+ onError,
167
+ continuous,
168
+ maxSilenceDuration,
169
+ shouldContinue,
170
+ ]);
90
171
  const stop = useCallback(async () => {
91
172
  try {
173
+ setShouldContinue(false);
174
+ if (silenceTimerRef.current) {
175
+ clearTimeout(silenceTimerRef.current);
176
+ silenceTimerRef.current = null;
177
+ }
92
178
  await Voice.stop();
93
179
  }
94
180
  catch (e) {
@@ -99,9 +185,15 @@ export const useVoiceRecognition = (options = {}) => {
99
185
  }, [onError]);
100
186
  const cancel = useCallback(async () => {
101
187
  try {
188
+ setShouldContinue(false);
189
+ if (silenceTimerRef.current) {
190
+ clearTimeout(silenceTimerRef.current);
191
+ silenceTimerRef.current = null;
192
+ }
102
193
  await Voice.cancel();
103
194
  setResults([]);
104
195
  setPartialResults([]);
196
+ accumulatedTextRef.current = '';
105
197
  }
106
198
  catch (e) {
107
199
  const errorMessage = e instanceof Error ? e.message : 'Failed to cancel recording';
@@ -114,6 +206,12 @@ export const useVoiceRecognition = (options = {}) => {
114
206
  setPartialResults([]);
115
207
  setError(null);
116
208
  setIsRecording(false);
209
+ accumulatedTextRef.current = '';
210
+ setShouldContinue(false);
211
+ if (silenceTimerRef.current) {
212
+ clearTimeout(silenceTimerRef.current);
213
+ silenceTimerRef.current = null;
214
+ }
117
215
  }, []);
118
216
  return {
119
217
  isRecording,
@@ -1 +1 @@
1
- {"version":3,"file":"useVoiceRecognition.js","sourceRoot":"","sources":["../../src/hooks/useVoiceRecognition.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useVoiceRecognition.js","sourceRoot":"","sources":["../../src/hooks/useVoiceRecognition.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "react-native-voice-ts",
3
3
  "description": "Advanced Speech-to-Text library for React Native with TypeScript support. Features ready-to-use components (VoiceMicrophone), custom hooks (useVoiceRecognition), real-time transcription, multi-language support, and comprehensive voice recognition capabilities for iOS and Android.",
4
- "version": "1.0.1",
4
+ "version": "1.0.2",
5
5
  "author": "Noor Mohammad <noor.jsdivs@gmail.com>",
6
6
  "private": false,
7
7
  "homepage": "https://github.com/noorjsdivs/react-native-voice-ts",
@@ -22,7 +22,7 @@
22
22
  "react": "^19.2.1",
23
23
  "react-native": "^0.83.0",
24
24
  "react-native-svg": "^15.15.1",
25
- "semantic-release": "^25.0.2",
25
+ "semantic-release": "^23.0.0",
26
26
  "typescript": "5.9.3"
27
27
  },
28
28
  "keywords": [
@@ -46,6 +46,20 @@ export interface VoiceMicrophoneProps {
46
46
  */
47
47
  enablePartialResults?: boolean;
48
48
 
49
+ /**
50
+ * Whether to continue listening after getting results (continuous mode)
51
+ * When enabled, the microphone will automatically restart after getting results
52
+ * @default false
53
+ */
54
+ continuous?: boolean;
55
+
56
+ /**
57
+ * Maximum silence duration in milliseconds before stopping (continuous mode)
58
+ * Only applies when continuous mode is enabled
59
+ * @default 5000 (5 seconds)
60
+ */
61
+ maxSilenceDuration?: number;
62
+
49
63
  /**
50
64
  * Custom render function for the component
51
65
  * Receives isRecording state and control functions
@@ -97,38 +111,85 @@ const VoiceMicrophone: React.FC<VoiceMicrophoneProps> = ({
97
111
  locale = 'en-US',
98
112
  autoStart = false,
99
113
  enablePartialResults = true,
114
+ continuous = false,
115
+ maxSilenceDuration = 5000,
100
116
  children,
101
117
  }) => {
102
118
  const [isRecording, setIsRecording] = useState(false);
103
119
  const [recognizedText, setRecognizedText] = useState('');
104
120
  const [partialText, setPartialText] = useState('');
105
121
  const [error, setError] = useState<string | null>(null);
122
+ const [shouldContinue, setShouldContinue] = useState(false);
123
+ const silenceTimerRef = React.useRef<NodeJS.Timeout | null>(null);
124
+
125
+ useEffect(() => {
126
+ // Clear any existing timers on cleanup
127
+ return () => {
128
+ if (silenceTimerRef.current) {
129
+ clearTimeout(silenceTimerRef.current);
130
+ }
131
+ };
132
+ }, []);
106
133
 
107
134
  useEffect(() => {
108
135
  // Set up event listeners
109
136
  Voice.onSpeechStart = () => {
110
137
  setIsRecording(true);
111
138
  setError(null);
139
+ if (silenceTimerRef.current) {
140
+ clearTimeout(silenceTimerRef.current);
141
+ }
112
142
  onStart?.();
113
143
  };
114
144
 
115
- Voice.onSpeechEnd = () => {
145
+ Voice.onSpeechEnd = async () => {
116
146
  setIsRecording(false);
117
- onStop?.();
147
+
148
+ // In continuous mode, restart listening after results
149
+ if (continuous && shouldContinue) {
150
+ // Small delay before restarting
151
+ setTimeout(async () => {
152
+ if (shouldContinue) {
153
+ try {
154
+ await Voice.start(locale, {
155
+ EXTRA_PARTIAL_RESULTS: enablePartialResults,
156
+ });
157
+ } catch (err) {
158
+ console.error('Failed to restart voice recognition:', err);
159
+ }
160
+ }
161
+ }, 100);
162
+ } else {
163
+ onStop?.();
164
+ }
118
165
  };
119
166
 
120
167
  Voice.onSpeechError = (e: SpeechErrorEvent) => {
121
168
  const errorMessage = e.error?.message || 'Unknown error';
122
169
  setError(errorMessage);
123
170
  setIsRecording(false);
171
+ setShouldContinue(false);
172
+ if (silenceTimerRef.current) {
173
+ clearTimeout(silenceTimerRef.current);
174
+ }
124
175
  onError?.(errorMessage);
125
176
  };
126
177
 
127
178
  Voice.onSpeechResults = (e: SpeechResultsEvent) => {
128
179
  if (e.value && e.value.length > 0) {
129
180
  const text = e.value[0];
130
- setRecognizedText(text);
131
- onSpeechResult?.(text);
181
+
182
+ // In continuous mode, append new text to existing
183
+ if (continuous && recognizedText) {
184
+ const updatedText = recognizedText + ' ' + text;
185
+ setRecognizedText(updatedText);
186
+ onSpeechResult?.(updatedText);
187
+ } else {
188
+ setRecognizedText(text);
189
+ onSpeechResult?.(text);
190
+ }
191
+
192
+ setPartialText('');
132
193
  }
133
194
  };
134
195
 
@@ -138,6 +199,16 @@ const VoiceMicrophone: React.FC<VoiceMicrophoneProps> = ({
138
199
  const text = e.value[0];
139
200
  setPartialText(text);
140
201
  onPartialResult?.(text);
202
+
203
+ // Reset silence timer on partial results (user is speaking)
204
+ if (continuous && silenceTimerRef.current) {
205
+ clearTimeout(silenceTimerRef.current);
206
+ silenceTimerRef.current = setTimeout(() => {
207
+ if (shouldContinue) {
208
+ stop();
209
+ }
210
+ }, maxSilenceDuration);
211
+ }
141
212
  }
142
213
  };
143
214
  }
@@ -153,6 +224,11 @@ const VoiceMicrophone: React.FC<VoiceMicrophoneProps> = ({
153
224
  onStop,
154
225
  onError,
155
226
  enablePartialResults,
227
+ continuous,
228
+ shouldContinue,
229
+ recognizedText,
230
+ locale,
231
+ maxSilenceDuration,
156
232
  ]);
157
233
 
158
234
  // Auto-start if enabled
@@ -166,8 +242,11 @@ const VoiceMicrophone: React.FC<VoiceMicrophoneProps> = ({
166
242
  const start = useCallback(async () => {
167
243
  try {
168
244
  setError(null);
169
- setRecognizedText('');
170
- setPartialText('');
245
+ if (!continuous) {
246
+ setRecognizedText('');
247
+ setPartialText('');
248
+ }
249
+ setShouldContinue(true);
171
250
 
172
251
  // Check permission (Android only)
173
252
  const hasPermission = await Voice.checkMicrophonePermission();
@@ -182,27 +261,55 @@ const VoiceMicrophone: React.FC<VoiceMicrophoneProps> = ({
182
261
  await Voice.start(locale, {
183
262
  EXTRA_PARTIAL_RESULTS: enablePartialResults,
184
263
  });
264
+
265
+ // Start silence timer if in continuous mode
266
+ if (continuous) {
267
+ silenceTimerRef.current = setTimeout(() => {
268
+ if (shouldContinue) {
269
+ stop();
270
+ }
271
+ }, maxSilenceDuration);
272
+ }
185
273
  } catch (e) {
186
274
  const errorMessage =
187
275
  e instanceof Error ? e.message : 'Failed to start recording';
188
276
  setError(errorMessage);
277
+ setShouldContinue(false);
189
278
  onError?.(errorMessage);
190
279
  }
191
- }, [locale, enablePartialResults, onError]);
280
+ }, [
281
+ locale,
282
+ enablePartialResults,
283
+ onError,
284
+ continuous,
285
+ maxSilenceDuration,
286
+ shouldContinue,
287
+ ]);
192
288
 
193
289
  const stop = useCallback(async () => {
194
290
  try {
291
+ setShouldContinue(false);
292
+ if (silenceTimerRef.current) {
293
+ clearTimeout(silenceTimerRef.current);
294
+ silenceTimerRef.current = null;
295
+ }
195
296
  await Voice.stop();
297
+ onStop?.();
196
298
  } catch (e) {
197
299
  const errorMessage =
198
300
  e instanceof Error ? e.message : 'Failed to stop recording';
199
301
  setError(errorMessage);
200
302
  onError?.(errorMessage);
201
303
  }
202
- }, [onError]);
304
+ }, [onError, onStop]);
203
305
 
204
306
  const cancel = useCallback(async () => {
205
307
  try {
308
+ setShouldContinue(false);
309
+ if (silenceTimerRef.current) {
310
+ clearTimeout(silenceTimerRef.current);
311
+ silenceTimerRef.current = null;
312
+ }
206
313
  await Voice.cancel();
207
314
  setRecognizedText('');
208
315
  setPartialText('');
@@ -1,4 +1,4 @@
1
- import { useEffect, useState, useCallback } from 'react';
1
+ import React, { useEffect, useState, useCallback } from 'react';
2
2
  import Voice from '../index';
3
3
  import type { SpeechErrorEvent, SpeechResultsEvent } from '../VoiceModuleTypes';
4
4
 
@@ -15,6 +15,20 @@ export interface UseVoiceRecognitionOptions {
15
15
  */
16
16
  enablePartialResults?: boolean;
17
17
 
18
+ /**
19
+ * Whether to continue listening after getting results (continuous mode)
20
+ * When enabled, the microphone will automatically restart after getting results
21
+ * @default false
22
+ */
23
+ continuous?: boolean;
24
+
25
+ /**
26
+ * Maximum silence duration in milliseconds before stopping (continuous mode)
27
+ * Only applies when continuous mode is enabled
28
+ * @default 5000 (5 seconds)
29
+ */
30
+ maxSilenceDuration?: number;
31
+
18
32
  /**
19
33
  * Callback fired when speech is recognized
20
34
  */
@@ -95,6 +109,8 @@ export const useVoiceRecognition = (
95
109
  const {
96
110
  locale = 'en-US',
97
111
  enablePartialResults = true,
112
+ continuous = false,
113
+ maxSilenceDuration = 5000,
98
114
  onResult,
99
115
  onError,
100
116
  } = options;
@@ -103,31 +119,75 @@ export const useVoiceRecognition = (
103
119
  const [results, setResults] = useState<string[]>([]);
104
120
  const [partialResults, setPartialResults] = useState<string[]>([]);
105
121
  const [error, setError] = useState<string | null>(null);
122
+ const [shouldContinue, setShouldContinue] = useState(false);
123
+ const silenceTimerRef = React.useRef<NodeJS.Timeout | null>(null);
124
+ const accumulatedTextRef = React.useRef<string>('');
125
+
126
+ useEffect(() => {
127
+ // Clear any existing timers on cleanup
128
+ return () => {
129
+ if (silenceTimerRef.current) {
130
+ clearTimeout(silenceTimerRef.current);
131
+ }
132
+ };
133
+ }, []);
106
134
 
107
135
  useEffect(() => {
108
136
  // Set up event listeners
109
137
  Voice.onSpeechStart = () => {
110
138
  setIsRecording(true);
111
139
  setError(null);
140
+ if (silenceTimerRef.current) {
141
+ clearTimeout(silenceTimerRef.current);
142
+ }
112
143
  };
113
144
 
114
- Voice.onSpeechEnd = () => {
145
+ Voice.onSpeechEnd = async () => {
115
146
  setIsRecording(false);
147
+
148
+ // In continuous mode, restart listening after results
149
+ if (continuous && shouldContinue) {
150
+ setTimeout(async () => {
151
+ if (shouldContinue) {
152
+ try {
153
+ await Voice.start(locale, {
154
+ EXTRA_PARTIAL_RESULTS: enablePartialResults,
155
+ });
156
+ } catch (err) {
157
+ console.error('Failed to restart voice recognition:', err);
158
+ }
159
+ }
160
+ }, 100);
161
+ }
116
162
  };
117
163
 
118
164
  Voice.onSpeechError = (e: SpeechErrorEvent) => {
119
165
  const errorMessage = e.error?.message || 'Unknown error';
120
166
  setError(errorMessage);
121
167
  setIsRecording(false);
168
+ setShouldContinue(false);
169
+ if (silenceTimerRef.current) {
170
+ clearTimeout(silenceTimerRef.current);
171
+ }
122
172
  onError?.(errorMessage);
123
173
  };
124
174
 
125
175
  Voice.onSpeechResults = (e: SpeechResultsEvent) => {
126
176
  if (e.value && e.value.length > 0) {
127
- setResults(e.value);
128
- const firstResult = e.value[0];
129
- if (firstResult) {
130
- onResult?.(firstResult);
177
+ if (continuous) {
178
+ // Append new text to accumulated text
179
+ const newText = e.value[0];
180
+ accumulatedTextRef.current = accumulatedTextRef.current
181
+ ? accumulatedTextRef.current + ' ' + newText
182
+ : newText;
183
+ setResults([accumulatedTextRef.current, ...e.value.slice(1)]);
184
+ onResult?.(accumulatedTextRef.current);
185
+ } else {
186
+ setResults(e.value);
187
+ const firstResult = e.value[0];
188
+ if (firstResult) {
189
+ onResult?.(firstResult);
190
+ }
131
191
  }
132
192
  }
133
193
  };
@@ -136,6 +196,16 @@ export const useVoiceRecognition = (
136
196
  Voice.onSpeechPartialResults = (e: SpeechResultsEvent) => {
137
197
  if (e.value && e.value.length > 0) {
138
198
  setPartialResults(e.value);
199
+
200
+ // Reset silence timer on partial results (user is speaking)
201
+ if (continuous && silenceTimerRef.current) {
202
+ clearTimeout(silenceTimerRef.current);
203
+ silenceTimerRef.current = setTimeout(() => {
204
+ if (shouldContinue) {
205
+ stop();
206
+ }
207
+ }, maxSilenceDuration);
208
+ }
139
209
  }
140
210
  };
141
211
  }
@@ -144,13 +214,25 @@ export const useVoiceRecognition = (
144
214
  return () => {
145
215
  Voice.destroy().then(Voice.removeAllListeners);
146
216
  };
147
- }, [enablePartialResults, onResult, onError]);
217
+ }, [
218
+ enablePartialResults,
219
+ onResult,
220
+ onError,
221
+ continuous,
222
+ shouldContinue,
223
+ locale,
224
+ maxSilenceDuration,
225
+ ]);
148
226
 
149
227
  const start = useCallback(async () => {
150
228
  try {
151
229
  setError(null);
152
- setResults([]);
153
- setPartialResults([]);
230
+ if (!continuous) {
231
+ setResults([]);
232
+ setPartialResults([]);
233
+ accumulatedTextRef.current = '';
234
+ }
235
+ setShouldContinue(true);
154
236
 
155
237
  // Check permission (Android only)
156
238
  const hasPermission = await Voice.checkMicrophonePermission();
@@ -165,16 +247,38 @@ export const useVoiceRecognition = (
165
247
  await Voice.start(locale, {
166
248
  EXTRA_PARTIAL_RESULTS: enablePartialResults,
167
249
  });
250
+
251
+ // Start silence timer if in continuous mode
252
+ if (continuous) {
253
+ silenceTimerRef.current = setTimeout(() => {
254
+ if (shouldContinue) {
255
+ stop();
256
+ }
257
+ }, maxSilenceDuration);
258
+ }
168
259
  } catch (e) {
169
260
  const errorMessage =
170
261
  e instanceof Error ? e.message : 'Failed to start recording';
171
262
  setError(errorMessage);
263
+ setShouldContinue(false);
172
264
  onError?.(errorMessage);
173
265
  }
174
- }, [locale, enablePartialResults, onError]);
266
+ }, [
267
+ locale,
268
+ enablePartialResults,
269
+ onError,
270
+ continuous,
271
+ maxSilenceDuration,
272
+ shouldContinue,
273
+ ]);
175
274
 
176
275
  const stop = useCallback(async () => {
177
276
  try {
277
+ setShouldContinue(false);
278
+ if (silenceTimerRef.current) {
279
+ clearTimeout(silenceTimerRef.current);
280
+ silenceTimerRef.current = null;
281
+ }
178
282
  await Voice.stop();
179
283
  } catch (e) {
180
284
  const errorMessage =
@@ -186,9 +290,15 @@ export const useVoiceRecognition = (
186
290
 
187
291
  const cancel = useCallback(async () => {
188
292
  try {
293
+ setShouldContinue(false);
294
+ if (silenceTimerRef.current) {
295
+ clearTimeout(silenceTimerRef.current);
296
+ silenceTimerRef.current = null;
297
+ }
189
298
  await Voice.cancel();
190
299
  setResults([]);
191
300
  setPartialResults([]);
301
+ accumulatedTextRef.current = '';
192
302
  } catch (e) {
193
303
  const errorMessage =
194
304
  e instanceof Error ? e.message : 'Failed to cancel recording';
@@ -202,6 +312,12 @@ export const useVoiceRecognition = (
202
312
  setPartialResults([]);
203
313
  setError(null);
204
314
  setIsRecording(false);
315
+ accumulatedTextRef.current = '';
316
+ setShouldContinue(false);
317
+ if (silenceTimerRef.current) {
318
+ clearTimeout(silenceTimerRef.current);
319
+ silenceTimerRef.current = null;
320
+ }
205
321
  }, []);
206
322
 
207
323
  return {