@independo/capacitor-voice-recorder
Version:
Capacitor plugin for voice recording
120 lines (119 loc) • 6.11 kB
TypeScript
import type { CurrentRecordingStatus, GenericResponse, RecordingData, RecordingOptions } from '../../definitions';
/**
* Ordered MIME types to probe for audio recording via `MediaRecorder.isTypeSupported()`.
*
* ⚠️ The order is intentional and MUST remain stable unless you also update the
* selection policy in code and test on Safari/iOS + WebViews.
*
* ✅ What this list is used for
* - Selecting a `mimeType` for `new MediaRecorder(stream, { mimeType })`.
*
* ❌ What this list does NOT guarantee
* - It does NOT guarantee that the recorded output will be playable via the
* HTML `<audio>` element in the same browser.
*
* Real-world caveat (important):
* - We have observed cases where `MediaRecorder.isTypeSupported('audio/webm;codecs=opus')`
* returned `true`, the recorder produced a Blob, but `<audio>` could not play it.
* This can happen due to container/codec playback support differences, platform
* quirks (especially Safari/iOS / WKWebView), or incomplete WebM playback support.
*
* Current selection behavior in this implementation:
* - By default, MIME selection treats recorder support and playback support as separate
* capabilities and probes both:
* - Recorder capability: `MediaRecorder.isTypeSupported(type)`
* - Playback capability: `audio.canPlayType(type)`
* - This default can be disabled via `RecordingOptions.requirePlaybackSupport = false`
* to fall back to recorder-only probing.
*
* Keeping legacy keys:
* - Some entries are kept even if they overlap (e.g. `audio/mp4` and explicit codec),
* to maximize compatibility across differing browser implementations.
*/
declare const POSSIBLE_MIME_TYPES: Record<string, string>;
/** Browser implementation backed by MediaRecorder and Capacitor Filesystem. */
export declare class VoiceRecorderImpl {
/** Default behavior for web MIME selection: require recorder + playback support. */
private static readonly DEFAULT_REQUIRE_PLAYBACK_SUPPORT;
/** Active MediaRecorder instance, if recording. */
private mediaRecorder;
/** Collected data chunks from MediaRecorder. */
private chunks;
/** Promise resolved when the recorder stops and payload is ready. */
private pendingResult;
/**
* Returns whether the browser can start a recording session.
*
* On web this checks:
* - `navigator.mediaDevices.getUserMedia`
* - at least one supported recording MIME type using {@link getSupportedMimeType}
*
* The optional `requirePlaybackSupport` flag is forwarded to MIME selection and defaults
* to `true` when omitted.
*/
static canDeviceVoiceRecord(options?: Pick<RecordingOptions, 'requirePlaybackSupport'>): Promise<GenericResponse>;
/**
* Starts a recording session using `MediaRecorder`.
*
* The selected MIME type is resolved once at start time (using the optional
* `requirePlaybackSupport` flag from `RecordingOptions`) and reused for the final Blob
* and file extension to keep the recording payload internally consistent.
*/
startRecording(options?: RecordingOptions): Promise<GenericResponse>;
/** Stops the current recording and resolves the pending payload. */
stopRecording(): Promise<RecordingData>;
/** Returns whether the browser has microphone permission. */
static hasAudioRecordingPermission(): Promise<GenericResponse>;
/** Requests microphone permission from the browser. */
static requestAudioRecordingPermission(): Promise<GenericResponse>;
/** Pauses the recording session when supported. */
pauseRecording(): Promise<GenericResponse>;
/** Resumes a paused recording session when supported. */
resumeRecording(): Promise<GenericResponse>;
/** Returns the current recording status from MediaRecorder. */
getCurrentStatus(): Promise<CurrentRecordingStatus>;
/**
* Returns the first MIME type (key of {@link POSSIBLE_MIME_TYPES}) that the current
* environment reports as supported for recording via `MediaRecorder.isTypeSupported()`,
* optionally requiring native HTML `<audio>` playback support too.
*
* The search order is the iteration order of {@link POSSIBLE_MIME_TYPES}.
*
* @typeParam T - A MIME type string that exists as a key in {@link POSSIBLE_MIME_TYPES}.
*
* @returns The first supported MIME type for `MediaRecorder`, or `null` if:
* - `MediaRecorder` is unavailable, or
* - no configured MIME types are supported.
*
* ⚠️ Important: `MediaRecorder` support ≠ `<audio>` playback support
*
* Some browsers/platforms can claim support for recording a format (notably WebM/Opus)
* but still fail to play the resulting Blob through the native HTML audio pipeline.
* This mismatch is especially likely on Safari/iOS / WKWebView variants, so the default
* behavior also probes `HTMLAudioElement.canPlayType(type)` when available.
*
* Selection policy when playback probing is enabled:
* - keep the global priority order from {@link POSSIBLE_MIME_TYPES}
* - among recordable types, prefer the first `"probably"` playable candidate
* - otherwise return the first `"maybe"` playable candidate
* - treat `""` as not playable
*
* Note: The <audio> element is never attached to the DOM, so it won't appear to users or assistive tech.
*
* Fallback behavior:
* - If `document` / `audio.canPlayType` is unavailable (e.g. SSR-like environments),
* this falls back to record-only probing.
*/
static getSupportedMimeType<T extends keyof typeof POSSIBLE_MIME_TYPES>(options?: {
requirePlaybackSupport?: boolean;
}): T | null;
/** Initializes MediaRecorder and wires up handlers. */
private onSuccessfullyStartedRecording;
/** Handles failures from getUserMedia. */
private onFailedToStartRecording;
/** Converts a Blob payload into a base64 string. */
private static blobToBase64;
/** Resets state for the next recording attempt. */
private prepareInstanceForNextOperation;
}
export {};