Circle Voice Recorder
A reusable voice recording UI built on top of expo-audio to be used in your projects easily.
SimpleVoiceRecorder
SimpleVoiceRecorder is a tap-to-record screen UI for a demo showcasing the voice recording functionality.
- Big orange circular button
- Idle state: microphone icon
- Recording state: 5 metering “bars” that animate from the center up/down (based on mic input)
- Tap to start / tap to stop
Dependencies
expo-audioexpo-haptics(tap feedback)react-native-reanimated(smooth bar animation)@expo/vector-icons(mic icon)
Props
ts
interface SimpleVoiceRecorderProps {
onRecordingComplete?: (uri: string | null) => void;
title?: string;
tip?: string;
}- onRecordingComplete: Called after the user stops recording. Receives the recorded file
uri. - title: Optional title text shown at the top.
- tip: Optional subtitle/tip text.
Usage
tsx
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { SimpleVoiceRecorder } from '../components/voice-recording';
export default function Screen() {
return (
<View style={styles.container}>
<SimpleVoiceRecorder
title="Braindump tasks with your voice"
tip="Tip: You can mention the time for your task or if it's a routine ;)"
onRecordingComplete={(uri) => {
console.log('Recording URI:', uri);
}}
/>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: '#fff' },
});Playback (debug)
To quickly play back the returned uri, you can use expo-audio’s player hooks:
tsx
import { useAudioPlayer, useAudioPlayerStatus } from 'expo-audio';
function DebugPlayer({ uri }: { uri: string }) {
const player = useAudioPlayer(uri);
const status = useAudioPlayerStatus(player);
return (
<>
<Button title={status.playing ? 'Pause' : 'Play'} onPress={() => (status.playing ? player.pause() : player.play())} />
<Text>{status.currentTime} / {status.duration}</Text>
</>
);
}Metering + Sensitivity
Metering is enabled in useVoiceRecording() via:
audioRecorder.prepareToRecordAsync({ ..., isMeteringEnabled: true })
Wave animation is driven by useWaveform() which polls audioRecorder.getStatus() at the interval defined in:
components/voice-recording/constants.ts→WAVEFORM_CONFIG
Useful knobs:
SILENCE_THRESHOLD: Lower (more negative) = more sensitive to quiet input. Higher = less sensitive.UPDATE_INTERVAL: Lower = more frequent polling (smoother, more CPU).
Notes
- On first use, the system will prompt for microphone permissions.