@superapp_men/voice-recorder-capacitor
v1.0.6
Published
Voice recorder with checkpoint support for Capacitor-based SuperApp Partner Apps
Maintainers
Readme
@superapp_men/voice-recorder-capacitor
Voice recorder with checkpoint support for SuperApp Partner Apps. This package provides a clean API for recording audio in partner apps that are hosted within a SuperApp environment, with native audio capture handled by the SuperApp.
Features
- 🎙️ High-Quality Audio Recording - Native audio capture via SuperApp
- 📍 Checkpoint Support - Create intermediate checkpoints during recording to segment audio
- 🔄 Event-Driven Architecture - Real-time state updates and progress events
- ⚙️ Configurable Audio Settings - Customize format (WAV/PCM), sample rate, bit depth, and channels
- 🔐 Permission Management - Built-in permission checking and requesting
- 📱 Cross-Platform - Works on iOS and Android via SuperApp
- 🎯 TypeScript Support - Full TypeScript definitions included
- 🐛 Debug Mode - Comprehensive logging for troubleshooting
Installation
npm install @superapp_men/voice-recorder-capacitorQuick Start
Basic Usage
import {
VoiceRecorder,
RecorderState,
AudioFormat,
SampleRate,
} from "@superapp_men/voice-recorder-capacitor";
// Create a recorder instance
const recorder = new VoiceRecorder({
timeout: 10000,
debug: true,
});
// Check availability
const available = await recorder.isAvailable();
console.log("Recording available:", available);
// Request permission
const permission = await recorder.requestPermission();
if (permission !== "granted") {
console.error("Permission denied");
return;
}
// Start recording
await recorder.startRecording({
audioConfig: {
format: AudioFormat.WAV,
sampleRate: SampleRate.SR_16000,
bitDepth: 16,
channels: 1,
},
maxDuration: 120000, // 2 minutes
});
// Stop recording
const result = await recorder.stopRecording();
console.log("Recording result:", result);
console.log("Audio data:", result.audioData); // Base64-encoded WAVWith Checkpoints
// Start recording with checkpoint mode enabled
await recorder.startRecording({
isCheckpoints: true,
audioConfig: {
format: AudioFormat.WAV,
sampleRate: SampleRate.SR_16000,
bitDepth: 16,
channels: 1,
},
});
// Create checkpoints during recording
const checkpoint1 = await recorder.createCheckpoint();
console.log("Checkpoint 1:", checkpoint1.audioData);
// Continue recording...
const checkpoint2 = await recorder.createCheckpoint();
console.log("Checkpoint 2:", checkpoint2.audioData);
// Stop recording - result includes all checkpoints merged
const result = await recorder.stopRecording();
console.log("All checkpoints:", result.checkpoints);
console.log("Complete recording:", result.audioData); // Merged audioEvent Listeners
// Listen to state changes
recorder.on("stateChange", ({ state }) => {
console.log("State changed:", state);
});
// Listen to progress updates
recorder.on("progress", ({ duration }) => {
console.log("Recording duration:", duration, "ms");
});
// Listen to checkpoint creation
recorder.on("checkpointCreated", ({ checkpoint }) => {
console.log("Checkpoint created:", checkpoint.index);
});
// Listen to errors
recorder.on("error", ({ message }) => {
console.error("Error:", message);
});API Reference
VoiceRecorder Class
Constructor
new VoiceRecorder(config?: VoiceRecorderConfig)Config Options:
timeout?: number- Request timeout in milliseconds (default: 5000)debug?: boolean- Enable debug logging (default: false)
Methods
isAvailable(): Promise<boolean>
Check if voice recording is available on the device.
const available = await recorder.isAvailable();checkPermission(): Promise<PermissionStatus>
Check the current microphone permission status.
Returns: 'granted' | 'denied' | 'prompt' | 'unknown'
const status = await recorder.checkPermission();requestPermission(): Promise<PermissionStatus>
Request microphone permission from the user.
const status = await recorder.requestPermission();
if (status === "granted") {
// Permission granted
}startRecording(config?: RecordingConfig): Promise<void>
Start a new recording session.
Config Options:
isCheckpoints?: boolean- Enable checkpoint mode (default: false)audioConfig?: AudioConfig- Audio encoding configurationmaxDuration?: number- Maximum recording duration in milliseconds
AudioConfig:
format?: AudioFormat- Audio format:AudioFormat.WAVorAudioFormat.PCM(default: WAV)sampleRate?: number- Sample rate in Hz (default: 16000)bitDepth?: number- Bit depth: 8, 16, 24, or 32 (default: 16)channels?: number- Number of channels: 1 (mono) or 2 (stereo) (default: 1)
await recorder.startRecording({
isCheckpoints: true,
audioConfig: {
format: AudioFormat.WAV,
sampleRate: SampleRate.SR_16000,
bitDepth: 16,
channels: 1,
},
maxDuration: 120000,
});stopRecording(): Promise<RecordingResult>
Stop the current recording and return the result.
Returns:
{
audioData: string; // Base64-encoded WAV audio
duration: number; // Total duration in milliseconds
size: number; // Size in bytes
timestamp: number; // Completion timestamp
audioConfig: AudioConfig; // Audio configuration used
checkpointCount: number; // Number of checkpoints created
checkpoints?: Checkpoint[]; // Array of checkpoints (if checkpoint mode)
}createCheckpoint(): Promise<Checkpoint>
Create a checkpoint during recording (only available in checkpoint mode).
Returns:
{
id: string; // Unique checkpoint ID
index: number; // Checkpoint number (1-based)
audioData: string; // Base64-encoded WAV audio segment
duration: number; // Duration from start in milliseconds
segmentDuration: number; // Duration of this segment in milliseconds
size: number; // Size in bytes
timestamp: number; // Creation timestamp
audioConfig: AudioConfig; // Audio configuration used
}getStatus(): Promise<RecordingStatus>
Get the current recording status.
getState(): RecorderState
Get the current recorder state.
Returns: 'idle' | 'requesting_permission' | 'ready' | 'recording' | 'paused' | 'stopped' | 'error'
isCurrentlyRecording(): boolean
Check if currently recording.
getDuration(): number
Get the current recording duration in milliseconds.
getCheckpoints(): Checkpoint[]
Get all checkpoints created during the current recording session.
on<T>(event: RecorderEventType, callback: EventListener<T>): () => void
Add an event listener. Returns an unsubscribe function.
Events:
'stateChange'- Recorder state changed'recordingStarted'- Recording started'recordingStopped'- Recording stopped'checkpointCreated'- Checkpoint created'progress'- Progress update (duration)'error'- Error occurred
off(event: RecorderEventType, callback: EventListener<any>): void
Remove an event listener.
destroy(): void
Clean up resources and remove all listeners.
Enums and Types
RecorderState
enum RecorderState {
IDLE = "idle",
REQUESTING_PERMISSION = "requesting_permission",
READY = "ready",
RECORDING = "recording",
PAUSED = "paused",
STOPPED = "stopped",
ERROR = "error",
}AudioFormat
enum AudioFormat {
WAV = "wav",
PCM = "pcm",
}SampleRate
enum SampleRate {
SR_8000 = 8000,
SR_11025 = 11025,
SR_16000 = 16000,
SR_22050 = 22050,
SR_44100 = 44100,
SR_48000 = 48000,
}PermissionStatus
type PermissionStatus = "granted" | "denied" | "prompt" | "unknown";React Example
import { useEffect, useState } from "react";
import {
VoiceRecorder,
RecorderState,
AudioFormat,
SampleRate,
type RecordingResult,
} from "@superapp_men/voice-recorder-capacitor";
function VoiceRecorderComponent() {
const [recorder] = useState(() => new VoiceRecorder({ debug: true }));
const [state, setState] = useState<RecorderState>(RecorderState.IDLE);
const [recording, setRecording] = useState<RecordingResult | null>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
// Listen to state changes
const unsubscribe = recorder.on("stateChange", ({ state }) => {
setState(state);
});
// Listen to errors
const unsubError = recorder.on("error", ({ message }) => {
setError(message);
});
return () => {
unsubscribe();
unsubError();
recorder.destroy();
};
}, [recorder]);
const handleStart = async () => {
try {
const permission = await recorder.requestPermission();
if (permission !== "granted") {
setError("Permission denied");
return;
}
await recorder.startRecording({
audioConfig: {
format: AudioFormat.WAV,
sampleRate: SampleRate.SR_16000,
bitDepth: 16,
channels: 1,
},
});
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to start");
}
};
const handleStop = async () => {
try {
const result = await recorder.stopRecording();
setRecording(result);
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to stop");
}
};
return (
<div>
<button
onClick={handleStart}
disabled={state === RecorderState.RECORDING}
>
Start Recording
</button>
<button onClick={handleStop} disabled={state !== RecorderState.RECORDING}>
Stop Recording
</button>
{error && <div style={{ color: "red" }}>{error}</div>}
{recording && (
<audio controls src={`data:audio/wav;base64,${recording.audioData}`} />
)}
</div>
);
}Audio Format Support
Supported Formats
- WAV - Waveform Audio File Format (recommended)
- PCM - Raw Pulse Code Modulation
Recommended Configurations
Voice Recording (Low Bandwidth):
{
format: AudioFormat.WAV,
sampleRate: SampleRate.SR_16000,
bitDepth: 16,
channels: 1,
}High Quality:
{
format: AudioFormat.WAV,
sampleRate: SampleRate.SR_44100,
bitDepth: 16,
channels: 2,
}Checkpoint Mode
Checkpoint mode allows you to create intermediate audio segments during a single recording session. This is useful for:
- Creating segments for transcription
- Marking important sections
- Allowing users to review segments before continuing
- Creating structured audio data
When checkpoint mode is enabled:
- Each checkpoint creates a segment of audio from the last checkpoint (or start)
- The final recording result includes all segments merged into one complete audio file
- Individual checkpoint segments are also available in the result
Error Handling
The package uses error events and throws exceptions for error conditions:
try {
await recorder.startRecording();
} catch (error) {
if (error instanceof Error) {
console.error("Recording failed:", error.message);
}
}
// Or use event listener
recorder.on("error", ({ message }) => {
console.error("Error:", message);
});Troubleshooting
Permission Issues
If you encounter permission errors:
- Ensure microphone permission is requested before starting
- Check that the SuperApp has properly configured microphone permissions
- Verify that permission requests are being handled by the SuperApp
Audio Not Playing
- Ensure the audio data is properly base64-encoded
- Use the correct MIME type:
data:audio/wav;base64,${audioData} - Check browser/platform audio codec support
Checkpoint Mode Issues
- Ensure
isCheckpoints: trueis set when starting recording - Check that all checkpoints have valid audio data
- Verify the merged audio result in the final recording
Debug Mode
Enable debug mode for detailed logging:
const recorder = new VoiceRecorder({ debug: true });This will log all operations, state changes, and API calls to the console.
Platform Support
This package is designed for partner apps running within a SuperApp environment. Full functionality is provided when:
- The SuperApp has proper native audio recording support configured
- Microphone permissions are properly handled by the SuperApp
- The SuperApp implements the voice recorder message handlers
License
MIT
Support
- Email: [email protected]
