This is a sound recording application created in ReactJS. It is a learning exercise. Buyer beware.
This is, in many ways, a recreation of this dictaphone web application. However, with this version, I plan on making it a PWA so you can install it on your device and use it without an Internet connection.
I am a bit of a sound effects enthusiast. I have a small collection of sound effects and used to use a very nice Roland stereo recording device but it can sometimes be a burden to carry around. The feature I liked the most about it was its reliability. It was always ready to go and I could record a sound effect in a matter of seconds. I wanted to create a similar experience for myself.
The main feature of this application will be reliability. Once installed, you tap it to open it and tap the record button to start recording immediately. My plan is to save the recording every second so that should the app crash or you accidentally close it, you will not lose your recording.
- Record audio from device microphone with real-time waveform visualization
- Quality presets: Voice (22.05kHz mono 64kbps), Music (44.1kHz stereo 128kbps), Hi-Fi (48kHz stereo 320kbps), and Custom
- Gain boost toggle (1x / 7x amplification)
- Reverb effect toggle
- Recording persists during tab navigation
- File size estimation based on selected quality settings
- Supports WebM/Opus (Chrome, Firefox, Edge) and MP4/AAC (Safari)
- Play, rename, and delete recordings
- Add descriptions and categories (Broad Sound Taxonomy)
- Recordings listed in reverse chronological order with quality badges and sync status indicators
- OAuth2 authentication with Freesound
- Upload recordings to your Freesound account (auto-converts to WAV)
- Download sounds tagged
sound-recorder-syncfrom your account - Edit name/description on approved sounds and push changes to Freesound
- Track moderation status (Processing, In Moderation, Approved, Failed)
- Cross-device sync — recordings uploaded on one device appear on others
- Rate limit handling with automatic backoff and retry
- Install as a standalone app on any device
- Full offline support — record, edit, and manage without internet
- Background sync queues uploads for when connectivity returns
- Service worker with asset precaching for offline-first experience
- Online/offline status indicator
- Record — recording interface with visualizer
- Recordings — manage all local and synced recordings
- Settings — quality presets and advanced audio configuration
- User — Freesound account connection and profile info
You can see a live demo here of the current development version.
The app records in the browser's native format:
- WebM/Opus (
audio/webm;codecs="opus") - Chrome, Firefox, Edge - MP4/AAC (
audio/mp4) - Safari fallback
See src/hooks/useGetMediaRecorder.ts for implementation.
When syncing to Freesound, recordings are converted from WebM/Opus to WAV (16-bit PCM) before upload. See src/utils/audioConverter.ts.
Why WAV instead of uploading WebM directly?
- Freesound officially supports: WAV, FLAC, OGG, MP3, AIFF
- WebM is not officially listed as supported
- WAV is universally accepted and avoids potential compatibility issues
Trade-offs of WAV conversion:
- Larger file size (uncompressed PCM vs compressed Opus)
- Lossy conversion (Opus → PCM is a decode, not a transcode)
- More processing time on client
Future consideration: Freesound also accepts OGG, which uses the same Opus codec as WebM. A WebM → OGG conversion would be a lossless container change (same audio data, different wrapper). However, browsers don't provide a native API for this conversion. Libraries like FFmpeg.wasm could enable this but would add significant bundle size. For now, WAV conversion is simpler and guaranteed to work.
The app supports bidirectional sync with Freesound:
- Upload — local recordings are uploaded to your Freesound account
- Download — remote sounds tagged
sound-recorder-syncare downloaded to the app
Freesound sync uses OAuth 2.0. Because Freesound's OAuth flow requires a server-side token exchange, requests are proxied through a lightweight Cloudflare Worker.
| Variable | Description |
|---|---|
REACT_APP_FREESOUND_CLIENT_ID |
Your Freesound API client ID |
REACT_APP_FREESOUND_OAUTH_PROXY_URL |
URL of the OAuth proxy worker |
See .env.example for reference.
- MediaRecorder API
- MediaStream Recording
- MediaDevices.getUserMedia()
- Mocking methods which are not implemented in JSDOM
- Mocking browser APIs in Jest (localStorage, fetch and more!)
- MediaRecorder Pollyfill
- React Media Recorder
- use-media-recorder (React based hooks to utilize the MediaRecorder API for audio, video and screen recording)
These are issues I reported / uncovered / contributed to while working on this project.