react-native-voice-ts 1.0.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.
- package/.nvmrc +1 -0
- package/.prettierrc +5 -0
- package/.releaserc +15 -0
- package/CONTRIBUTING.md +293 -0
- package/LICENSE +21 -0
- package/MIGRATION_SUMMARY.md +510 -0
- package/README.md +576 -0
- package/android/build.gradle +126 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +8 -0
- package/android/src/main/VoiceSpec.kt +55 -0
- package/android/src/main/java/com/wenkesj/voice/Voice.kt +343 -0
- package/android/src/main/java/com/wenkesj/voice/VoiceModule.kt +63 -0
- package/android/src/main/java/com/wenkesj/voice/VoicePackage.kt +35 -0
- package/android/src/newarch/VoiceSpec.kt +55 -0
- package/android/src/oldarch/VoiceSpec.kt +30 -0
- package/app.plugin.js +1 -0
- package/dist/NativeVoiceAndroid.d.ts +22 -0
- package/dist/NativeVoiceAndroid.d.ts.map +1 -0
- package/dist/NativeVoiceAndroid.js +3 -0
- package/dist/NativeVoiceAndroid.js.map +1 -0
- package/dist/NativeVoiceIOS.d.ts +18 -0
- package/dist/NativeVoiceIOS.d.ts.map +1 -0
- package/dist/NativeVoiceIOS.js +3 -0
- package/dist/NativeVoiceIOS.js.map +1 -0
- package/dist/VoiceModuleTypes.d.ts +54 -0
- package/dist/VoiceModuleTypes.d.ts.map +1 -0
- package/dist/VoiceModuleTypes.js +2 -0
- package/dist/VoiceModuleTypes.js.map +1 -0
- package/dist/VoiceUtilTypes.d.ts +43 -0
- package/dist/VoiceUtilTypes.d.ts.map +1 -0
- package/dist/VoiceUtilTypes.js +8 -0
- package/dist/VoiceUtilTypes.js.map +1 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +395 -0
- package/dist/index.js.map +1 -0
- package/ios/Voice/Voice.h +14 -0
- package/ios/Voice/Voice.mm +672 -0
- package/ios/Voice.xcodeproj/project.pbxproj +272 -0
- package/ios/Voice.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/package.json +101 -0
- package/plugin/build/withVoice.d.ts +13 -0
- package/plugin/build/withVoice.js +47 -0
- package/plugin/tsconfig.tsbuildinfo +1 -0
- package/react-native-voice.podspec +46 -0
- package/src/NativeVoiceAndroid.ts +28 -0
- package/src/NativeVoiceIOS.ts +24 -0
- package/src/VoiceModuleTypes.ts +64 -0
- package/src/VoiceUtilTypes.ts +46 -0
- package/src/index.ts +500 -0
package/README.md
ADDED
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# 🎤 React Native Voice (TypeScript)
|
|
4
|
+
|
|
5
|
+
### Advanced Speech-to-Text Library for React Native
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/react-native-voice-ts)
|
|
8
|
+
[](https://www.npmjs.com/package/react-native-voice-ts)
|
|
9
|
+
[](https://opensource.org/licenses/MIT)
|
|
10
|
+
[](https://www.typescriptlang.org/)
|
|
11
|
+
[](https://github.com/noorjsdivs/react-native-voice-ts/pulls)
|
|
12
|
+
|
|
13
|
+
A powerful, production-ready speech-to-text library for React Native applications with full TypeScript support, built-in performance optimizations, and comprehensive features.
|
|
14
|
+
|
|
15
|
+
[Features](#-features) •
|
|
16
|
+
[Installation](#-installation) •
|
|
17
|
+
[Quick Start](#-quick-start) •
|
|
18
|
+
[API Reference](#-api-reference) •
|
|
19
|
+
[Examples](#-complete-examples) •
|
|
20
|
+
[Contributing](#-contributing)
|
|
21
|
+
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## ✨ Features
|
|
27
|
+
|
|
28
|
+
### Core Capabilities
|
|
29
|
+
|
|
30
|
+
- 🎯 **Real-time Speech Recognition** - Live speech-to-text conversion
|
|
31
|
+
- 🔄 **Partial Results** - Get intermediate results as the user speaks
|
|
32
|
+
- 📊 **Volume Monitoring** - Track audio input levels in real-time
|
|
33
|
+
- 🌍 **Multi-language Support** - Support for 100+ languages
|
|
34
|
+
- ⚡ **Performance Optimized** - Built with performance best practices
|
|
35
|
+
- 📱 **Cross-platform** - Works on both iOS and Android
|
|
36
|
+
- 🔒 **Type-safe** - Full TypeScript support with comprehensive types
|
|
37
|
+
|
|
38
|
+
### Enhanced Features (2025 Update)
|
|
39
|
+
|
|
40
|
+
- ✅ **Permission Management** - Easy microphone permission handling
|
|
41
|
+
- 📈 **Performance Tracking** - Monitor recognition duration and state
|
|
42
|
+
- 💾 **Result Caching** - Access last results without re-recognition
|
|
43
|
+
- 🎨 **Modern API** - Clean, intuitive API design
|
|
44
|
+
- 🛡️ **Error Handling** - Comprehensive error management
|
|
45
|
+
- 🔧 **Fully Customizable** - Extensive configuration options
|
|
46
|
+
|
|
47
|
+
### Platform Support
|
|
48
|
+
|
|
49
|
+
| Feature | iOS | Android |
|
|
50
|
+
| --------------------- | :-: | :-----: |
|
|
51
|
+
| Speech Recognition | ✅ | ✅ |
|
|
52
|
+
| Partial Results | ✅ | ✅ |
|
|
53
|
+
| Volume Events | ✅ | ✅ |
|
|
54
|
+
| Permission Management | N/A | ✅ |
|
|
55
|
+
| Audio Transcription | ✅ | ❌ |
|
|
56
|
+
| Recognition Services | ❌ | ✅ |
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 📦 Installation
|
|
61
|
+
|
|
62
|
+
### Using npm
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm install react-native-voice-ts --save
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Using yarn
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
yarn add react-native-voice-ts
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### iOS Setup
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
cd ios && pod install && cd ..
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Permissions
|
|
81
|
+
|
|
82
|
+
#### iOS (Info.plist)
|
|
83
|
+
|
|
84
|
+
```xml
|
|
85
|
+
<key>NSMicrophoneUsageDescription</key>
|
|
86
|
+
<string>This app needs access to your microphone for voice recognition</string>
|
|
87
|
+
<key>NSSpeechRecognitionUsageDescription</key>
|
|
88
|
+
<string>This app needs speech recognition permission to convert your speech to text</string>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### Android (AndroidManifest.xml)
|
|
92
|
+
|
|
93
|
+
```xml
|
|
94
|
+
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 🚀 Quick Start
|
|
100
|
+
|
|
101
|
+
### Basic Usage
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import React, { useEffect, useState } from 'react';
|
|
105
|
+
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
|
|
106
|
+
import Voice from '@react-native-voice/voice';
|
|
107
|
+
|
|
108
|
+
const App = () => {
|
|
109
|
+
const [isRecording, setIsRecording] = useState(false);
|
|
110
|
+
const [recognizedText, setRecognizedText] = useState('');
|
|
111
|
+
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
// Set up event listeners
|
|
114
|
+
Voice.onSpeechResults = (e) => {
|
|
115
|
+
setRecognizedText(e.value[0]);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// Cleanup
|
|
119
|
+
return () => {
|
|
120
|
+
Voice.destroy().then(Voice.removeAllListeners);
|
|
121
|
+
};
|
|
122
|
+
}, []);
|
|
123
|
+
|
|
124
|
+
const startRecording = async () => {
|
|
125
|
+
try {
|
|
126
|
+
await Voice.start('en-US');
|
|
127
|
+
setIsRecording(true);
|
|
128
|
+
} catch (error) {
|
|
129
|
+
console.error(error);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const stopRecording = async () => {
|
|
134
|
+
try {
|
|
135
|
+
await Voice.stop();
|
|
136
|
+
setIsRecording(false);
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.error(error);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<View style={styles.container}>
|
|
144
|
+
<Text style={styles.text}>{recognizedText || 'Press to speak'}</Text>
|
|
145
|
+
<TouchableOpacity
|
|
146
|
+
style={[styles.button, isRecording && styles.recording]}
|
|
147
|
+
onPress={isRecording ? stopRecording : startRecording}
|
|
148
|
+
>
|
|
149
|
+
<Text style={styles.buttonText}>
|
|
150
|
+
{isRecording ? '🔴 Stop' : '🎤 Start'}
|
|
151
|
+
</Text>
|
|
152
|
+
</TouchableOpacity>
|
|
153
|
+
</View>
|
|
154
|
+
);
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const styles = StyleSheet.create({
|
|
158
|
+
container: {
|
|
159
|
+
flex: 1,
|
|
160
|
+
justifyContent: 'center',
|
|
161
|
+
alignItems: 'center',
|
|
162
|
+
padding: 20,
|
|
163
|
+
},
|
|
164
|
+
text: {
|
|
165
|
+
fontSize: 24,
|
|
166
|
+
marginBottom: 40,
|
|
167
|
+
textAlign: 'center',
|
|
168
|
+
},
|
|
169
|
+
button: {
|
|
170
|
+
backgroundColor: '#007AFF',
|
|
171
|
+
padding: 20,
|
|
172
|
+
borderRadius: 50,
|
|
173
|
+
width: 100,
|
|
174
|
+
height: 100,
|
|
175
|
+
justifyContent: 'center',
|
|
176
|
+
alignItems: 'center',
|
|
177
|
+
},
|
|
178
|
+
recording: {
|
|
179
|
+
backgroundColor: '#FF3B30',
|
|
180
|
+
},
|
|
181
|
+
buttonText: {
|
|
182
|
+
color: 'white',
|
|
183
|
+
fontSize: 16,
|
|
184
|
+
fontWeight: 'bold',
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
export default App;
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 📚 API Reference
|
|
194
|
+
|
|
195
|
+
### Methods
|
|
196
|
+
|
|
197
|
+
#### Core Methods
|
|
198
|
+
|
|
199
|
+
##### `start(locale: string, options?: VoiceOptions): Promise<void>`
|
|
200
|
+
|
|
201
|
+
Start voice recognition.
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
// Basic usage
|
|
205
|
+
await Voice.start('en-US');
|
|
206
|
+
|
|
207
|
+
// With options (Android)
|
|
208
|
+
await Voice.start('en-US', {
|
|
209
|
+
EXTRA_LANGUAGE_MODEL: 'LANGUAGE_MODEL_FREE_FORM',
|
|
210
|
+
EXTRA_MAX_RESULTS: 5,
|
|
211
|
+
EXTRA_PARTIAL_RESULTS: true,
|
|
212
|
+
REQUEST_PERMISSIONS_AUTO: true,
|
|
213
|
+
});
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**Supported Languages**: `en-US`, `es-ES`, `fr-FR`, `de-DE`, `it-IT`, `ja-JP`, `ko-KR`, `pt-BR`, `ru-RU`, `zh-CN`, and 100+ more.
|
|
217
|
+
|
|
218
|
+
##### `stop(): Promise<void>`
|
|
219
|
+
|
|
220
|
+
Stop voice recognition and get final results.
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
await Voice.stop();
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
##### `cancel(): Promise<void>`
|
|
227
|
+
|
|
228
|
+
Cancel voice recognition without getting results.
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
await Voice.cancel();
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
##### `destroy(): Promise<void>`
|
|
235
|
+
|
|
236
|
+
Destroy the voice recognition instance and cleanup.
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
await Voice.destroy();
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
##### `removeAllListeners(): void`
|
|
243
|
+
|
|
244
|
+
Remove all event listeners.
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
Voice.removeAllListeners();
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### Status Methods
|
|
251
|
+
|
|
252
|
+
##### `isAvailable(): Promise<0 | 1>`
|
|
253
|
+
|
|
254
|
+
Check if speech recognition is available on the device.
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
const available = await Voice.isAvailable();
|
|
258
|
+
if (available) {
|
|
259
|
+
console.log('Speech recognition is available');
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
##### `isRecognizing(): Promise<0 | 1>`
|
|
264
|
+
|
|
265
|
+
Check if currently recognizing (async).
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
const recognizing = await Voice.isRecognizing();
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
##### `recognizing: boolean` (getter)
|
|
272
|
+
|
|
273
|
+
Check if currently recognizing (synchronous).
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
if (Voice.recognizing) {
|
|
277
|
+
console.log('Currently recording');
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
#### New Features (2025)
|
|
282
|
+
|
|
283
|
+
##### `requestMicrophonePermission(): Promise<boolean>`
|
|
284
|
+
|
|
285
|
+
Request microphone permission (Android only).
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
const granted = await Voice.requestMicrophonePermission();
|
|
289
|
+
if (granted) {
|
|
290
|
+
await Voice.start('en-US');
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
##### `checkMicrophonePermission(): Promise<boolean>`
|
|
295
|
+
|
|
296
|
+
Check microphone permission status (Android only).
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
const hasPermission = await Voice.checkMicrophonePermission();
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
##### `getRecognitionDuration(): number`
|
|
303
|
+
|
|
304
|
+
Get the duration of current recognition session in milliseconds.
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
const duration = Voice.getRecognitionDuration();
|
|
308
|
+
console.log(`Recording for ${duration}ms`);
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
##### `getLastResults(): string[]`
|
|
312
|
+
|
|
313
|
+
Get the last recognized results without triggering new recognition.
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
const lastResults = Voice.getLastResults();
|
|
317
|
+
console.log('Last results:', lastResults);
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
#### Android-Only Methods
|
|
321
|
+
|
|
322
|
+
##### `getSpeechRecognitionServices(): Promise<string[]>`
|
|
323
|
+
|
|
324
|
+
Get available speech recognition engines on Android.
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
if (Platform.OS === 'android') {
|
|
328
|
+
const services = await Voice.getSpeechRecognitionServices();
|
|
329
|
+
console.log('Available services:', services);
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Events
|
|
334
|
+
|
|
335
|
+
Set up event listeners to handle voice recognition events:
|
|
336
|
+
|
|
337
|
+
#### `onSpeechStart`
|
|
338
|
+
|
|
339
|
+
Triggered when speech recognition starts.
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
Voice.onSpeechStart = (e: SpeechStartEvent) => {
|
|
343
|
+
console.log('Speech recognition started');
|
|
344
|
+
};
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
#### `onSpeechRecognized`
|
|
348
|
+
|
|
349
|
+
Triggered when speech is recognized.
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
Voice.onSpeechRecognized = (e: SpeechRecognizedEvent) => {
|
|
353
|
+
console.log('Speech recognized');
|
|
354
|
+
};
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
#### `onSpeechEnd`
|
|
358
|
+
|
|
359
|
+
Triggered when speech recognition ends.
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
Voice.onSpeechEnd = (e: SpeechEndEvent) => {
|
|
363
|
+
console.log('Speech recognition ended');
|
|
364
|
+
};
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
#### `onSpeechError`
|
|
368
|
+
|
|
369
|
+
Triggered when an error occurs.
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
Voice.onSpeechError = (e: SpeechErrorEvent) => {
|
|
373
|
+
console.error('Error:', e.error?.message);
|
|
374
|
+
};
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
#### `onSpeechResults`
|
|
378
|
+
|
|
379
|
+
Triggered when final results are available.
|
|
380
|
+
|
|
381
|
+
```typescript
|
|
382
|
+
Voice.onSpeechResults = (e: SpeechResultsEvent) => {
|
|
383
|
+
console.log('Results:', e.value);
|
|
384
|
+
// e.value is an array of strings, sorted by confidence
|
|
385
|
+
};
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
#### `onSpeechPartialResults`
|
|
389
|
+
|
|
390
|
+
Triggered when partial results are available (real-time).
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
Voice.onSpeechPartialResults = (e: SpeechResultsEvent) => {
|
|
394
|
+
console.log('Partial results:', e.value);
|
|
395
|
+
};
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
#### `onSpeechVolumeChanged`
|
|
399
|
+
|
|
400
|
+
Triggered when the audio volume changes.
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
Voice.onSpeechVolumeChanged = (e: SpeechVolumeChangeEvent) => {
|
|
404
|
+
console.log('Volume:', e.value); // 0-10
|
|
405
|
+
};
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Types
|
|
409
|
+
|
|
410
|
+
```typescript
|
|
411
|
+
import type {
|
|
412
|
+
SpeechEvents,
|
|
413
|
+
SpeechStartEvent,
|
|
414
|
+
SpeechEndEvent,
|
|
415
|
+
SpeechResultsEvent,
|
|
416
|
+
SpeechErrorEvent,
|
|
417
|
+
SpeechRecognizedEvent,
|
|
418
|
+
SpeechVolumeChangeEvent,
|
|
419
|
+
VoiceOptions,
|
|
420
|
+
RecognitionStats,
|
|
421
|
+
PermissionResult,
|
|
422
|
+
Language,
|
|
423
|
+
} from 'react-native-voice-ts';
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## 💡 Complete Examples
|
|
429
|
+
|
|
430
|
+
For comprehensive examples including:
|
|
431
|
+
|
|
432
|
+
- Simple Voice-to-Text
|
|
433
|
+
- Real-time Transcription with Partial Results
|
|
434
|
+
- Multi-language Support
|
|
435
|
+
- Voice Commands
|
|
436
|
+
- Permission Handling
|
|
437
|
+
- Custom Hooks
|
|
438
|
+
|
|
439
|
+
Please refer to the [example](./example) directory in this repository.
|
|
440
|
+
|
|
441
|
+
### Quick Example: Custom Hook
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
import { useEffect, useState, useCallback } from 'react';
|
|
445
|
+
import Voice from '@react-native-voice/voice';
|
|
446
|
+
|
|
447
|
+
export const useVoiceRecognition = (locale = 'en-US') => {
|
|
448
|
+
const [isRecording, setIsRecording] = useState(false);
|
|
449
|
+
const [results, setResults] = useState<string[]>([]);
|
|
450
|
+
const [error, setError] = useState<string | null>(null);
|
|
451
|
+
|
|
452
|
+
useEffect(() => {
|
|
453
|
+
Voice.onSpeechStart = () => setIsRecording(true);
|
|
454
|
+
Voice.onSpeechEnd = () => setIsRecording(false);
|
|
455
|
+
Voice.onSpeechResults = (e) => setResults(e.value || []);
|
|
456
|
+
Voice.onSpeechError = (e) => setError(e.error?.message || 'Error');
|
|
457
|
+
|
|
458
|
+
return () => {
|
|
459
|
+
Voice.destroy().then(Voice.removeAllListeners);
|
|
460
|
+
};
|
|
461
|
+
}, []);
|
|
462
|
+
|
|
463
|
+
const start = useCallback(async () => {
|
|
464
|
+
try {
|
|
465
|
+
await Voice.start(locale);
|
|
466
|
+
} catch (e) {
|
|
467
|
+
setError('Failed to start');
|
|
468
|
+
}
|
|
469
|
+
}, [locale]);
|
|
470
|
+
|
|
471
|
+
const stop = useCallback(async () => {
|
|
472
|
+
try {
|
|
473
|
+
await Voice.stop();
|
|
474
|
+
} catch (e) {
|
|
475
|
+
setError('Failed to stop');
|
|
476
|
+
}
|
|
477
|
+
}, []);
|
|
478
|
+
|
|
479
|
+
return { isRecording, results, error, start, stop };
|
|
480
|
+
};
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
## ⚠️ Common Issues & Solutions
|
|
486
|
+
|
|
487
|
+
### Issue: No speech detected
|
|
488
|
+
|
|
489
|
+
**Solution**: Check microphone permissions and ensure the device is not muted.
|
|
490
|
+
|
|
491
|
+
### Issue: Error on iOS Simulator
|
|
492
|
+
|
|
493
|
+
**Solution**: Speech recognition doesn't work on iOS Simulator. Use a real device.
|
|
494
|
+
|
|
495
|
+
### Issue: Partial results not working
|
|
496
|
+
|
|
497
|
+
**Solution**: Ensure `EXTRA_PARTIAL_RESULTS: true` is set on Android.
|
|
498
|
+
|
|
499
|
+
### Issue: App crashes on Android
|
|
500
|
+
|
|
501
|
+
**Solution**: Make sure RECORD_AUDIO permission is declared in AndroidManifest.xml.
|
|
502
|
+
|
|
503
|
+
---
|
|
504
|
+
|
|
505
|
+
## 🤝 Contributing
|
|
506
|
+
|
|
507
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
508
|
+
|
|
509
|
+
1. Fork the repository
|
|
510
|
+
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
|
|
511
|
+
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
|
|
512
|
+
4. Push to the branch (`git push origin feature/AmazingFeature`)
|
|
513
|
+
5. Open a Pull Request
|
|
514
|
+
|
|
515
|
+
### Development Setup
|
|
516
|
+
|
|
517
|
+
```bash
|
|
518
|
+
# Clone the repository
|
|
519
|
+
git clone https://github.com/noorjsdivs/react-native-voice-ts.git
|
|
520
|
+
cd react-native-voice-ts
|
|
521
|
+
|
|
522
|
+
# Install dependencies
|
|
523
|
+
yarn install
|
|
524
|
+
|
|
525
|
+
# Build
|
|
526
|
+
yarn build
|
|
527
|
+
|
|
528
|
+
# Run example
|
|
529
|
+
cd example
|
|
530
|
+
yarn install
|
|
531
|
+
yarn ios # or yarn android
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
---
|
|
535
|
+
|
|
536
|
+
## 📄 License
|
|
537
|
+
|
|
538
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
539
|
+
|
|
540
|
+
Copyright (c) 2025 Noor Mohammad
|
|
541
|
+
|
|
542
|
+
---
|
|
543
|
+
|
|
544
|
+
## 👤 Author
|
|
545
|
+
|
|
546
|
+
**Noor Mohammad**
|
|
547
|
+
|
|
548
|
+
- GitHub: [@noorjsdivs](https://github.com/noorjsdivs)
|
|
549
|
+
- Email: noor.jsdivs@gmail.com
|
|
550
|
+
|
|
551
|
+
---
|
|
552
|
+
|
|
553
|
+
## 🙏 Acknowledgments
|
|
554
|
+
|
|
555
|
+
- Thanks to all contributors who have helped improve this library
|
|
556
|
+
- Inspired by the need for better voice recognition in React Native apps
|
|
557
|
+
- Built with ❤️ for the React Native community
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
561
|
+
## 📊 Stats
|
|
562
|
+
|
|
563
|
+

|
|
564
|
+

|
|
565
|
+

|
|
566
|
+

|
|
567
|
+

|
|
568
|
+
|
|
569
|
+
---
|
|
570
|
+
|
|
571
|
+
<div align="center">
|
|
572
|
+
<strong>⭐ Star this repo if you find it helpful! ⭐</strong>
|
|
573
|
+
<br />
|
|
574
|
+
<br />
|
|
575
|
+
Made with ❤️ by <a href="https://github.com/noorjsdivs">Noor Mohammad</a>
|
|
576
|
+
</div>
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
// Buildscript is evaluated before everything else so we can't use getExtOrDefault
|
|
3
|
+
def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["Voice_kotlinVersion"]
|
|
4
|
+
|
|
5
|
+
repositories {
|
|
6
|
+
google()
|
|
7
|
+
mavenCentral()
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
dependencies {
|
|
11
|
+
classpath "com.android.tools.build:gradle:7.2.1"
|
|
12
|
+
// noinspection DifferentKotlinGradleVersion
|
|
13
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
def reactNativeArchitectures() {
|
|
18
|
+
def value = rootProject.getProperties().get("reactNativeArchitectures")
|
|
19
|
+
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
def isNewArchitectureEnabled() {
|
|
23
|
+
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
apply plugin: "com.android.library"
|
|
27
|
+
apply plugin: "kotlin-android"
|
|
28
|
+
|
|
29
|
+
if (isNewArchitectureEnabled()) {
|
|
30
|
+
apply plugin: "com.facebook.react"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
def getExtOrDefault(name) {
|
|
34
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["Voice_" + name]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
def getExtOrIntegerDefault(name) {
|
|
38
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["Voice_" + name]).toInteger()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
def supportsNamespace() {
|
|
42
|
+
def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
|
|
43
|
+
def major = parsed[0].toInteger()
|
|
44
|
+
def minor = parsed[1].toInteger()
|
|
45
|
+
|
|
46
|
+
// Namespace support was added in 7.3.0
|
|
47
|
+
return (major == 7 && minor >= 3) || major >= 8
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
android {
|
|
51
|
+
if (supportsNamespace()) {
|
|
52
|
+
namespace "com.wenkesj.voice"
|
|
53
|
+
|
|
54
|
+
sourceSets {
|
|
55
|
+
main {
|
|
56
|
+
manifest.srcFile "src/main/AndroidManifestNew.xml"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
62
|
+
|
|
63
|
+
defaultConfig {
|
|
64
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
65
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
66
|
+
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
buildFeatures {
|
|
71
|
+
buildConfig true
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
buildTypes {
|
|
75
|
+
release {
|
|
76
|
+
minifyEnabled false
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
lintOptions {
|
|
81
|
+
disable "GradleCompatible"
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
compileOptions {
|
|
85
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
86
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
sourceSets {
|
|
90
|
+
main {
|
|
91
|
+
if (isNewArchitectureEnabled()) {
|
|
92
|
+
java.srcDirs += [
|
|
93
|
+
"src/newarch",
|
|
94
|
+
// Codegen specs
|
|
95
|
+
"generated/java",
|
|
96
|
+
"generated/jni"
|
|
97
|
+
]
|
|
98
|
+
} else {
|
|
99
|
+
java.srcDirs += ["src/oldarch"]
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
repositories {
|
|
106
|
+
mavenCentral()
|
|
107
|
+
google()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
def kotlin_version = getExtOrDefault("kotlinVersion")
|
|
111
|
+
|
|
112
|
+
dependencies {
|
|
113
|
+
// For < 0.71, this will be from the local maven repo
|
|
114
|
+
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
|
|
115
|
+
//noinspection GradleDynamicVersion
|
|
116
|
+
implementation "com.facebook.react:react-native:+"
|
|
117
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (isNewArchitectureEnabled()) {
|
|
121
|
+
react {
|
|
122
|
+
jsRootDir = file("../src/")
|
|
123
|
+
libraryName = "Voice"
|
|
124
|
+
codegenJavaPackageName = "com.wenkesj.voice"
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
|
+
package="com.wenkesj.voice"
|
|
3
|
+
xmlns:tools="http://schemas.android.com/tools">
|
|
4
|
+
|
|
5
|
+
<uses-sdk tools:overrideLibrary="com.facebook.react" />
|
|
6
|
+
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
|
7
|
+
<uses-permission android:name="android.permission.INTERNET" />
|
|
8
|
+
</manifest>
|