-
Notifications
You must be signed in to change notification settings - Fork 375
Expand file tree
/
Copy pathuseAudioRecorder.tsx
More file actions
124 lines (107 loc) · 4.02 KB
/
useAudioRecorder.tsx
File metadata and controls
124 lines (107 loc) · 4.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import { useCallback, useEffect } from 'react';
import { LocalVoiceRecordingAttachment } from 'stream-chat';
import { useMessageComposer } from '../../../contexts/messageInputContext/hooks/useMessageComposer';
import { MessageInputContextValue } from '../../../contexts/messageInputContext/MessageInputContext';
import type { File } from '../../../types/types';
import { FileTypes } from '../../../types/types';
import { generateRandomId } from '../../../utils/utils';
import { resampleWaveformData } from '../utils/audioSampling';
/**
* The hook that controls all the async audio core features including start/stop or recording, player, upload/delete of the recorded audio.
*/
export const useAudioRecorder = ({
audioRecorderManager,
sendMessage,
}: Pick<MessageInputContextValue, 'audioRecorderManager' | 'sendMessage'>) => {
const { attachmentManager } = useMessageComposer();
/**
* A function that takes care of stopping the voice recording from the library's
* side only. Meant to be used as a pure function (during unmounting for instance)
* hence this approach.
*/
const stopVoiceRecording = useCallback(
async (withDelete?: boolean) => {
await audioRecorderManager.stopRecording(withDelete);
},
[audioRecorderManager],
);
// This effect stop the player from playing and stops audio recording on
// the audio SDK side on unmount.
useEffect(
() => () => {
stopVoiceRecording();
},
[stopVoiceRecording],
);
/**
* Function to start voice recording. Will return whether access is granted
* with regards to the microphone permission as that's how the underlying
* library works on iOS.
*/
const startVoiceRecording = useCallback(async () => {
return await audioRecorderManager.startRecording();
}, [audioRecorderManager]);
/**
* Function to delete voice recording.
*/
const deleteVoiceRecording = useCallback(async () => {
await stopVoiceRecording(true);
}, [stopVoiceRecording]);
/**
* Function to upload or send voice recording.
* @param sendOnComplete boolean
*/
const uploadVoiceRecording = useCallback(
async (sendOnComplete: boolean) => {
try {
const { recording, duration, waveformData } = audioRecorderManager.state.getLatestValue();
await stopVoiceRecording();
const durationInSeconds = parseFloat((duration / 1000).toFixed(3));
const resampledWaveformData =
waveformData.length > 100 ? resampleWaveformData(waveformData, 100) : waveformData;
const clearFilter = new RegExp('[.:]', 'g');
const date = new Date().toISOString().replace(clearFilter, '_');
const file: File = {
duration: durationInSeconds,
name: `audio_recording_${date}.aac`,
size: 0,
type: 'audio/aac',
uri:
typeof recording !== 'string' ? (recording?.getURI() as string) : (recording as string),
waveform_data: resampledWaveformData,
};
const audioFile: LocalVoiceRecordingAttachment = {
asset_url:
typeof recording !== 'string' ? (recording?.getURI() as string) : (recording as string),
duration: durationInSeconds,
file_size: 0,
localMetadata: {
file,
id: generateRandomId(),
uploadState: 'pending',
},
mime_type: 'audio/aac',
title: `audio_recording_${date}.aac`,
type: FileTypes.VoiceRecording,
waveform_data: resampledWaveformData,
};
audioRecorderManager.reset();
if (sendOnComplete) {
attachmentManager.upsertAttachments([audioFile]);
sendMessage();
} else {
await attachmentManager.uploadAttachment(audioFile);
}
} catch (error) {
console.log('Error uploading voice recording: ', error);
}
},
[audioRecorderManager, attachmentManager, sendMessage, stopVoiceRecording],
);
return {
deleteVoiceRecording,
startVoiceRecording,
stopVoiceRecording,
uploadVoiceRecording,
};
};