audio-recording-sdk
v0.2.3
Published
React SDK for ambient audio recording with guaranteed uploads and offline support
Readme
audio-recording-sdk
React SDK for ambient audio recording with guaranteed uploads and offline support.
Records audio in chunks, persists every chunk to IndexedDB before uploading, and automatically resumes uploads when the network returns. Built for long sessions (3–5 hours).
Install
npm install audio-recording-sdkPeer dependencies:
npm install react react-domQuick Start
import { useAudioRecorder, getAudios } from 'audio-recording-sdk';
export default function App() {
const { startRecording, stopRecording, status, error } = useAudioRecorder();
const handleGetAudios = async () => {
const audios = await getAudios();
console.log(audios); // list of all recordings for this device
};
return (
<div>
<button onClick={startRecording} disabled={status === 'recording'}>Start</button>
<button onClick={stopRecording} disabled={status !== 'recording'}>Stop</button>
<button onClick={handleGetAudios}>Get Audios</button>
<p>Status: {status}</p>
{error && <p>Error: {error.message}</p>}
</div>
);
}API
useAudioRecorder(config?)
const { startRecording, stopRecording, status, error } = useAudioRecorder(config?);| Option | Default | Description |
|---|---|---|
| headers | undefined | Added to every upload request — use for auth tokens |
| chunkIntervalMs | 30000 | How often a new chunk is created (ms) |
| maxRetries | 5 | Retry attempts per chunk with exponential backoff |
| onChunkUploaded | undefined | Fires after each successful chunk upload |
| onError | undefined | Fires on any error |
| onStatusChange | undefined | Fires on every status change |
| debug | false | Logs internal events to console |
startRecording()
Requests microphone permission and starts recording. Chunks are saved to IndexedDB and uploaded automatically.
stopRecording()
Stops recording and waits for all pending chunks to upload. Returns a RecordingSession.
interface RecordingSession {
sessionId: string;
startedAt: number;
stoppedAt: number;
totalChunks: number;
uploadedChunks: number;
}getAudios()
Fetches all recorded sessions for the current device. Returns an array of AudioSession.
const audios = await getAudios();
interface AudioSession {
sessionId: string;
createdAt: string;
totalChunks: number;
audioUrl: string; // direct URL to play the audio
}Each device is identified by a unique ID generated on first use and stored in localStorage. All recordings made on the same device are returned.
status
type RecordingStatus =
| 'idle'
| 'requesting-permission'
| 'recording'
| 'paused'
| 'uploading'
| 'done'
| 'error';Sharing State Across Components
import { AudioRecorderProvider, useAudioRecorderContext } from 'audio-recording-sdk';
function App() {
return (
<AudioRecorderProvider>
<RecordButton />
<StatusDisplay />
</AudioRecorderProvider>
);
}
function RecordButton() {
const { startRecording, stopRecording } = useAudioRecorderContext();
// ...
}Platform Support
| Platform | Screen lock | Background recording | |---|---|---| | Web browser | Best effort | Continues while tab is open | | Safari iOS (web only) | Stops | Not supported | | Capacitor iOS (native) | Continues | Full background support | | Capacitor Android (native) | Continues | Full background support |
The SDK auto-detects the platform at runtime and switches to the native adapter automatically. No code changes needed.
iOS Background Recording (Capacitor)
1. Install
npm install @capacitor/core @capacitor/ios audio-recording-sdk-plugin
npx cap add ios && npx cap sync ios2. Configure Info.plist
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access is required for audio recording.</string>No code changes needed — SDK auto-detects Capacitor.
Android Background Recording (Capacitor)
1. Install
npm install @capacitor/core @capacitor/android audio-recording-sdk-plugin
npx cap add android && npx cap sync android2. Register plugin in MainActivity.kt
import com.audiosdk.plugin.AudioRecorderPlugin
class MainActivity : BridgeActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
registerPlugin(AudioRecorderPlugin::class.java)
super.onCreate(savedInstanceState)
}
}3. Add permissions to AndroidManifest.xml
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />No code changes needed — SDK auto-detects Capacitor. A persistent notification appears while recording (required by Android for background audio).
How Offline Works
Every chunk is saved to IndexedDB first, then uploaded. When the network drops:
- Recording continues uninterrupted
- Chunks accumulate in IndexedDB
- Upload queue pauses automatically
- When network returns, all pending chunks upload in order
Chunks survive page refreshes and app restarts. On the next startRecording() call, any unuploaded chunks from previous sessions are recovered and re-queued automatically.
Error Handling
const { error } = useAudioRecorder({
onError: (err) => console.error(err.code, err.message),
});
type SDKErrorCode =
| 'PERMISSION_DENIED'
| 'RECORDER_ERROR'
| 'STORAGE_ERROR'
| 'UPLOAD_ERROR'
| 'NETWORK_ERROR';Known Limitations
- Safari iOS (web only): Recording pauses when the screen locks. Use Capacitor for uninterrupted recording.
- Android Chrome (web only): Recording pauses when the screen locks. Use Capacitor for uninterrupted recording.
- Screen lock (any browser): Pressing the power button suspends browser JS on all platforms — use Capacitor native for guaranteed background recording.
- Private browsing: IndexedDB is unavailable. SDK falls back to in-memory storage — chunks are lost if tab closes before upload completes.
License
MIT
