Skip to main content

VoiceRecorder

Location: src/components/voice/VoiceRecorder.jsx

Overview

VoiceRecorder provides an in-post audio recording interface. Users can record voice notes up to a configurable duration (default 60 seconds), preview the recording, re-record, or remove it. The component uses the MediaRecorder API with automatic MIME type detection and handles browser compatibility, microphone permissions, and error states.

Relevant Invariants

  • Invariant #9: "Time Is Not Weaponized" -- Recording has a generous time limit but no urgency pressure
  • Invariant #1: "Participation Is Always Voluntary" -- Voice is always optional ("Add voice (optional)")

Props

PropTypeRequiredDefaultDescription
onVoiceReadyfunctionYes--Callback when recording completes. Receives { blob, url, duration, mimeType }
onVoiceRemovefunctionYes--Callback when user removes the voice note
maxDurationnumberNo60Maximum recording duration in seconds

States

The component cycles through these states:

StateDescription
idleReady to record, shows mic button
recordingActively recording, shows timer and stop button
attachedRecording complete, shows preview with re-record/remove options
unsupportedBrowser lacks MediaRecorder support, renders nothing

Key Behaviors

  • MIME Type Detection: Tries audio/webm;codecs=opus, audio/webm, audio/mp4, audio/ogg;codecs=opus, audio/ogg in order
  • Audio Processing: Enables echo cancellation, noise suppression, and auto gain control
  • Auto-Stop: Recording automatically stops when maxDuration is reached
  • Device Selection: Respects inputDeviceId from useVoiceSettings context
  • Cleanup: Revokes object URLs and stops media tracks on unmount

Usage

import VoiceRecorder from '../voice/VoiceRecorder';

<VoiceRecorder
onVoiceReady={({ blob, url, duration, mimeType }) => {
setVoiceAttachment({ blob, url, duration, mimeType });
}}
onVoiceRemove={() => setVoiceAttachment(null)}
maxDuration={120}
/>

Last updated: 2026-02-07