UNPKG

@independo/capacitor-voice-recorder

Version:
120 lines (119 loc) 6.11 kB
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 {};