Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,43 @@ const ref = useRef<IWaveformRef>(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 (
<View>
<Text>My recording voice component</Text>
</View>
);
};
```

You can check out the full example at [Example](./example/src/App.tsx).

---
Expand Down
54 changes: 15 additions & 39 deletions src/components/Waveform/Waveform.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
PermissionStatus,
playbackSpeedThreshold,
PlayerState,
RecorderState,
UpdateFrequency,
} from '../../constants';
import {
Expand Down Expand Up @@ -80,7 +79,6 @@ export const Waveform = forwardRef<IWaveformRef, IWaveform>((props, ref) => {
const [currentProgress, setCurrentProgress] = useState<number>(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;
Expand All @@ -95,13 +93,18 @@ export const Waveform = forwardRef<IWaveformRef, IWaveform>((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();

Expand Down Expand Up @@ -316,13 +319,7 @@ export const Waveform = forwardRef<IWaveformRef, IWaveform>((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(
Expand All @@ -344,26 +341,17 @@ export const Waveform = forwardRef<IWaveformRef, IWaveform>((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(
'error in stopping recording. can not get path of recording'
)
);
}
return Promise.resolve(pathData);
} catch (err) {
return Promise.reject(err);
}
Expand All @@ -377,13 +365,7 @@ export const Waveform = forwardRef<IWaveformRef, IWaveform>((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);
}
Expand All @@ -399,13 +381,7 @@ export const Waveform = forwardRef<IWaveformRef, IWaveform>((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(
Expand Down
10 changes: 0 additions & 10 deletions src/hooks/useAudioPlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
type IGetDuration,
type IOnCurrentDurationChange,
type IOnCurrentExtractedWaveForm,
type IOnCurrentRecordingWaveForm,
type IPausePlayer,
type IPreparePlayer,
type ISeekPlayer,
Expand Down Expand Up @@ -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);

Expand All @@ -99,7 +90,6 @@ export const useAudioPlayer = () => {
onCurrentDuration,
onCurrentExtractedWaveformData,
getDuration,
onCurrentRecordingWaveformData,
setPlaybackSpeed,
markPlayerAsUnmounted,
stopAllWaveFormExtractors,
Expand Down
64 changes: 58 additions & 6 deletions src/hooks/useAudioRecorder.tsx
Original file line number Diff line number Diff line change
@@ -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<IStartRecording>) =>
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<IStartRecording>) => {
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,
};
};
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ export {
RecorderState,
UpdateFrequency,
} from './constants';
export { useAudioPermission, useAudioPlayer } from './hooks';
export { useAudioPermission, useAudioPlayer, useAudioRecorder } from './hooks';