import { EmitterSubscription, EventSubscription, NativeEventEmitter, NativeModules, PermissionsAndroid, Platform, } from 'react-native'; const LINKING_ERROR = `The package 'react-native-vosk' doesn't seem to be linked. Make sure: \n\n` + Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo managed workflow\n'; const VoskModule = NativeModules.Vosk ? NativeModules.Vosk : new Proxy( {}, { get() { throw new Error(LINKING_ERROR); }, } ); type VoskEvent = { /** * Event datas */ data: string; } const eventEmitter = new NativeEventEmitter(VoskModule); export default class Vosk { // Public functions loadModel = (path: string) => VoskModule.loadModel(path); currentRegisteredEvents: EmitterSubscription[] = []; start = (grammar: string[] | null = null) : Promise => { return new Promise((resolve, reject) => { // Check for permission this.requestRecordPermission() .then((granted) => { if (!granted) return reject('Audio record permission denied'); // Setup events this.currentRegisteredEvents.push(eventEmitter.addListener('onResult', (e: VoskEvent) => resolve(e.data))); this.currentRegisteredEvents.push(eventEmitter.addListener('onFinalResult', (e: VoskEvent) => resolve(e.data))); this.currentRegisteredEvents.push(eventEmitter.addListener('onError', (e: VoskEvent) => reject(e.data))); this.currentRegisteredEvents.push(eventEmitter.addListener('onTimeout', () => reject('timeout'))); // Start recognition VoskModule.start(grammar); }) .catch((e) => { reject(e); }); }).finally(() => { this.cleanListeners(); }); }; stop = () => { this.cleanListeners(); VoskModule.stop(); }; // Event listeners builders onResult = (onResult: (e: VoskEvent) => void) : EventSubscription => { return eventEmitter.addListener('onResult', onResult); }; onFinalResult = (onFinalResult: (e: VoskEvent) => void) : EventSubscription => { return eventEmitter.addListener('onFinalResult', onFinalResult); }; onError = (onError: (e: VoskEvent) => void) : EventSubscription => { return eventEmitter.addListener('onError', onError); }; onTimeout = (onTimeout: (e: VoskEvent) => void) : EventSubscription => { return eventEmitter.addListener('onTimeout', onTimeout); }; // Private functions private requestRecordPermission = async () => { if (Platform.OS === "ios") return true; const granted = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.RECORD_AUDIO! ); return granted === PermissionsAndroid.RESULTS.GRANTED; }; private cleanListeners = () => { // Clean event listeners this.currentRegisteredEvents.forEach(subscription => subscription.remove()); this.currentRegisteredEvents = []; } }