diff --git a/README.md b/README.md index 76bf1a5..cfee37c 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,43 @@ const ref = useRef(null); />; ``` +#### 3. Use recording functions without use WaveForm Component + +If you want to use our library to record audio but you do not need or do not want to display a live Waveform Component while recording you can use useAudioRecorder hook to extract all necessary functions to record voice + +```tsx +import { useAudioRecorder } from '@simform_solutions/react-native-audio-waveform'; +import React, { useEffect } from 'react'; +import { View, Text } from 'react-native'; + +export default () => { + const { + recorderState, + getDecibel, + pauseRecording, + resumeRecording, + startRecording, + stopRecording, + onCurrentRecordingWaveformData, + } = useAudioRecorder(); + + useEffect(() => { + const audioRecordingListener = onCurrentRecordingWaveformData(result => { + console.log(result); + }); + return () => { + audioRecordingListener.remove(); + }; + }, []); + + return ( + + My recording voice component + + ); +}; +``` + You can check out the full example at [Example](./example/src/App.tsx). --- diff --git a/src/components/Waveform/Waveform.tsx b/src/components/Waveform/Waveform.tsx index cef932b..dc563a8 100644 --- a/src/components/Waveform/Waveform.tsx +++ b/src/components/Waveform/Waveform.tsx @@ -23,7 +23,6 @@ import { PermissionStatus, playbackSpeedThreshold, PlayerState, - RecorderState, UpdateFrequency, } from '../../constants'; import { @@ -80,7 +79,6 @@ export const Waveform = forwardRef((props, ref) => { const [currentProgress, setCurrentProgress] = useState(0); const [panMoving, setPanMoving] = useState(false); const [playerState, setPlayerState] = useState(PlayerState.stopped); - const [recorderState, setRecorderState] = useState(RecorderState.stopped); const [isWaveformExtracted, setWaveformExtracted] = useState(false); const audioSpeed: number = playbackSpeed > playbackSpeedThreshold ? 1.0 : playbackSpeed; @@ -95,13 +93,18 @@ export const Waveform = forwardRef((props, ref) => { pausePlayer, onCurrentDuration, onDidFinishPlayingAudio, - onCurrentRecordingWaveformData, setPlaybackSpeed, markPlayerAsUnmounted, } = useAudioPlayer(); - const { startRecording, stopRecording, pauseRecording, resumeRecording } = - useAudioRecorder(); + const { + startRecording, + stopRecording, + pauseRecording, + resumeRecording, + onCurrentRecordingWaveformData, + recorderState, + } = useAudioRecorder(); const { checkHasAudioRecorderPermission } = useAudioPermission(); @@ -316,13 +319,7 @@ export const Waveform = forwardRef((props, ref) => { const hasPermission = await checkHasAudioRecorderPermission(); if (hasPermission === PermissionStatus.granted) { - const start = await startRecording(args); - if (!isNil(start) && start) { - setRecorderState(RecorderState.recording); - return Promise.resolve(true); - } else { - return Promise.reject(new Error('error in start recording action')); - } + return await startRecording(args); } else { return Promise.reject( new Error( @@ -344,19 +341,9 @@ export const Waveform = forwardRef((props, ref) => { if (mode === 'live') { try { const data = await stopRecording(); - if (!isNil(data) && !isEmpty(data)) { - setWaveform([]); - const pathData = head(data); - if (!isNil(pathData)) { - setRecorderState(RecorderState.stopped); - return Promise.resolve(pathData); - } else { - return Promise.reject( - new Error( - 'error in stopping recording. can not get path of recording' - ) - ); - } + setWaveform([]); + const pathData = head(data); + if (!isNil(pathData)) { } else { return Promise.reject( new Error( @@ -364,6 +351,7 @@ export const Waveform = forwardRef((props, ref) => { ) ); } + return Promise.resolve(pathData); } catch (err) { return Promise.reject(err); } @@ -377,13 +365,7 @@ export const Waveform = forwardRef((props, ref) => { const pauseRecordingAction = async () => { if (mode === 'live') { try { - const pause = await pauseRecording(); - if (!isNil(pause) && pause) { - setRecorderState(RecorderState.paused); - return Promise.resolve(pause); - } else { - return Promise.reject(new Error('Error in pausing recording audio')); - } + return await pauseRecording(); } catch (err) { return Promise.reject(err); } @@ -399,13 +381,7 @@ export const Waveform = forwardRef((props, ref) => { try { const hasPermission = await checkHasAudioRecorderPermission(); if (hasPermission === PermissionStatus.granted) { - const resume = await resumeRecording(); - if (!isNil(resume)) { - setRecorderState(RecorderState.recording); - return Promise.resolve(resume); - } else { - return Promise.reject(new Error('Error in resume recording')); - } + return await resumeRecording(); } else { return Promise.reject( new Error( diff --git a/src/hooks/useAudioPlayer.tsx b/src/hooks/useAudioPlayer.tsx index c231c65..cfe7b00 100644 --- a/src/hooks/useAudioPlayer.tsx +++ b/src/hooks/useAudioPlayer.tsx @@ -7,7 +7,6 @@ import { type IGetDuration, type IOnCurrentDurationChange, type IOnCurrentExtractedWaveForm, - type IOnCurrentRecordingWaveForm, type IPausePlayer, type IPreparePlayer, type ISeekPlayer, @@ -71,14 +70,6 @@ export const useAudioPlayer = () => { result => callback(result) ); - const onCurrentRecordingWaveformData = ( - callback: (result: IOnCurrentRecordingWaveForm) => void - ) => - audioPlayerEmitter.addListener( - NativeEvents.onCurrentRecordingWaveformData, - result => callback(result) - ); - const setPlaybackSpeed = (args: ISetPlaybackSpeed) => AudioWaveform.setPlaybackSpeed(args); @@ -99,7 +90,6 @@ export const useAudioPlayer = () => { onCurrentDuration, onCurrentExtractedWaveformData, getDuration, - onCurrentRecordingWaveformData, setPlaybackSpeed, markPlayerAsUnmounted, stopAllWaveFormExtractors, diff --git a/src/hooks/useAudioRecorder.tsx b/src/hooks/useAudioRecorder.tsx index 092414f..db458c7 100644 --- a/src/hooks/useAudioRecorder.tsx +++ b/src/hooks/useAudioRecorder.tsx @@ -1,23 +1,75 @@ +import { NativeEventEmitter, NativeModules } from 'react-native'; import { AudioWaveform } from '../AudioWaveform'; -import type { IStartRecording } from '../types'; +import type { IOnCurrentRecordingWaveForm, IStartRecording } from '../types'; +import { NativeEvents, RecorderState } from '../constants'; +import { useState } from 'react'; +import { isEmpty, isNil } from 'lodash'; export const useAudioRecorder = () => { - const startRecording = (args?: Partial) => - AudioWaveform.startRecording(args); + const [recorderState, setRecorderState] = useState(RecorderState.stopped); - const stopRecording = () => AudioWaveform.stopRecording(); + const audioPlayerEmitter = new NativeEventEmitter( + NativeModules.AudioWaveformsEventEmitter + ); - const pauseRecording = () => AudioWaveform.pauseRecording(); + const startRecording = async (args?: Partial) => { + const start = await AudioWaveform.startRecording(args); + if (!isNil(start) && start) { + setRecorderState(RecorderState.recording); + return Promise.resolve(true); + } else { + return Promise.reject(new Error('error in start recording action')); + } + }; + + const stopRecording = async () => { + const data = await AudioWaveform.stopRecording(); + if (!isNil(data) && !isEmpty(data)) { + return Promise.resolve(data); + } else { + return Promise.reject( + new Error('error in stopping recording. can not get path of recording') + ); + } + }; - const resumeRecording = () => AudioWaveform.resumeRecording(); + const pauseRecording = async () => { + const pause = await AudioWaveform.pauseRecording(); + if (!isNil(pause) && pause) { + setRecorderState(RecorderState.paused); + return Promise.resolve(pause); + } else { + return Promise.reject(new Error('Error in pausing recording audio')); + } + }; + + const resumeRecording = async () => { + const resume = await AudioWaveform.resumeRecording(); + if (!isNil(resume)) { + setRecorderState(RecorderState.recording); + return Promise.resolve(resume); + } else { + return Promise.reject(new Error('Error in resume recording')); + } + }; const getDecibel = () => AudioWaveform.getDecibel(); + const onCurrentRecordingWaveformData = ( + callback: (result: IOnCurrentRecordingWaveForm) => void + ) => + audioPlayerEmitter.addListener( + NativeEvents.onCurrentRecordingWaveformData, + result => callback(result) + ); + return { + recorderState, getDecibel, pauseRecording, resumeRecording, startRecording, stopRecording, + onCurrentRecordingWaveformData, }; }; diff --git a/src/index.ts b/src/index.ts index d056c9c..0626586 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,4 +10,4 @@ export { RecorderState, UpdateFrequency, } from './constants'; -export { useAudioPermission, useAudioPlayer } from './hooks'; +export { useAudioPermission, useAudioPlayer, useAudioRecorder } from './hooks';