@independo/capacitor-voice-recorder 8.1.9-dev.2 → 8.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/android/src/main/java/app/independo/capacitorvoicerecorder/adapters/RecordDataMapper.java +1 -0
- package/android/src/main/java/app/independo/capacitorvoicerecorder/core/RecordData.java +35 -0
- package/android/src/main/java/app/independo/capacitorvoicerecorder/service/VoiceRecorderService.java +1 -1
- package/dist/docs.json +1 -1
- package/dist/esm/core/recording-contract.js +2 -2
- package/dist/esm/core/recording-contract.js.map +1 -1
- package/dist/esm/definitions.d.ts +4 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/platform/web/VoiceRecorderImpl.js +4 -2
- package/dist/esm/platform/web/VoiceRecorderImpl.js.map +1 -1
- package/dist/plugin.cjs.js +6 -4
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +6 -4
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/VoiceRecorder/Adapters/RecordDataMapper.swift +1 -0
- package/ios/Sources/VoiceRecorder/Core/RecordData.swift +3 -0
- package/ios/Sources/VoiceRecorder/Service/VoiceRecorderService.swift +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -333,9 +333,9 @@ Can be used to specify options for the recording.
|
|
|
333
333
|
|
|
334
334
|
Interface representing the data of a recording.
|
|
335
335
|
|
|
336
|
-
| Prop | Type
|
|
337
|
-
| ----------- |
|
|
338
|
-
| **`value`** | <code>{ recordDataBase64: string; msDuration: number; mimeType: string; uri?: string; }</code> | The value containing the recording details. |
|
|
336
|
+
| Prop | Type | Description |
|
|
337
|
+
| ----------- | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
|
|
338
|
+
| **`value`** | <code>{ recordDataBase64: string; msDuration: number; mimeType: string; fileExtension: string; uri?: string; }</code> | The value containing the recording details. |
|
|
339
339
|
|
|
340
340
|
|
|
341
341
|
#### CurrentRecordingStatus
|
package/android/src/main/java/app/independo/capacitorvoicerecorder/adapters/RecordDataMapper.java
CHANGED
|
@@ -18,6 +18,7 @@ public final class RecordDataMapper {
|
|
|
18
18
|
JSObject normalized = new JSObject();
|
|
19
19
|
normalized.put("msDuration", recordData.getMsDuration());
|
|
20
20
|
normalized.put("mimeType", recordData.getMimeType());
|
|
21
|
+
normalized.put("fileExtension", recordData.getFileExtension());
|
|
21
22
|
|
|
22
23
|
String uri = recordData.getUri();
|
|
23
24
|
String recordDataBase64 = recordData.getRecordDataBase64();
|
|
@@ -11,15 +11,22 @@ public class RecordData {
|
|
|
11
11
|
private String recordDataBase64;
|
|
12
12
|
/** MIME type of the audio payload. */
|
|
13
13
|
private String mimeType;
|
|
14
|
+
/** File extension / format without a leading dot (for example: aac, m4a, mp3). */
|
|
15
|
+
private String fileExtension;
|
|
14
16
|
/** Recording duration in milliseconds. */
|
|
15
17
|
private int msDuration;
|
|
16
18
|
|
|
17
19
|
public RecordData() {}
|
|
18
20
|
|
|
19
21
|
public RecordData(String recordDataBase64, int msDuration, String mimeType, String uri) {
|
|
22
|
+
this(recordDataBase64, msDuration, mimeType, inferFileExtension(mimeType, uri), uri);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public RecordData(String recordDataBase64, int msDuration, String mimeType, String fileExtension, String uri) {
|
|
20
26
|
this.recordDataBase64 = recordDataBase64;
|
|
21
27
|
this.msDuration = msDuration;
|
|
22
28
|
this.mimeType = mimeType;
|
|
29
|
+
this.fileExtension = fileExtension;
|
|
23
30
|
this.uri = uri;
|
|
24
31
|
}
|
|
25
32
|
|
|
@@ -50,6 +57,15 @@ public class RecordData {
|
|
|
50
57
|
this.mimeType = mimeType;
|
|
51
58
|
}
|
|
52
59
|
|
|
60
|
+
/** Returns the file extension / format of the recording. */
|
|
61
|
+
public String getFileExtension() {
|
|
62
|
+
return fileExtension;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public void setFileExtension(String fileExtension) {
|
|
66
|
+
this.fileExtension = fileExtension;
|
|
67
|
+
}
|
|
68
|
+
|
|
53
69
|
/** Returns the file URI, if present. */
|
|
54
70
|
public String getUri() {
|
|
55
71
|
return uri;
|
|
@@ -61,7 +77,26 @@ public class RecordData {
|
|
|
61
77
|
toReturn.put("recordDataBase64", recordDataBase64);
|
|
62
78
|
toReturn.put("msDuration", msDuration);
|
|
63
79
|
toReturn.put("mimeType", mimeType);
|
|
80
|
+
toReturn.put("fileExtension", fileExtension);
|
|
64
81
|
toReturn.put("uri", uri);
|
|
65
82
|
return toReturn;
|
|
66
83
|
}
|
|
84
|
+
|
|
85
|
+
private static String inferFileExtension(String mimeType, String uri) {
|
|
86
|
+
if (uri != null) {
|
|
87
|
+
int dotIndex = uri.lastIndexOf('.');
|
|
88
|
+
if (dotIndex >= 0 && dotIndex < uri.length() - 1) {
|
|
89
|
+
return uri.substring(dotIndex + 1).toLowerCase();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if ("audio/mp4".equals(mimeType)) return "m4a";
|
|
94
|
+
if ("audio/mpeg".equals(mimeType)) return "mp3";
|
|
95
|
+
if ("audio/wav".equals(mimeType)) return "wav";
|
|
96
|
+
if ("audio/webm".equals(mimeType) || "audio/webm;codecs=opus".equals(mimeType)) return "webm";
|
|
97
|
+
if ("audio/ogg;codecs=opus".equals(mimeType) || "audio/ogg;codecs=vorbis".equals(mimeType)) return "ogg";
|
|
98
|
+
if ("audio/aac".equals(mimeType)) return "aac";
|
|
99
|
+
|
|
100
|
+
return "";
|
|
101
|
+
}
|
|
67
102
|
}
|
package/android/src/main/java/app/independo/capacitorvoicerecorder/service/VoiceRecorderService.java
CHANGED
|
@@ -92,7 +92,7 @@ public class VoiceRecorderService {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
int duration = platform.getDurationMs(recordedFile);
|
|
95
|
-
RecordData recordData = new RecordData(recordDataBase64, duration, "audio/aac", uri);
|
|
95
|
+
RecordData recordData = new RecordData(recordDataBase64, duration, "audio/aac", "aac", uri);
|
|
96
96
|
if ((recordDataBase64 == null && uri == null) || recordData.getMsDuration() < 0) {
|
|
97
97
|
throw new VoiceRecorderServiceException(ErrorCodes.EMPTY_RECORDING);
|
|
98
98
|
}
|
package/dist/docs.json
CHANGED
|
@@ -339,7 +339,7 @@
|
|
|
339
339
|
"complexTypes": [
|
|
340
340
|
"Base64String"
|
|
341
341
|
],
|
|
342
|
-
"type": "{ recordDataBase64: string; msDuration: number; mimeType: string; uri?: string | undefined; }"
|
|
342
|
+
"type": "{ recordDataBase64: string; msDuration: number; mimeType: string; fileExtension: string; uri?: string | undefined; }"
|
|
343
343
|
}
|
|
344
344
|
]
|
|
345
345
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Normalizes recording payloads into a stable contract shape. */
|
|
2
2
|
export const normalizeRecordingData = (data) => {
|
|
3
|
-
const { recordDataBase64, uri, msDuration, mimeType } = data.value;
|
|
4
|
-
const normalizedValue = { msDuration, mimeType };
|
|
3
|
+
const { recordDataBase64, uri, msDuration, mimeType, fileExtension } = data.value;
|
|
4
|
+
const normalizedValue = { msDuration, mimeType, fileExtension };
|
|
5
5
|
const trimmedUri = typeof uri === 'string' && uri.length > 0 ? uri : undefined;
|
|
6
6
|
const trimmedBase64 = typeof recordDataBase64 === 'string' && recordDataBase64.length > 0 ? recordDataBase64 : undefined;
|
|
7
7
|
if (trimmedUri) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recording-contract.js","sourceRoot":"","sources":["../../../src/core/recording-contract.ts"],"names":[],"mappings":"AAEA,kEAAkE;AAClE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,IAAmB,EAAiB,EAAE;IACzE,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"recording-contract.js","sourceRoot":"","sources":["../../../src/core/recording-contract.ts"],"names":[],"mappings":"AAEA,kEAAkE;AAClE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,IAAmB,EAAiB,EAAE;IACzE,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;IAClF,MAAM,eAAe,GAA4B,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;IACzF,MAAM,UAAU,GAAG,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/E,MAAM,aAAa,GAAG,OAAO,gBAAgB,KAAK,QAAQ,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC;IAEzH,IAAI,UAAU,EAAE,CAAC;QACb,eAAe,CAAC,GAAG,GAAG,UAAU,CAAC;IACrC,CAAC;SAAM,IAAI,aAAa,EAAE,CAAC;QACvB,eAAe,CAAC,gBAAgB,GAAG,aAAa,CAAC;IACrD,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,eAAe,EAAmB,CAAC;AACvD,CAAC,CAAC","sourcesContent":["import type { RecordingData } from '../definitions';\n\n/** Normalizes recording payloads into a stable contract shape. */\nexport const normalizeRecordingData = (data: RecordingData): RecordingData => {\n const { recordDataBase64, uri, msDuration, mimeType, fileExtension } = data.value;\n const normalizedValue: Record<string, unknown> = { msDuration, mimeType, fileExtension };\n const trimmedUri = typeof uri === 'string' && uri.length > 0 ? uri : undefined;\n const trimmedBase64 = typeof recordDataBase64 === 'string' && recordDataBase64.length > 0 ? recordDataBase64 : undefined;\n\n if (trimmedUri) {\n normalizedValue.uri = trimmedUri;\n } else if (trimmedBase64) {\n normalizedValue.recordDataBase64 = trimmedBase64;\n }\n\n return { value: normalizedValue } as RecordingData;\n};\n"]}
|
|
@@ -51,6 +51,10 @@ export interface RecordingData {
|
|
|
51
51
|
* The MIME type of the recorded file.
|
|
52
52
|
*/
|
|
53
53
|
mimeType: string;
|
|
54
|
+
/**
|
|
55
|
+
* The recorded file extension / format without a leading dot (for example: `m4a`, `aac`, `mp3`, `webm`).
|
|
56
|
+
*/
|
|
57
|
+
fileExtension: string;
|
|
54
58
|
/**
|
|
55
59
|
* The URI of the recording file.
|
|
56
60
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type {PluginListenerHandle} from \"@capacitor/core\";\nimport type {Directory} from \"@capacitor/filesystem\";\n\n/**\n * Represents a Base64 encoded string.\n */\nexport type Base64String = string;\n\n/**\n * Can be used to specify options for the recording.\n */\nexport interface RecordingOptions {\n /**\n * The capacitor filesystem directory where the recording should be saved.\n *\n * If not specified, the recording will be stored in a base64 string and returned in the `RecordingData` object.\n * @see RecordingData\n */\n directory?: Directory;\n\n /**\n * An optional subdirectory in the specified directory where the recording should be saved.\n */\n subDirectory?: string;\n\n /**\n * Whether the web implementation should require the selected recording MIME type\n * to also be playable by the browser's native HTML `<audio>` element.\n *\n * Defaults to `true` on web to reduce cases where `MediaRecorder` reports support\n * for a format but the recorded file cannot be played back in the same browser\n * (observed on some Safari/iOS/WKWebView combinations).\n *\n * Native platforms ignore this option.\n */\n requirePlaybackSupport?: boolean;\n}\n\n/**\n * Interface representing the data of a recording.\n */\nexport interface RecordingData {\n /**\n * The value containing the recording details.\n */\n value: {\n /**\n * The recorded data as a Base64 encoded string.\n */\n recordDataBase64: Base64String;\n /**\n * The duration of the recording in milliseconds.\n */\n msDuration: number;\n /**\n * The MIME type of the recorded file.\n */\n mimeType: string;\n\n /**\n * The URI of the recording file.\n */\n uri?: string;\n };\n}\n\n/**\n * Interface representing a generic response with a boolean value.\n */\nexport interface GenericResponse {\n /**\n * The result of the operation as a boolean value.\n */\n value: boolean;\n}\n\n/**\n * Interface representing the current status of the voice recorder.\n */\nexport interface CurrentRecordingStatus {\n /**\n * The current status of the recorder, which can be one of the following values: 'RECORDING', 'PAUSED', 'INTERRUPTED', 'NONE'.\n */\n status: 'RECORDING' | 'PAUSED' | 'INTERRUPTED' | 'NONE';\n}\n\n/**\n * Event payload for voiceRecordingInterrupted event (empty - no data).\n */\nexport type VoiceRecordingInterruptedEvent = Record<string, never>;\n\n/**\n * Event payload for voiceRecordingInterruptionEnded event (empty - no data).\n */\nexport type VoiceRecordingInterruptionEndedEvent = Record<string, never>;\n\n/**\n * Interface for the VoiceRecorderPlugin which provides methods to record audio.\n */\nexport interface VoiceRecorderPlugin {\n /**\n * Checks if the current device can record audio.\n * On mobile, this function will always resolve to `{ value: true }`.\n * In a browser, it will resolve to `{ value: true }` or `{ value: false }` based on the browser's ability to record.\n * This method does not take into account the permission status, only if the browser itself is capable of recording at all.\n * @returns A promise that resolves to a GenericResponse.\n * @throws Error with code \"COULD_NOT_QUERY_PERMISSION_STATUS\" if the device cannot query the permission status.\n */\n canDeviceVoiceRecord(): Promise<GenericResponse>;\n\n /**\n * Requests audio recording permission from the user.\n * If the permission has already been provided, the promise will resolve with `{ value: true }`.\n * Otherwise, the promise will resolve to `{ value: true }` or `{ value: false }` based on the user's response.\n * @returns A promise that resolves to a GenericResponse.\n * @throws Error if the permission request fails.\n */\n requestAudioRecordingPermission(): Promise<GenericResponse>;\n\n /**\n * Checks if audio recording permission has been granted.\n * Will resolve to `{ value: true }` or `{ value: false }` based on the status of the permission.\n * The web implementation of this plugin uses the Permissions API, which is not widespread.\n * If the status of the permission cannot be checked, the promise will reject with `COULD_NOT_QUERY_PERMISSION_STATUS`.\n * In that case, use `requestAudioRecordingPermission` or `startRecording` and capture any exception that is thrown.\n * @returns A promise that resolves to a GenericResponse.\n * @throws Error with code \"COULD_NOT_QUERY_PERMISSION_STATUS\" if the device cannot query the permission status.\n */\n hasAudioRecordingPermission(): Promise<GenericResponse>;\n\n /**\n * Starts audio recording.\n * On success, the promise will resolve to { value: true }.\n * On error, the promise will reject with one of the following error codes:\n * \"MISSING_PERMISSION\", \"ALREADY_RECORDING\", \"MICROPHONE_BEING_USED\", \"DEVICE_CANNOT_VOICE_RECORD\", or \"FAILED_TO_RECORD\".\n * @param options The options for the recording.\n * @returns A promise that resolves to a GenericResponse.\n * @throws Error with one of the specified error codes if the recording cannot be started.\n */\n startRecording(options?: RecordingOptions): Promise<GenericResponse>;\n\n /**\n * Stops audio recording.\n * Will stop the recording that has been previously started.\n * If the function `startRecording` has not been called beforehand, the promise will reject with `RECORDING_HAS_NOT_STARTED`.\n * If the recording has been stopped immediately after it has been started, the promise will reject with `EMPTY_RECORDING`.\n * In a case of unknown error, the promise will reject with `FAILED_TO_FETCH_RECORDING`.\n * On iOS, if a recording interrupted by the system cannot be merged, the promise will reject with `FAILED_TO_MERGE_RECORDING`.\n * In case of success, the promise resolves to RecordingData containing the recording in base-64, the duration of the recording in milliseconds, and the MIME type.\n * @returns A promise that resolves to RecordingData.\n * @throws Error with one of the specified error codes if the recording cannot be stopped.\n */\n stopRecording(): Promise<RecordingData>;\n\n /**\n * Pauses the ongoing audio recording.\n * If the recording has not started yet, the promise will reject with an error code `RECORDING_HAS_NOT_STARTED`.\n * On success, the promise will resolve to { value: true } if the pause was successful or { value: false } if the recording is already paused.\n * On certain mobile OS versions, this function is not supported and will reject with `NOT_SUPPORTED_OS_VERSION`.\n * @returns A promise that resolves to a GenericResponse.\n * @throws Error with one of the specified error codes if the recording cannot be paused.\n */\n pauseRecording(): Promise<GenericResponse>;\n\n /**\n * Resumes a paused or interrupted audio recording.\n * If the recording has not started yet, the promise will reject with an error code `RECORDING_HAS_NOT_STARTED`.\n * On success, the promise will resolve to { value: true } if the resume was successful or { value: false } if the recording is already running.\n * On certain mobile OS versions, this function is not supported and will reject with `NOT_SUPPORTED_OS_VERSION`.\n * @returns A promise that resolves to a GenericResponse.\n * @throws Error with one of the specified error codes if the recording cannot be resumed.\n */\n resumeRecording(): Promise<GenericResponse>;\n\n /**\n * Gets the current status of the voice recorder.\n * Will resolve with one of the following values:\n * `{ status: \"NONE\" }` if the plugin is idle and waiting to start a new recording.\n * `{ status: \"RECORDING\" }` if the plugin is in the middle of recording.\n * `{ status: \"PAUSED\" }` if the recording is paused.\n * `{ status: \"INTERRUPTED\" }` if the recording was paused due to a system interruption.\n * @returns A promise that resolves to a CurrentRecordingStatus.\n * @throws Error if the status cannot be fetched.\n */\n getCurrentStatus(): Promise<CurrentRecordingStatus>;\n\n /**\n * Listen for audio recording interruptions (e.g., phone calls, other apps using microphone).\n * Available on iOS and Android only.\n *\n * @param eventName The name of the event to listen for.\n * @param listenerFunc The callback function to invoke when the event occurs.\n * @returns A promise that resolves to a PluginListenerHandle.\n */\n addListener(\n eventName: 'voiceRecordingInterrupted',\n listenerFunc: (event: VoiceRecordingInterruptedEvent) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for audio recording interruption end events.\n * Available on iOS and Android only.\n *\n * @param eventName The name of the event to listen for.\n * @param listenerFunc The callback function to invoke when the event occurs.\n * @returns A promise that resolves to a PluginListenerHandle.\n */\n addListener(\n eventName: 'voiceRecordingInterruptionEnded',\n listenerFunc: (event: VoiceRecordingInterruptionEndedEvent) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Remove all listeners for this plugin.\n */\n removeAllListeners(): Promise<void>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type {PluginListenerHandle} from \"@capacitor/core\";\nimport type {Directory} from \"@capacitor/filesystem\";\n\n/**\n * Represents a Base64 encoded string.\n */\nexport type Base64String = string;\n\n/**\n * Can be used to specify options for the recording.\n */\nexport interface RecordingOptions {\n /**\n * The capacitor filesystem directory where the recording should be saved.\n *\n * If not specified, the recording will be stored in a base64 string and returned in the `RecordingData` object.\n * @see RecordingData\n */\n directory?: Directory;\n\n /**\n * An optional subdirectory in the specified directory where the recording should be saved.\n */\n subDirectory?: string;\n\n /**\n * Whether the web implementation should require the selected recording MIME type\n * to also be playable by the browser's native HTML `<audio>` element.\n *\n * Defaults to `true` on web to reduce cases where `MediaRecorder` reports support\n * for a format but the recorded file cannot be played back in the same browser\n * (observed on some Safari/iOS/WKWebView combinations).\n *\n * Native platforms ignore this option.\n */\n requirePlaybackSupport?: boolean;\n}\n\n/**\n * Interface representing the data of a recording.\n */\nexport interface RecordingData {\n /**\n * The value containing the recording details.\n */\n value: {\n /**\n * The recorded data as a Base64 encoded string.\n */\n recordDataBase64: Base64String;\n /**\n * The duration of the recording in milliseconds.\n */\n msDuration: number;\n /**\n * The MIME type of the recorded file.\n */\n mimeType: string;\n /**\n * The recorded file extension / format without a leading dot (for example: `m4a`, `aac`, `mp3`, `webm`).\n */\n fileExtension: string;\n\n /**\n * The URI of the recording file.\n */\n uri?: string;\n };\n}\n\n/**\n * Interface representing a generic response with a boolean value.\n */\nexport interface GenericResponse {\n /**\n * The result of the operation as a boolean value.\n */\n value: boolean;\n}\n\n/**\n * Interface representing the current status of the voice recorder.\n */\nexport interface CurrentRecordingStatus {\n /**\n * The current status of the recorder, which can be one of the following values: 'RECORDING', 'PAUSED', 'INTERRUPTED', 'NONE'.\n */\n status: 'RECORDING' | 'PAUSED' | 'INTERRUPTED' | 'NONE';\n}\n\n/**\n * Event payload for voiceRecordingInterrupted event (empty - no data).\n */\nexport type VoiceRecordingInterruptedEvent = Record<string, never>;\n\n/**\n * Event payload for voiceRecordingInterruptionEnded event (empty - no data).\n */\nexport type VoiceRecordingInterruptionEndedEvent = Record<string, never>;\n\n/**\n * Interface for the VoiceRecorderPlugin which provides methods to record audio.\n */\nexport interface VoiceRecorderPlugin {\n /**\n * Checks if the current device can record audio.\n * On mobile, this function will always resolve to `{ value: true }`.\n * In a browser, it will resolve to `{ value: true }` or `{ value: false }` based on the browser's ability to record.\n * This method does not take into account the permission status, only if the browser itself is capable of recording at all.\n * @returns A promise that resolves to a GenericResponse.\n * @throws Error with code \"COULD_NOT_QUERY_PERMISSION_STATUS\" if the device cannot query the permission status.\n */\n canDeviceVoiceRecord(): Promise<GenericResponse>;\n\n /**\n * Requests audio recording permission from the user.\n * If the permission has already been provided, the promise will resolve with `{ value: true }`.\n * Otherwise, the promise will resolve to `{ value: true }` or `{ value: false }` based on the user's response.\n * @returns A promise that resolves to a GenericResponse.\n * @throws Error if the permission request fails.\n */\n requestAudioRecordingPermission(): Promise<GenericResponse>;\n\n /**\n * Checks if audio recording permission has been granted.\n * Will resolve to `{ value: true }` or `{ value: false }` based on the status of the permission.\n * The web implementation of this plugin uses the Permissions API, which is not widespread.\n * If the status of the permission cannot be checked, the promise will reject with `COULD_NOT_QUERY_PERMISSION_STATUS`.\n * In that case, use `requestAudioRecordingPermission` or `startRecording` and capture any exception that is thrown.\n * @returns A promise that resolves to a GenericResponse.\n * @throws Error with code \"COULD_NOT_QUERY_PERMISSION_STATUS\" if the device cannot query the permission status.\n */\n hasAudioRecordingPermission(): Promise<GenericResponse>;\n\n /**\n * Starts audio recording.\n * On success, the promise will resolve to { value: true }.\n * On error, the promise will reject with one of the following error codes:\n * \"MISSING_PERMISSION\", \"ALREADY_RECORDING\", \"MICROPHONE_BEING_USED\", \"DEVICE_CANNOT_VOICE_RECORD\", or \"FAILED_TO_RECORD\".\n * @param options The options for the recording.\n * @returns A promise that resolves to a GenericResponse.\n * @throws Error with one of the specified error codes if the recording cannot be started.\n */\n startRecording(options?: RecordingOptions): Promise<GenericResponse>;\n\n /**\n * Stops audio recording.\n * Will stop the recording that has been previously started.\n * If the function `startRecording` has not been called beforehand, the promise will reject with `RECORDING_HAS_NOT_STARTED`.\n * If the recording has been stopped immediately after it has been started, the promise will reject with `EMPTY_RECORDING`.\n * In a case of unknown error, the promise will reject with `FAILED_TO_FETCH_RECORDING`.\n * On iOS, if a recording interrupted by the system cannot be merged, the promise will reject with `FAILED_TO_MERGE_RECORDING`.\n * In case of success, the promise resolves to RecordingData containing the recording in base-64, the duration of the recording in milliseconds, and the MIME type.\n * @returns A promise that resolves to RecordingData.\n * @throws Error with one of the specified error codes if the recording cannot be stopped.\n */\n stopRecording(): Promise<RecordingData>;\n\n /**\n * Pauses the ongoing audio recording.\n * If the recording has not started yet, the promise will reject with an error code `RECORDING_HAS_NOT_STARTED`.\n * On success, the promise will resolve to { value: true } if the pause was successful or { value: false } if the recording is already paused.\n * On certain mobile OS versions, this function is not supported and will reject with `NOT_SUPPORTED_OS_VERSION`.\n * @returns A promise that resolves to a GenericResponse.\n * @throws Error with one of the specified error codes if the recording cannot be paused.\n */\n pauseRecording(): Promise<GenericResponse>;\n\n /**\n * Resumes a paused or interrupted audio recording.\n * If the recording has not started yet, the promise will reject with an error code `RECORDING_HAS_NOT_STARTED`.\n * On success, the promise will resolve to { value: true } if the resume was successful or { value: false } if the recording is already running.\n * On certain mobile OS versions, this function is not supported and will reject with `NOT_SUPPORTED_OS_VERSION`.\n * @returns A promise that resolves to a GenericResponse.\n * @throws Error with one of the specified error codes if the recording cannot be resumed.\n */\n resumeRecording(): Promise<GenericResponse>;\n\n /**\n * Gets the current status of the voice recorder.\n * Will resolve with one of the following values:\n * `{ status: \"NONE\" }` if the plugin is idle and waiting to start a new recording.\n * `{ status: \"RECORDING\" }` if the plugin is in the middle of recording.\n * `{ status: \"PAUSED\" }` if the recording is paused.\n * `{ status: \"INTERRUPTED\" }` if the recording was paused due to a system interruption.\n * @returns A promise that resolves to a CurrentRecordingStatus.\n * @throws Error if the status cannot be fetched.\n */\n getCurrentStatus(): Promise<CurrentRecordingStatus>;\n\n /**\n * Listen for audio recording interruptions (e.g., phone calls, other apps using microphone).\n * Available on iOS and Android only.\n *\n * @param eventName The name of the event to listen for.\n * @param listenerFunc The callback function to invoke when the event occurs.\n * @returns A promise that resolves to a PluginListenerHandle.\n */\n addListener(\n eventName: 'voiceRecordingInterrupted',\n listenerFunc: (event: VoiceRecordingInterruptedEvent) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for audio recording interruption end events.\n * Available on iOS and Android only.\n *\n * @param eventName The name of the event to listen for.\n * @param listenerFunc The callback function to invoke when the event occurs.\n * @returns A promise that resolves to a PluginListenerHandle.\n */\n addListener(\n eventName: 'voiceRecordingInterruptionEnded',\n listenerFunc: (event: VoiceRecordingInterruptionEndedEvent) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Remove all listeners for this plugin.\n */\n removeAllListeners(): Promise<void>;\n}\n"]}
|
|
@@ -277,7 +277,7 @@ export class VoiceRecorderImpl {
|
|
|
277
277
|
reject(failedToRecordError());
|
|
278
278
|
};
|
|
279
279
|
this.mediaRecorder.onstop = async () => {
|
|
280
|
-
var _a, _b, _c, _d, _e;
|
|
280
|
+
var _a, _b, _c, _d, _e, _f;
|
|
281
281
|
const mt = (_b = (_a = this.mediaRecorder) === null || _a === void 0 ? void 0 : _a.mimeType) !== null && _b !== void 0 ? _b : mimeType;
|
|
282
282
|
const blobVoiceRecording = new Blob(this.chunks, { type: mt });
|
|
283
283
|
if (blobVoiceRecording.size <= 0) {
|
|
@@ -287,8 +287,9 @@ export class VoiceRecorderImpl {
|
|
|
287
287
|
}
|
|
288
288
|
let uri = undefined;
|
|
289
289
|
let recordDataBase64 = '';
|
|
290
|
+
const fileExtension = ((_c = POSSIBLE_MIME_TYPES[mimeType]) !== null && _c !== void 0 ? _c : '').replace(/^\./, '');
|
|
290
291
|
if (options === null || options === void 0 ? void 0 : options.directory) {
|
|
291
|
-
const subDirectory = (
|
|
292
|
+
const subDirectory = (_f = (_e = (_d = options.subDirectory) === null || _d === void 0 ? void 0 : _d.match(/^\/?(.+[^/])\/?$/)) === null || _e === void 0 ? void 0 : _e[1]) !== null && _f !== void 0 ? _f : '';
|
|
292
293
|
const path = `${subDirectory}/recording-${new Date().getTime()}${POSSIBLE_MIME_TYPES[mt]}`;
|
|
293
294
|
await write_blob({
|
|
294
295
|
blob: blobVoiceRecording,
|
|
@@ -308,6 +309,7 @@ export class VoiceRecorderImpl {
|
|
|
308
309
|
value: {
|
|
309
310
|
recordDataBase64,
|
|
310
311
|
mimeType: mt,
|
|
312
|
+
fileExtension,
|
|
311
313
|
msDuration: recordingDuration * 1000,
|
|
312
314
|
uri
|
|
313
315
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VoiceRecorderImpl.js","sourceRoot":"","sources":["../../../../src/platform/web/VoiceRecorderImpl.ts"],"names":[],"mappings":"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","sourcesContent":["import {Filesystem} from '@capacitor/filesystem';\nimport write_blob from 'capacitor-blob-writer';\n\nimport type {\n Base64String,\n CurrentRecordingStatus,\n GenericResponse,\n RecordingData,\n RecordingOptions,\n} from '../../definitions';\n\nimport getBlobDuration from './get-blob-duration';\nimport {\n alreadyRecordingError,\n couldNotQueryPermissionStatusError,\n deviceCannotVoiceRecordError,\n emptyRecordingError,\n failedToFetchRecordingError,\n failedToRecordError,\n failureResponse,\n missingPermissionError,\n recordingHasNotStartedError,\n successResponse,\n} from './predefined-web-responses';\n\n/**\n * Ordered MIME types to probe for audio recording via `MediaRecorder.isTypeSupported()`.\n *\n * ⚠️ The order is intentional and MUST remain stable unless you also update the\n * selection policy in code and test on Safari/iOS + WebViews.\n *\n * ✅ What this list is used for\n * - Selecting a `mimeType` for `new MediaRecorder(stream, { mimeType })`.\n *\n * ❌ What this list does NOT guarantee\n * - It does NOT guarantee that the recorded output will be playable via the\n * HTML `<audio>` element in the same browser.\n *\n * Real-world caveat (important):\n * - We have observed cases where `MediaRecorder.isTypeSupported('audio/webm;codecs=opus')`\n * returned `true`, the recorder produced a Blob, but `<audio>` could not play it.\n * This can happen due to container/codec playback support differences, platform\n * quirks (especially Safari/iOS / WKWebView), or incomplete WebM playback support.\n *\n * Current selection behavior in this implementation:\n * - By default, MIME selection treats recorder support and playback support as separate\n * capabilities and probes both:\n * - Recorder capability: `MediaRecorder.isTypeSupported(type)`\n * - Playback capability: `audio.canPlayType(type)`\n * - This default can be disabled via `RecordingOptions.requirePlaybackSupport = false`\n * to fall back to recorder-only probing.\n *\n * Keeping legacy keys:\n * - Some entries are kept even if they overlap (e.g. `audio/mp4` and explicit codec),\n * to maximize compatibility across differing browser implementations.\n */\nconst POSSIBLE_MIME_TYPES: Record<string, string> = {\n // ✅ Most universal\n 'audio/mp4;codecs=\"mp4a.40.2\"': '.m4a', // AAC in MP4 (explicit codec helps detection)\n 'audio/mp4': '.m4a', // (legacy key kept; broad support)\n 'audio/aac': '.aac', // (legacy key kept; less common in the wild)\n 'audio/mpeg': '.mp3', // MP3 (universal)\n 'audio/wav': '.wav', // WAV (universal, big files)\n\n // ✅ Modern high-quality (very widely supported, but slightly less “universal” than MP3/AAC)\n 'audio/webm;codecs=\"opus\"': '.webm', // Opus in WebM (explicit codec helps detection)\n 'audio/webm;codecs=opus': '.webm', // (legacy key kept)\n 'audio/webm': '.webm', // (legacy key kept; container-only, codec-dependent)\n\n // ⚠️ Least universal (Safari/iOS historically the limiting factor)\n 'audio/ogg;codecs=opus': '.ogg', // (legacy key kept)\n 'audio/ogg;codecs=vorbis': '.ogg', // Ogg Vorbis (weakest mainstream support)\n};\n\n/** Creates a promise that never resolves. */\nconst neverResolvingPromise = (): Promise<any> => new Promise(() => undefined);\n\n/** Browser implementation backed by MediaRecorder and Capacitor Filesystem. */\nexport class VoiceRecorderImpl {\n /** Default behavior for web MIME selection: require recorder + playback support. */\n private static readonly DEFAULT_REQUIRE_PLAYBACK_SUPPORT = true;\n /** Active MediaRecorder instance, if recording. */\n private mediaRecorder: MediaRecorder | null = null;\n /** Collected data chunks from MediaRecorder. */\n private chunks: any[] = [];\n /** Promise resolved when the recorder stops and payload is ready. */\n private pendingResult: Promise<RecordingData> = neverResolvingPromise();\n\n /**\n * Returns whether the browser can start a recording session.\n *\n * On web this checks:\n * - `navigator.mediaDevices.getUserMedia`\n * - at least one supported recording MIME type using {@link getSupportedMimeType}\n *\n * The optional `requirePlaybackSupport` flag is forwarded to MIME selection and defaults\n * to `true` when omitted.\n */\n public static async canDeviceVoiceRecord(\n options?: Pick<RecordingOptions, 'requirePlaybackSupport'>,\n ): Promise<GenericResponse> {\n if (\n navigator?.mediaDevices?.getUserMedia == null ||\n VoiceRecorderImpl.getSupportedMimeType({\n requirePlaybackSupport: options?.requirePlaybackSupport,\n }) == null\n ) {\n return failureResponse();\n } else {\n return successResponse();\n }\n }\n\n /**\n * Starts a recording session using `MediaRecorder`.\n *\n * The selected MIME type is resolved once at start time (using the optional\n * `requirePlaybackSupport` flag from `RecordingOptions`) and reused for the final Blob\n * and file extension to keep the recording payload internally consistent.\n */\n public async startRecording(options?: RecordingOptions): Promise<GenericResponse> {\n if (this.mediaRecorder != null) {\n throw alreadyRecordingError();\n }\n const deviceCanRecord = await VoiceRecorderImpl.canDeviceVoiceRecord(options);\n if (!deviceCanRecord.value) {\n throw deviceCannotVoiceRecordError();\n }\n const havingPermission = await VoiceRecorderImpl.hasAudioRecordingPermission().catch(() => successResponse());\n if (!havingPermission.value) {\n throw missingPermissionError();\n }\n\n return navigator.mediaDevices\n .getUserMedia({audio: true})\n .then((stream) => this.onSuccessfullyStartedRecording(stream, options))\n .catch(this.onFailedToStartRecording.bind(this));\n }\n\n /** Stops the current recording and resolves the pending payload. */\n public async stopRecording(): Promise<RecordingData> {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n }\n try {\n this.mediaRecorder.stop();\n this.mediaRecorder.stream.getTracks().forEach((track) => track.stop());\n return this.pendingResult;\n } catch (ignore) {\n throw failedToFetchRecordingError();\n } finally {\n this.prepareInstanceForNextOperation();\n }\n }\n\n /** Returns whether the browser has microphone permission. */\n public static async hasAudioRecordingPermission(): Promise<GenericResponse> {\n // Safari does not support navigator.permissions.query\n if (!navigator.permissions.query) {\n if (navigator.mediaDevices !== undefined) {\n return navigator.mediaDevices\n .getUserMedia({audio: true})\n .then(() => successResponse())\n .catch(() => {\n throw couldNotQueryPermissionStatusError();\n });\n }\n }\n return navigator.permissions\n .query({name: 'microphone' as any})\n .then((result) => ({value: result.state === 'granted'}))\n .catch(() => {\n throw couldNotQueryPermissionStatusError();\n });\n }\n\n /** Requests microphone permission from the browser. */\n public static async requestAudioRecordingPermission(): Promise<GenericResponse> {\n const havingPermission = await VoiceRecorderImpl.hasAudioRecordingPermission().catch(() => failureResponse());\n if (havingPermission.value) {\n return successResponse();\n }\n\n return navigator.mediaDevices\n .getUserMedia({audio: true})\n .then(() => successResponse())\n .catch(() => failureResponse());\n }\n\n /** Pauses the recording session when supported. */\n public pauseRecording(): Promise<GenericResponse> {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n } else if (this.mediaRecorder.state === 'recording') {\n this.mediaRecorder.pause();\n return Promise.resolve(successResponse());\n } else {\n return Promise.resolve(failureResponse());\n }\n }\n\n /** Resumes a paused recording session when supported. */\n public resumeRecording(): Promise<GenericResponse> {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n } else if (this.mediaRecorder.state === 'paused') {\n this.mediaRecorder.resume();\n return Promise.resolve(successResponse());\n } else {\n return Promise.resolve(failureResponse());\n }\n }\n\n /** Returns the current recording status from MediaRecorder. */\n public getCurrentStatus(): Promise<CurrentRecordingStatus> {\n if (this.mediaRecorder == null) {\n return Promise.resolve({status: 'NONE'});\n } else if (this.mediaRecorder.state === 'recording') {\n return Promise.resolve({status: 'RECORDING'});\n } else if (this.mediaRecorder.state === 'paused') {\n return Promise.resolve({status: 'PAUSED'});\n } else {\n return Promise.resolve({status: 'NONE'});\n }\n }\n\n /**\n * Returns the first MIME type (key of {@link POSSIBLE_MIME_TYPES}) that the current\n * environment reports as supported for recording via `MediaRecorder.isTypeSupported()`,\n * optionally requiring native HTML `<audio>` playback support too.\n *\n * The search order is the iteration order of {@link POSSIBLE_MIME_TYPES}.\n *\n * @typeParam T - A MIME type string that exists as a key in {@link POSSIBLE_MIME_TYPES}.\n *\n * @returns The first supported MIME type for `MediaRecorder`, or `null` if:\n * - `MediaRecorder` is unavailable, or\n * - no configured MIME types are supported.\n *\n * ⚠️ Important: `MediaRecorder` support ≠ `<audio>` playback support\n *\n * Some browsers/platforms can claim support for recording a format (notably WebM/Opus)\n * but still fail to play the resulting Blob through the native HTML audio pipeline.\n * This mismatch is especially likely on Safari/iOS / WKWebView variants, so the default\n * behavior also probes `HTMLAudioElement.canPlayType(type)` when available.\n *\n * Selection policy when playback probing is enabled:\n * - keep the global priority order from {@link POSSIBLE_MIME_TYPES}\n * - among recordable types, prefer the first `\"probably\"` playable candidate\n * - otherwise return the first `\"maybe\"` playable candidate\n * - treat `\"\"` as not playable\n *\n * Note: The <audio> element is never attached to the DOM, so it won't appear to users or assistive tech.\n *\n * Fallback behavior:\n * - If `document` / `audio.canPlayType` is unavailable (e.g. SSR-like environments),\n * this falls back to record-only probing.\n */\n public static getSupportedMimeType<T extends keyof typeof POSSIBLE_MIME_TYPES>(\n options?: { requirePlaybackSupport?: boolean },\n ): T | null {\n if (MediaRecorder?.isTypeSupported == null) return null;\n\n const orderedTypes = Object.keys(POSSIBLE_MIME_TYPES) as T[];\n const recordSupportedTypes = orderedTypes.filter((type) => MediaRecorder.isTypeSupported(type));\n if (recordSupportedTypes.length === 0) return null;\n\n const requirePlaybackSupport =\n options?.requirePlaybackSupport ?? VoiceRecorderImpl.DEFAULT_REQUIRE_PLAYBACK_SUPPORT;\n if (!requirePlaybackSupport) {\n return recordSupportedTypes[0] ?? null;\n }\n\n if (typeof document === 'undefined' || typeof document.createElement !== 'function') {\n return recordSupportedTypes[0] ?? null;\n }\n\n const audioElement = document.createElement('audio') as Partial<HTMLAudioElement>;\n if (typeof audioElement.canPlayType !== 'function') {\n return recordSupportedTypes[0] ?? null;\n }\n\n let firstProbably: T | null = null;\n let firstMaybe: T | null = null;\n\n for (const type of recordSupportedTypes) {\n const playbackSupport = audioElement.canPlayType(type);\n if (playbackSupport === 'probably') {\n firstProbably = type;\n break;\n }\n if (playbackSupport === 'maybe' && firstMaybe == null) {\n firstMaybe = type;\n }\n }\n\n return firstProbably ?? firstMaybe ?? null;\n }\n\n /** Initializes MediaRecorder and wires up handlers. */\n private onSuccessfullyStartedRecording(stream: MediaStream, options?: RecordingOptions): GenericResponse {\n this.pendingResult = new Promise((resolve, reject) => {\n const mimeType = VoiceRecorderImpl.getSupportedMimeType({\n requirePlaybackSupport: options?.requirePlaybackSupport,\n });\n if (mimeType == null) {\n this.prepareInstanceForNextOperation();\n reject(failedToRecordError());\n return;\n }\n\n this.mediaRecorder = new MediaRecorder(stream, {mimeType});\n this.mediaRecorder.onerror = () => {\n this.prepareInstanceForNextOperation();\n reject(failedToRecordError());\n };\n this.mediaRecorder.onstop = async () => {\n const mt = this.mediaRecorder?.mimeType ?? mimeType;\n const blobVoiceRecording = new Blob(this.chunks, {type: mt});\n if (blobVoiceRecording.size <= 0) {\n this.prepareInstanceForNextOperation();\n reject(emptyRecordingError());\n return;\n }\n\n let uri: string | undefined = undefined;\n let recordDataBase64 = '';\n if (options?.directory) {\n const subDirectory = options.subDirectory?.match(/^\\/?(.+[^/])\\/?$/)?.[1] ?? '';\n const path = `${subDirectory}/recording-${new Date().getTime()}${POSSIBLE_MIME_TYPES[mt]}`;\n\n await write_blob({\n blob: blobVoiceRecording,\n directory: options.directory,\n fast_mode: true,\n path,\n recursive: true,\n });\n\n ({uri} = await Filesystem.getUri({directory: options.directory, path}));\n } else {\n recordDataBase64 = await VoiceRecorderImpl.blobToBase64(blobVoiceRecording);\n }\n\n const recordingDuration = await getBlobDuration(blobVoiceRecording);\n this.prepareInstanceForNextOperation();\n resolve({\n value: {\n recordDataBase64,\n mimeType: mt,\n msDuration: recordingDuration * 1000,\n uri\n }\n });\n };\n this.mediaRecorder.ondataavailable = (event: any) => this.chunks.push(event.data);\n this.mediaRecorder.start();\n });\n return successResponse();\n }\n\n /** Handles failures from getUserMedia. */\n private onFailedToStartRecording(): GenericResponse {\n this.prepareInstanceForNextOperation();\n throw failedToRecordError();\n }\n\n /** Converts a Blob payload into a base64 string. */\n private static blobToBase64(blob: Blob): Promise<Base64String> {\n return new Promise((resolve) => {\n const reader = new FileReader();\n reader.onloadend = () => {\n const recordingResult = String(reader.result);\n const splitResult = recordingResult.split('base64,');\n const toResolve = splitResult.length > 1 ? splitResult[1] : recordingResult;\n resolve(toResolve.trim());\n };\n reader.readAsDataURL(blob);\n });\n }\n\n /** Resets state for the next recording attempt. */\n private prepareInstanceForNextOperation(): void {\n if (this.mediaRecorder != null && this.mediaRecorder.state === 'recording') {\n try {\n this.mediaRecorder.stop();\n } catch (ignore) {\n console.warn('Failed to stop recording during cleanup');\n }\n }\n this.pendingResult = neverResolvingPromise();\n this.mediaRecorder = null;\n this.chunks = [];\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"VoiceRecorderImpl.js","sourceRoot":"","sources":["../../../../src/platform/web/VoiceRecorderImpl.ts"],"names":[],"mappings":"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","sourcesContent":["import {Filesystem} from '@capacitor/filesystem';\nimport write_blob from 'capacitor-blob-writer';\n\nimport type {\n Base64String,\n CurrentRecordingStatus,\n GenericResponse,\n RecordingData,\n RecordingOptions,\n} from '../../definitions';\n\nimport getBlobDuration from './get-blob-duration';\nimport {\n alreadyRecordingError,\n couldNotQueryPermissionStatusError,\n deviceCannotVoiceRecordError,\n emptyRecordingError,\n failedToFetchRecordingError,\n failedToRecordError,\n failureResponse,\n missingPermissionError,\n recordingHasNotStartedError,\n successResponse,\n} from './predefined-web-responses';\n\n/**\n * Ordered MIME types to probe for audio recording via `MediaRecorder.isTypeSupported()`.\n *\n * ⚠️ The order is intentional and MUST remain stable unless you also update the\n * selection policy in code and test on Safari/iOS + WebViews.\n *\n * ✅ What this list is used for\n * - Selecting a `mimeType` for `new MediaRecorder(stream, { mimeType })`.\n *\n * ❌ What this list does NOT guarantee\n * - It does NOT guarantee that the recorded output will be playable via the\n * HTML `<audio>` element in the same browser.\n *\n * Real-world caveat (important):\n * - We have observed cases where `MediaRecorder.isTypeSupported('audio/webm;codecs=opus')`\n * returned `true`, the recorder produced a Blob, but `<audio>` could not play it.\n * This can happen due to container/codec playback support differences, platform\n * quirks (especially Safari/iOS / WKWebView), or incomplete WebM playback support.\n *\n * Current selection behavior in this implementation:\n * - By default, MIME selection treats recorder support and playback support as separate\n * capabilities and probes both:\n * - Recorder capability: `MediaRecorder.isTypeSupported(type)`\n * - Playback capability: `audio.canPlayType(type)`\n * - This default can be disabled via `RecordingOptions.requirePlaybackSupport = false`\n * to fall back to recorder-only probing.\n *\n * Keeping legacy keys:\n * - Some entries are kept even if they overlap (e.g. `audio/mp4` and explicit codec),\n * to maximize compatibility across differing browser implementations.\n */\nconst POSSIBLE_MIME_TYPES: Record<string, string> = {\n // ✅ Most universal\n 'audio/mp4;codecs=\"mp4a.40.2\"': '.m4a', // AAC in MP4 (explicit codec helps detection)\n 'audio/mp4': '.m4a', // (legacy key kept; broad support)\n 'audio/aac': '.aac', // (legacy key kept; less common in the wild)\n 'audio/mpeg': '.mp3', // MP3 (universal)\n 'audio/wav': '.wav', // WAV (universal, big files)\n\n // ✅ Modern high-quality (very widely supported, but slightly less “universal” than MP3/AAC)\n 'audio/webm;codecs=\"opus\"': '.webm', // Opus in WebM (explicit codec helps detection)\n 'audio/webm;codecs=opus': '.webm', // (legacy key kept)\n 'audio/webm': '.webm', // (legacy key kept; container-only, codec-dependent)\n\n // ⚠️ Least universal (Safari/iOS historically the limiting factor)\n 'audio/ogg;codecs=opus': '.ogg', // (legacy key kept)\n 'audio/ogg;codecs=vorbis': '.ogg', // Ogg Vorbis (weakest mainstream support)\n};\n\n/** Creates a promise that never resolves. */\nconst neverResolvingPromise = (): Promise<any> => new Promise(() => undefined);\n\n/** Browser implementation backed by MediaRecorder and Capacitor Filesystem. */\nexport class VoiceRecorderImpl {\n /** Default behavior for web MIME selection: require recorder + playback support. */\n private static readonly DEFAULT_REQUIRE_PLAYBACK_SUPPORT = true;\n /** Active MediaRecorder instance, if recording. */\n private mediaRecorder: MediaRecorder | null = null;\n /** Collected data chunks from MediaRecorder. */\n private chunks: any[] = [];\n /** Promise resolved when the recorder stops and payload is ready. */\n private pendingResult: Promise<RecordingData> = neverResolvingPromise();\n\n /**\n * Returns whether the browser can start a recording session.\n *\n * On web this checks:\n * - `navigator.mediaDevices.getUserMedia`\n * - at least one supported recording MIME type using {@link getSupportedMimeType}\n *\n * The optional `requirePlaybackSupport` flag is forwarded to MIME selection and defaults\n * to `true` when omitted.\n */\n public static async canDeviceVoiceRecord(\n options?: Pick<RecordingOptions, 'requirePlaybackSupport'>,\n ): Promise<GenericResponse> {\n if (\n navigator?.mediaDevices?.getUserMedia == null ||\n VoiceRecorderImpl.getSupportedMimeType({\n requirePlaybackSupport: options?.requirePlaybackSupport,\n }) == null\n ) {\n return failureResponse();\n } else {\n return successResponse();\n }\n }\n\n /**\n * Starts a recording session using `MediaRecorder`.\n *\n * The selected MIME type is resolved once at start time (using the optional\n * `requirePlaybackSupport` flag from `RecordingOptions`) and reused for the final Blob\n * and file extension to keep the recording payload internally consistent.\n */\n public async startRecording(options?: RecordingOptions): Promise<GenericResponse> {\n if (this.mediaRecorder != null) {\n throw alreadyRecordingError();\n }\n const deviceCanRecord = await VoiceRecorderImpl.canDeviceVoiceRecord(options);\n if (!deviceCanRecord.value) {\n throw deviceCannotVoiceRecordError();\n }\n const havingPermission = await VoiceRecorderImpl.hasAudioRecordingPermission().catch(() => successResponse());\n if (!havingPermission.value) {\n throw missingPermissionError();\n }\n\n return navigator.mediaDevices\n .getUserMedia({audio: true})\n .then((stream) => this.onSuccessfullyStartedRecording(stream, options))\n .catch(this.onFailedToStartRecording.bind(this));\n }\n\n /** Stops the current recording and resolves the pending payload. */\n public async stopRecording(): Promise<RecordingData> {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n }\n try {\n this.mediaRecorder.stop();\n this.mediaRecorder.stream.getTracks().forEach((track) => track.stop());\n return this.pendingResult;\n } catch (ignore) {\n throw failedToFetchRecordingError();\n } finally {\n this.prepareInstanceForNextOperation();\n }\n }\n\n /** Returns whether the browser has microphone permission. */\n public static async hasAudioRecordingPermission(): Promise<GenericResponse> {\n // Safari does not support navigator.permissions.query\n if (!navigator.permissions.query) {\n if (navigator.mediaDevices !== undefined) {\n return navigator.mediaDevices\n .getUserMedia({audio: true})\n .then(() => successResponse())\n .catch(() => {\n throw couldNotQueryPermissionStatusError();\n });\n }\n }\n return navigator.permissions\n .query({name: 'microphone' as any})\n .then((result) => ({value: result.state === 'granted'}))\n .catch(() => {\n throw couldNotQueryPermissionStatusError();\n });\n }\n\n /** Requests microphone permission from the browser. */\n public static async requestAudioRecordingPermission(): Promise<GenericResponse> {\n const havingPermission = await VoiceRecorderImpl.hasAudioRecordingPermission().catch(() => failureResponse());\n if (havingPermission.value) {\n return successResponse();\n }\n\n return navigator.mediaDevices\n .getUserMedia({audio: true})\n .then(() => successResponse())\n .catch(() => failureResponse());\n }\n\n /** Pauses the recording session when supported. */\n public pauseRecording(): Promise<GenericResponse> {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n } else if (this.mediaRecorder.state === 'recording') {\n this.mediaRecorder.pause();\n return Promise.resolve(successResponse());\n } else {\n return Promise.resolve(failureResponse());\n }\n }\n\n /** Resumes a paused recording session when supported. */\n public resumeRecording(): Promise<GenericResponse> {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n } else if (this.mediaRecorder.state === 'paused') {\n this.mediaRecorder.resume();\n return Promise.resolve(successResponse());\n } else {\n return Promise.resolve(failureResponse());\n }\n }\n\n /** Returns the current recording status from MediaRecorder. */\n public getCurrentStatus(): Promise<CurrentRecordingStatus> {\n if (this.mediaRecorder == null) {\n return Promise.resolve({status: 'NONE'});\n } else if (this.mediaRecorder.state === 'recording') {\n return Promise.resolve({status: 'RECORDING'});\n } else if (this.mediaRecorder.state === 'paused') {\n return Promise.resolve({status: 'PAUSED'});\n } else {\n return Promise.resolve({status: 'NONE'});\n }\n }\n\n /**\n * Returns the first MIME type (key of {@link POSSIBLE_MIME_TYPES}) that the current\n * environment reports as supported for recording via `MediaRecorder.isTypeSupported()`,\n * optionally requiring native HTML `<audio>` playback support too.\n *\n * The search order is the iteration order of {@link POSSIBLE_MIME_TYPES}.\n *\n * @typeParam T - A MIME type string that exists as a key in {@link POSSIBLE_MIME_TYPES}.\n *\n * @returns The first supported MIME type for `MediaRecorder`, or `null` if:\n * - `MediaRecorder` is unavailable, or\n * - no configured MIME types are supported.\n *\n * ⚠️ Important: `MediaRecorder` support ≠ `<audio>` playback support\n *\n * Some browsers/platforms can claim support for recording a format (notably WebM/Opus)\n * but still fail to play the resulting Blob through the native HTML audio pipeline.\n * This mismatch is especially likely on Safari/iOS / WKWebView variants, so the default\n * behavior also probes `HTMLAudioElement.canPlayType(type)` when available.\n *\n * Selection policy when playback probing is enabled:\n * - keep the global priority order from {@link POSSIBLE_MIME_TYPES}\n * - among recordable types, prefer the first `\"probably\"` playable candidate\n * - otherwise return the first `\"maybe\"` playable candidate\n * - treat `\"\"` as not playable\n *\n * Note: The <audio> element is never attached to the DOM, so it won't appear to users or assistive tech.\n *\n * Fallback behavior:\n * - If `document` / `audio.canPlayType` is unavailable (e.g. SSR-like environments),\n * this falls back to record-only probing.\n */\n public static getSupportedMimeType<T extends keyof typeof POSSIBLE_MIME_TYPES>(\n options?: { requirePlaybackSupport?: boolean },\n ): T | null {\n if (MediaRecorder?.isTypeSupported == null) return null;\n\n const orderedTypes = Object.keys(POSSIBLE_MIME_TYPES) as T[];\n const recordSupportedTypes = orderedTypes.filter((type) => MediaRecorder.isTypeSupported(type));\n if (recordSupportedTypes.length === 0) return null;\n\n const requirePlaybackSupport =\n options?.requirePlaybackSupport ?? VoiceRecorderImpl.DEFAULT_REQUIRE_PLAYBACK_SUPPORT;\n if (!requirePlaybackSupport) {\n return recordSupportedTypes[0] ?? null;\n }\n\n if (typeof document === 'undefined' || typeof document.createElement !== 'function') {\n return recordSupportedTypes[0] ?? null;\n }\n\n const audioElement = document.createElement('audio') as Partial<HTMLAudioElement>;\n if (typeof audioElement.canPlayType !== 'function') {\n return recordSupportedTypes[0] ?? null;\n }\n\n let firstProbably: T | null = null;\n let firstMaybe: T | null = null;\n\n for (const type of recordSupportedTypes) {\n const playbackSupport = audioElement.canPlayType(type);\n if (playbackSupport === 'probably') {\n firstProbably = type;\n break;\n }\n if (playbackSupport === 'maybe' && firstMaybe == null) {\n firstMaybe = type;\n }\n }\n\n return firstProbably ?? firstMaybe ?? null;\n }\n\n /** Initializes MediaRecorder and wires up handlers. */\n private onSuccessfullyStartedRecording(stream: MediaStream, options?: RecordingOptions): GenericResponse {\n this.pendingResult = new Promise((resolve, reject) => {\n const mimeType = VoiceRecorderImpl.getSupportedMimeType({\n requirePlaybackSupport: options?.requirePlaybackSupport,\n });\n if (mimeType == null) {\n this.prepareInstanceForNextOperation();\n reject(failedToRecordError());\n return;\n }\n\n this.mediaRecorder = new MediaRecorder(stream, {mimeType});\n this.mediaRecorder.onerror = () => {\n this.prepareInstanceForNextOperation();\n reject(failedToRecordError());\n };\n this.mediaRecorder.onstop = async () => {\n const mt = this.mediaRecorder?.mimeType ?? mimeType;\n const blobVoiceRecording = new Blob(this.chunks, {type: mt});\n if (blobVoiceRecording.size <= 0) {\n this.prepareInstanceForNextOperation();\n reject(emptyRecordingError());\n return;\n }\n\n let uri: string | undefined = undefined;\n let recordDataBase64 = '';\n const fileExtension = (POSSIBLE_MIME_TYPES[mimeType] ?? '').replace(/^\\./, '');\n if (options?.directory) {\n const subDirectory = options.subDirectory?.match(/^\\/?(.+[^/])\\/?$/)?.[1] ?? '';\n const path = `${subDirectory}/recording-${new Date().getTime()}${POSSIBLE_MIME_TYPES[mt]}`;\n\n await write_blob({\n blob: blobVoiceRecording,\n directory: options.directory,\n fast_mode: true,\n path,\n recursive: true,\n });\n\n ({uri} = await Filesystem.getUri({directory: options.directory, path}));\n } else {\n recordDataBase64 = await VoiceRecorderImpl.blobToBase64(blobVoiceRecording);\n }\n\n const recordingDuration = await getBlobDuration(blobVoiceRecording);\n this.prepareInstanceForNextOperation();\n resolve({\n value: {\n recordDataBase64,\n mimeType: mt,\n fileExtension,\n msDuration: recordingDuration * 1000,\n uri\n }\n });\n };\n this.mediaRecorder.ondataavailable = (event: any) => this.chunks.push(event.data);\n this.mediaRecorder.start();\n });\n return successResponse();\n }\n\n /** Handles failures from getUserMedia. */\n private onFailedToStartRecording(): GenericResponse {\n this.prepareInstanceForNextOperation();\n throw failedToRecordError();\n }\n\n /** Converts a Blob payload into a base64 string. */\n private static blobToBase64(blob: Blob): Promise<Base64String> {\n return new Promise((resolve) => {\n const reader = new FileReader();\n reader.onloadend = () => {\n const recordingResult = String(reader.result);\n const splitResult = recordingResult.split('base64,');\n const toResolve = splitResult.length > 1 ? splitResult[1] : recordingResult;\n resolve(toResolve.trim());\n };\n reader.readAsDataURL(blob);\n });\n }\n\n /** Resets state for the next recording attempt. */\n private prepareInstanceForNextOperation(): void {\n if (this.mediaRecorder != null && this.mediaRecorder.state === 'recording') {\n try {\n this.mediaRecorder.stop();\n } catch (ignore) {\n console.warn('Failed to stop recording during cleanup');\n }\n }\n this.pendingResult = neverResolvingPromise();\n this.mediaRecorder = null;\n this.chunks = [];\n }\n}\n"]}
|
package/dist/plugin.cjs.js
CHANGED
|
@@ -352,7 +352,7 @@ class VoiceRecorderImpl {
|
|
|
352
352
|
reject(failedToRecordError());
|
|
353
353
|
};
|
|
354
354
|
this.mediaRecorder.onstop = async () => {
|
|
355
|
-
var _a, _b, _c, _d, _e;
|
|
355
|
+
var _a, _b, _c, _d, _e, _f;
|
|
356
356
|
const mt = (_b = (_a = this.mediaRecorder) === null || _a === void 0 ? void 0 : _a.mimeType) !== null && _b !== void 0 ? _b : mimeType;
|
|
357
357
|
const blobVoiceRecording = new Blob(this.chunks, { type: mt });
|
|
358
358
|
if (blobVoiceRecording.size <= 0) {
|
|
@@ -362,8 +362,9 @@ class VoiceRecorderImpl {
|
|
|
362
362
|
}
|
|
363
363
|
let uri = undefined;
|
|
364
364
|
let recordDataBase64 = '';
|
|
365
|
+
const fileExtension = ((_c = POSSIBLE_MIME_TYPES[mimeType]) !== null && _c !== void 0 ? _c : '').replace(/^\./, '');
|
|
365
366
|
if (options === null || options === void 0 ? void 0 : options.directory) {
|
|
366
|
-
const subDirectory = (
|
|
367
|
+
const subDirectory = (_f = (_e = (_d = options.subDirectory) === null || _d === void 0 ? void 0 : _d.match(/^\/?(.+[^/])\/?$/)) === null || _e === void 0 ? void 0 : _e[1]) !== null && _f !== void 0 ? _f : '';
|
|
367
368
|
const path = `${subDirectory}/recording-${new Date().getTime()}${POSSIBLE_MIME_TYPES[mt]}`;
|
|
368
369
|
await write_blob({
|
|
369
370
|
blob: blobVoiceRecording,
|
|
@@ -383,6 +384,7 @@ class VoiceRecorderImpl {
|
|
|
383
384
|
value: {
|
|
384
385
|
recordDataBase64,
|
|
385
386
|
mimeType: mt,
|
|
387
|
+
fileExtension,
|
|
386
388
|
msDuration: recordingDuration * 1000,
|
|
387
389
|
uri
|
|
388
390
|
}
|
|
@@ -509,8 +511,8 @@ const attachCanonicalErrorCode = (error) => {
|
|
|
509
511
|
|
|
510
512
|
/** Normalizes recording payloads into a stable contract shape. */
|
|
511
513
|
const normalizeRecordingData = (data) => {
|
|
512
|
-
const { recordDataBase64, uri, msDuration, mimeType } = data.value;
|
|
513
|
-
const normalizedValue = { msDuration, mimeType };
|
|
514
|
+
const { recordDataBase64, uri, msDuration, mimeType, fileExtension } = data.value;
|
|
515
|
+
const normalizedValue = { msDuration, mimeType, fileExtension };
|
|
514
516
|
const trimmedUri = typeof uri === 'string' && uri.length > 0 ? uri : undefined;
|
|
515
517
|
const trimmedBase64 = typeof recordDataBase64 === 'string' && recordDataBase64.length > 0 ? recordDataBase64 : undefined;
|
|
516
518
|
if (trimmedUri) {
|
package/dist/plugin.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/platform/web/get-blob-duration.js","esm/platform/web/predefined-web-responses.js","esm/platform/web/VoiceRecorderImpl.js","esm/adapters/VoiceRecorderWebAdapter.js","esm/core/response-format.js","esm/core/error-codes.js","esm/core/recording-contract.js","esm/service/VoiceRecorderService.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst VoiceRecorder = registerPlugin('VoiceRecorder', {\n web: () => import('./web').then((m) => new m.VoiceRecorderWeb()),\n});\nexport * from './definitions';\nexport { VoiceRecorder };\n//# sourceMappingURL=index.js.map","/**\n * @param {Blob | string} blob\n * @returns {Promise<number>} Blob duration in seconds.\n */\nexport default async function getBlobDuration(blob) {\n // Check for AudioContext or webkitAudioContext (Safari)\n const AudioCtx = window.AudioContext || window.webkitAudioContext;\n if (!AudioCtx) {\n throw new Error('AudioContext is not supported in this environment.');\n }\n let audioContext = null;\n try {\n audioContext = new AudioCtx();\n let arrayBuffer;\n if (typeof blob === 'string') {\n arrayBuffer = base64ToArrayBuffer(blob);\n }\n else {\n arrayBuffer = await blob.arrayBuffer();\n }\n const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);\n return audioBuffer.duration;\n }\n catch (err) {\n throw new Error('Failed to get audio duration (AudioContext may require user interaction or is not supported): ' + (err instanceof Error ? err.message : String(err)));\n }\n finally {\n if (audioContext) {\n await audioContext.close();\n }\n }\n}\n/**\n * Convert base64 string to ArrayBuffer.\n * @param base64 The base64 string to convert.\n * @returns The converted ArrayBuffer.\n * @remarks This function is exported for test coverage purposes.\n */\nexport function base64ToArrayBuffer(base64) {\n const cleanBase64 = base64.replace(/^data:[^;]+;base64,/, '');\n const binaryString = atob(cleanBase64);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n}\n//# sourceMappingURL=get-blob-duration.js.map","/** Success wrapper for boolean plugin responses. */\nexport const successResponse = () => ({ value: true });\n/** Failure wrapper for boolean plugin responses. */\nexport const failureResponse = () => ({ value: false });\n/** Error for missing microphone permission. */\nexport const missingPermissionError = () => new Error('MISSING_PERMISSION');\n/** Error for attempting to start while already recording. */\nexport const alreadyRecordingError = () => new Error('ALREADY_RECORDING');\n/** Error for microphone in use by another app or recorder. */\nexport const microphoneBeingUsedError = () => new Error('MICROPHONE_BEING_USED');\n/** Error for devices that cannot record audio. */\nexport const deviceCannotVoiceRecordError = () => new Error('DEVICE_CANNOT_VOICE_RECORD');\n/** Error for recorder start failures. */\nexport const failedToRecordError = () => new Error('FAILED_TO_RECORD');\n/** Error for empty or zero-length recordings. */\nexport const emptyRecordingError = () => new Error('EMPTY_RECORDING');\n/** Error for stopping without an active recording. */\nexport const recordingHasNotStartedError = () => new Error('RECORDING_HAS_NOT_STARTED');\n/** Error for failures when fetching recording data. */\nexport const failedToFetchRecordingError = () => new Error('FAILED_TO_FETCH_RECORDING');\n/** Error for browsers that do not support permission queries. */\nexport const couldNotQueryPermissionStatusError = () => new Error('COULD_NOT_QUERY_PERMISSION_STATUS');\n//# sourceMappingURL=predefined-web-responses.js.map","import { Filesystem } from '@capacitor/filesystem';\nimport write_blob from 'capacitor-blob-writer';\nimport getBlobDuration from './get-blob-duration';\nimport { alreadyRecordingError, couldNotQueryPermissionStatusError, deviceCannotVoiceRecordError, emptyRecordingError, failedToFetchRecordingError, failedToRecordError, failureResponse, missingPermissionError, recordingHasNotStartedError, successResponse, } from './predefined-web-responses';\n/**\n * Ordered MIME types to probe for audio recording via `MediaRecorder.isTypeSupported()`.\n *\n * ⚠️ The order is intentional and MUST remain stable unless you also update the\n * selection policy in code and test on Safari/iOS + WebViews.\n *\n * ✅ What this list is used for\n * - Selecting a `mimeType` for `new MediaRecorder(stream, { mimeType })`.\n *\n * ❌ What this list does NOT guarantee\n * - It does NOT guarantee that the recorded output will be playable via the\n * HTML `<audio>` element in the same browser.\n *\n * Real-world caveat (important):\n * - We have observed cases where `MediaRecorder.isTypeSupported('audio/webm;codecs=opus')`\n * returned `true`, the recorder produced a Blob, but `<audio>` could not play it.\n * This can happen due to container/codec playback support differences, platform\n * quirks (especially Safari/iOS / WKWebView), or incomplete WebM playback support.\n *\n * Current selection behavior in this implementation:\n * - By default, MIME selection treats recorder support and playback support as separate\n * capabilities and probes both:\n * - Recorder capability: `MediaRecorder.isTypeSupported(type)`\n * - Playback capability: `audio.canPlayType(type)`\n * - This default can be disabled via `RecordingOptions.requirePlaybackSupport = false`\n * to fall back to recorder-only probing.\n *\n * Keeping legacy keys:\n * - Some entries are kept even if they overlap (e.g. `audio/mp4` and explicit codec),\n * to maximize compatibility across differing browser implementations.\n */\nconst POSSIBLE_MIME_TYPES = {\n // ✅ Most universal\n 'audio/mp4;codecs=\"mp4a.40.2\"': '.m4a', // AAC in MP4 (explicit codec helps detection)\n 'audio/mp4': '.m4a', // (legacy key kept; broad support)\n 'audio/aac': '.aac', // (legacy key kept; less common in the wild)\n 'audio/mpeg': '.mp3', // MP3 (universal)\n 'audio/wav': '.wav', // WAV (universal, big files)\n // ✅ Modern high-quality (very widely supported, but slightly less “universal” than MP3/AAC)\n 'audio/webm;codecs=\"opus\"': '.webm', // Opus in WebM (explicit codec helps detection)\n 'audio/webm;codecs=opus': '.webm', // (legacy key kept)\n 'audio/webm': '.webm', // (legacy key kept; container-only, codec-dependent)\n // ⚠️ Least universal (Safari/iOS historically the limiting factor)\n 'audio/ogg;codecs=opus': '.ogg', // (legacy key kept)\n 'audio/ogg;codecs=vorbis': '.ogg', // Ogg Vorbis (weakest mainstream support)\n};\n/** Creates a promise that never resolves. */\nconst neverResolvingPromise = () => new Promise(() => undefined);\n/** Browser implementation backed by MediaRecorder and Capacitor Filesystem. */\nexport class VoiceRecorderImpl {\n constructor() {\n /** Active MediaRecorder instance, if recording. */\n this.mediaRecorder = null;\n /** Collected data chunks from MediaRecorder. */\n this.chunks = [];\n /** Promise resolved when the recorder stops and payload is ready. */\n this.pendingResult = neverResolvingPromise();\n }\n /**\n * Returns whether the browser can start a recording session.\n *\n * On web this checks:\n * - `navigator.mediaDevices.getUserMedia`\n * - at least one supported recording MIME type using {@link getSupportedMimeType}\n *\n * The optional `requirePlaybackSupport` flag is forwarded to MIME selection and defaults\n * to `true` when omitted.\n */\n static async canDeviceVoiceRecord(options) {\n var _a;\n if (((_a = navigator === null || navigator === void 0 ? void 0 : navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.getUserMedia) == null ||\n VoiceRecorderImpl.getSupportedMimeType({\n requirePlaybackSupport: options === null || options === void 0 ? void 0 : options.requirePlaybackSupport,\n }) == null) {\n return failureResponse();\n }\n else {\n return successResponse();\n }\n }\n /**\n * Starts a recording session using `MediaRecorder`.\n *\n * The selected MIME type is resolved once at start time (using the optional\n * `requirePlaybackSupport` flag from `RecordingOptions`) and reused for the final Blob\n * and file extension to keep the recording payload internally consistent.\n */\n async startRecording(options) {\n if (this.mediaRecorder != null) {\n throw alreadyRecordingError();\n }\n const deviceCanRecord = await VoiceRecorderImpl.canDeviceVoiceRecord(options);\n if (!deviceCanRecord.value) {\n throw deviceCannotVoiceRecordError();\n }\n const havingPermission = await VoiceRecorderImpl.hasAudioRecordingPermission().catch(() => successResponse());\n if (!havingPermission.value) {\n throw missingPermissionError();\n }\n return navigator.mediaDevices\n .getUserMedia({ audio: true })\n .then((stream) => this.onSuccessfullyStartedRecording(stream, options))\n .catch(this.onFailedToStartRecording.bind(this));\n }\n /** Stops the current recording and resolves the pending payload. */\n async stopRecording() {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n }\n try {\n this.mediaRecorder.stop();\n this.mediaRecorder.stream.getTracks().forEach((track) => track.stop());\n return this.pendingResult;\n }\n catch (ignore) {\n throw failedToFetchRecordingError();\n }\n finally {\n this.prepareInstanceForNextOperation();\n }\n }\n /** Returns whether the browser has microphone permission. */\n static async hasAudioRecordingPermission() {\n // Safari does not support navigator.permissions.query\n if (!navigator.permissions.query) {\n if (navigator.mediaDevices !== undefined) {\n return navigator.mediaDevices\n .getUserMedia({ audio: true })\n .then(() => successResponse())\n .catch(() => {\n throw couldNotQueryPermissionStatusError();\n });\n }\n }\n return navigator.permissions\n .query({ name: 'microphone' })\n .then((result) => ({ value: result.state === 'granted' }))\n .catch(() => {\n throw couldNotQueryPermissionStatusError();\n });\n }\n /** Requests microphone permission from the browser. */\n static async requestAudioRecordingPermission() {\n const havingPermission = await VoiceRecorderImpl.hasAudioRecordingPermission().catch(() => failureResponse());\n if (havingPermission.value) {\n return successResponse();\n }\n return navigator.mediaDevices\n .getUserMedia({ audio: true })\n .then(() => successResponse())\n .catch(() => failureResponse());\n }\n /** Pauses the recording session when supported. */\n pauseRecording() {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n }\n else if (this.mediaRecorder.state === 'recording') {\n this.mediaRecorder.pause();\n return Promise.resolve(successResponse());\n }\n else {\n return Promise.resolve(failureResponse());\n }\n }\n /** Resumes a paused recording session when supported. */\n resumeRecording() {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n }\n else if (this.mediaRecorder.state === 'paused') {\n this.mediaRecorder.resume();\n return Promise.resolve(successResponse());\n }\n else {\n return Promise.resolve(failureResponse());\n }\n }\n /** Returns the current recording status from MediaRecorder. */\n getCurrentStatus() {\n if (this.mediaRecorder == null) {\n return Promise.resolve({ status: 'NONE' });\n }\n else if (this.mediaRecorder.state === 'recording') {\n return Promise.resolve({ status: 'RECORDING' });\n }\n else if (this.mediaRecorder.state === 'paused') {\n return Promise.resolve({ status: 'PAUSED' });\n }\n else {\n return Promise.resolve({ status: 'NONE' });\n }\n }\n /**\n * Returns the first MIME type (key of {@link POSSIBLE_MIME_TYPES}) that the current\n * environment reports as supported for recording via `MediaRecorder.isTypeSupported()`,\n * optionally requiring native HTML `<audio>` playback support too.\n *\n * The search order is the iteration order of {@link POSSIBLE_MIME_TYPES}.\n *\n * @typeParam T - A MIME type string that exists as a key in {@link POSSIBLE_MIME_TYPES}.\n *\n * @returns The first supported MIME type for `MediaRecorder`, or `null` if:\n * - `MediaRecorder` is unavailable, or\n * - no configured MIME types are supported.\n *\n * ⚠️ Important: `MediaRecorder` support ≠ `<audio>` playback support\n *\n * Some browsers/platforms can claim support for recording a format (notably WebM/Opus)\n * but still fail to play the resulting Blob through the native HTML audio pipeline.\n * This mismatch is especially likely on Safari/iOS / WKWebView variants, so the default\n * behavior also probes `HTMLAudioElement.canPlayType(type)` when available.\n *\n * Selection policy when playback probing is enabled:\n * - keep the global priority order from {@link POSSIBLE_MIME_TYPES}\n * - among recordable types, prefer the first `\"probably\"` playable candidate\n * - otherwise return the first `\"maybe\"` playable candidate\n * - treat `\"\"` as not playable\n *\n * Note: The <audio> element is never attached to the DOM, so it won't appear to users or assistive tech.\n *\n * Fallback behavior:\n * - If `document` / `audio.canPlayType` is unavailable (e.g. SSR-like environments),\n * this falls back to record-only probing.\n */\n static getSupportedMimeType(options) {\n var _a, _b, _c, _d, _e;\n if ((MediaRecorder === null || MediaRecorder === void 0 ? void 0 : MediaRecorder.isTypeSupported) == null)\n return null;\n const orderedTypes = Object.keys(POSSIBLE_MIME_TYPES);\n const recordSupportedTypes = orderedTypes.filter((type) => MediaRecorder.isTypeSupported(type));\n if (recordSupportedTypes.length === 0)\n return null;\n const requirePlaybackSupport = (_a = options === null || options === void 0 ? void 0 : options.requirePlaybackSupport) !== null && _a !== void 0 ? _a : VoiceRecorderImpl.DEFAULT_REQUIRE_PLAYBACK_SUPPORT;\n if (!requirePlaybackSupport) {\n return (_b = recordSupportedTypes[0]) !== null && _b !== void 0 ? _b : null;\n }\n if (typeof document === 'undefined' || typeof document.createElement !== 'function') {\n return (_c = recordSupportedTypes[0]) !== null && _c !== void 0 ? _c : null;\n }\n const audioElement = document.createElement('audio');\n if (typeof audioElement.canPlayType !== 'function') {\n return (_d = recordSupportedTypes[0]) !== null && _d !== void 0 ? _d : null;\n }\n let firstProbably = null;\n let firstMaybe = null;\n for (const type of recordSupportedTypes) {\n const playbackSupport = audioElement.canPlayType(type);\n if (playbackSupport === 'probably') {\n firstProbably = type;\n break;\n }\n if (playbackSupport === 'maybe' && firstMaybe == null) {\n firstMaybe = type;\n }\n }\n return (_e = firstProbably !== null && firstProbably !== void 0 ? firstProbably : firstMaybe) !== null && _e !== void 0 ? _e : null;\n }\n /** Initializes MediaRecorder and wires up handlers. */\n onSuccessfullyStartedRecording(stream, options) {\n this.pendingResult = new Promise((resolve, reject) => {\n const mimeType = VoiceRecorderImpl.getSupportedMimeType({\n requirePlaybackSupport: options === null || options === void 0 ? void 0 : options.requirePlaybackSupport,\n });\n if (mimeType == null) {\n this.prepareInstanceForNextOperation();\n reject(failedToRecordError());\n return;\n }\n this.mediaRecorder = new MediaRecorder(stream, { mimeType });\n this.mediaRecorder.onerror = () => {\n this.prepareInstanceForNextOperation();\n reject(failedToRecordError());\n };\n this.mediaRecorder.onstop = async () => {\n var _a, _b, _c, _d, _e;\n const mt = (_b = (_a = this.mediaRecorder) === null || _a === void 0 ? void 0 : _a.mimeType) !== null && _b !== void 0 ? _b : mimeType;\n const blobVoiceRecording = new Blob(this.chunks, { type: mt });\n if (blobVoiceRecording.size <= 0) {\n this.prepareInstanceForNextOperation();\n reject(emptyRecordingError());\n return;\n }\n let uri = undefined;\n let recordDataBase64 = '';\n if (options === null || options === void 0 ? void 0 : options.directory) {\n const subDirectory = (_e = (_d = (_c = options.subDirectory) === null || _c === void 0 ? void 0 : _c.match(/^\\/?(.+[^/])\\/?$/)) === null || _d === void 0 ? void 0 : _d[1]) !== null && _e !== void 0 ? _e : '';\n const path = `${subDirectory}/recording-${new Date().getTime()}${POSSIBLE_MIME_TYPES[mt]}`;\n await write_blob({\n blob: blobVoiceRecording,\n directory: options.directory,\n fast_mode: true,\n path,\n recursive: true,\n });\n ({ uri } = await Filesystem.getUri({ directory: options.directory, path }));\n }\n else {\n recordDataBase64 = await VoiceRecorderImpl.blobToBase64(blobVoiceRecording);\n }\n const recordingDuration = await getBlobDuration(blobVoiceRecording);\n this.prepareInstanceForNextOperation();\n resolve({\n value: {\n recordDataBase64,\n mimeType: mt,\n msDuration: recordingDuration * 1000,\n uri\n }\n });\n };\n this.mediaRecorder.ondataavailable = (event) => this.chunks.push(event.data);\n this.mediaRecorder.start();\n });\n return successResponse();\n }\n /** Handles failures from getUserMedia. */\n onFailedToStartRecording() {\n this.prepareInstanceForNextOperation();\n throw failedToRecordError();\n }\n /** Converts a Blob payload into a base64 string. */\n static blobToBase64(blob) {\n return new Promise((resolve) => {\n const reader = new FileReader();\n reader.onloadend = () => {\n const recordingResult = String(reader.result);\n const splitResult = recordingResult.split('base64,');\n const toResolve = splitResult.length > 1 ? splitResult[1] : recordingResult;\n resolve(toResolve.trim());\n };\n reader.readAsDataURL(blob);\n });\n }\n /** Resets state for the next recording attempt. */\n prepareInstanceForNextOperation() {\n if (this.mediaRecorder != null && this.mediaRecorder.state === 'recording') {\n try {\n this.mediaRecorder.stop();\n }\n catch (ignore) {\n console.warn('Failed to stop recording during cleanup');\n }\n }\n this.pendingResult = neverResolvingPromise();\n this.mediaRecorder = null;\n this.chunks = [];\n }\n}\n/** Default behavior for web MIME selection: require recorder + playback support. */\nVoiceRecorderImpl.DEFAULT_REQUIRE_PLAYBACK_SUPPORT = true;\n//# sourceMappingURL=VoiceRecorderImpl.js.map","import { VoiceRecorderImpl } from '../platform/web/VoiceRecorderImpl';\n/** Web adapter that delegates to the browser-specific implementation. */\nexport class VoiceRecorderWebAdapter {\n constructor() {\n /** Browser implementation that talks to MediaRecorder APIs. */\n this.voiceRecorderImpl = new VoiceRecorderImpl();\n }\n /** Checks whether the browser can record audio. */\n canDeviceVoiceRecord() {\n return VoiceRecorderImpl.canDeviceVoiceRecord();\n }\n /** Returns whether the browser has microphone permission. */\n hasAudioRecordingPermission() {\n return VoiceRecorderImpl.hasAudioRecordingPermission();\n }\n /** Requests microphone permission through the browser. */\n requestAudioRecordingPermission() {\n return VoiceRecorderImpl.requestAudioRecordingPermission();\n }\n /** Starts a recording session using MediaRecorder. */\n startRecording(options) {\n return this.voiceRecorderImpl.startRecording(options);\n }\n /** Stops the recording session and returns the payload. */\n stopRecording() {\n return this.voiceRecorderImpl.stopRecording();\n }\n /** Pauses the recording session when supported. */\n pauseRecording() {\n return this.voiceRecorderImpl.pauseRecording();\n }\n /** Resumes a paused recording session when supported. */\n resumeRecording() {\n return this.voiceRecorderImpl.resumeRecording();\n }\n /** Returns the current recording state. */\n getCurrentStatus() {\n return this.voiceRecorderImpl.getCurrentStatus();\n }\n}\n//# sourceMappingURL=VoiceRecorderWebAdapter.js.map","/** Default response shape when no config is provided. */\nexport const DEFAULT_RESPONSE_FORMAT = 'legacy';\n/** Parses a user-provided response format into a supported value. */\nexport const resolveResponseFormat = (value) => {\n if (typeof value === 'string' && value.toLowerCase() === 'normalized') {\n return 'normalized';\n }\n return DEFAULT_RESPONSE_FORMAT;\n};\n/** Reads the response format from a Capacitor plugin config object. */\nexport const getResponseFormatFromConfig = (config) => {\n if (config && typeof config === 'object' && 'responseFormat' in config) {\n return resolveResponseFormat(config.responseFormat);\n }\n return DEFAULT_RESPONSE_FORMAT;\n};\n//# sourceMappingURL=response-format.js.map","/** Maps legacy error messages to canonical error codes. */\nconst legacyToCanonical = {\n CANNOT_RECORD_ON_THIS_PHONE: 'DEVICE_CANNOT_VOICE_RECORD',\n};\n/** Normalizes legacy error messages into canonical error codes. */\nexport const toCanonicalErrorCode = (legacyMessage) => {\n var _a;\n return (_a = legacyToCanonical[legacyMessage]) !== null && _a !== void 0 ? _a : legacyMessage;\n};\n/** Adds a canonical `code` field to Error-like objects when possible. */\nexport const attachCanonicalErrorCode = (error) => {\n if (!error || typeof error !== 'object') {\n return;\n }\n const messageValue = error.message;\n if (typeof messageValue !== 'string') {\n return;\n }\n error.code = toCanonicalErrorCode(messageValue);\n};\n//# sourceMappingURL=error-codes.js.map","/** Normalizes recording payloads into a stable contract shape. */\nexport const normalizeRecordingData = (data) => {\n const { recordDataBase64, uri, msDuration, mimeType } = data.value;\n const normalizedValue = { msDuration, mimeType };\n const trimmedUri = typeof uri === 'string' && uri.length > 0 ? uri : undefined;\n const trimmedBase64 = typeof recordDataBase64 === 'string' && recordDataBase64.length > 0 ? recordDataBase64 : undefined;\n if (trimmedUri) {\n normalizedValue.uri = trimmedUri;\n }\n else if (trimmedBase64) {\n normalizedValue.recordDataBase64 = trimmedBase64;\n }\n return { value: normalizedValue };\n};\n//# sourceMappingURL=recording-contract.js.map","import { attachCanonicalErrorCode } from '../core/error-codes';\nimport { normalizeRecordingData } from '../core/recording-contract';\n/** Orchestrates platform calls and normalizes responses when requested. */\nexport class VoiceRecorderService {\n constructor(platform, responseFormat) {\n this.platform = platform;\n this.responseFormat = responseFormat;\n }\n /** Checks whether the device can record audio. */\n canDeviceVoiceRecord() {\n return this.execute(() => this.platform.canDeviceVoiceRecord());\n }\n /** Returns whether microphone permission is currently granted. */\n hasAudioRecordingPermission() {\n return this.execute(() => this.platform.hasAudioRecordingPermission());\n }\n /** Requests microphone permission from the user. */\n requestAudioRecordingPermission() {\n return this.execute(() => this.platform.requestAudioRecordingPermission());\n }\n /** Starts a recording session. */\n startRecording(options) {\n return this.execute(() => this.platform.startRecording(options));\n }\n /** Stops the recording session and formats the payload if needed. */\n async stopRecording() {\n return this.execute(async () => {\n const data = await this.platform.stopRecording();\n if (this.responseFormat === 'normalized') {\n return normalizeRecordingData(data);\n }\n return data;\n });\n }\n /** Pauses the recording session when supported. */\n pauseRecording() {\n return this.execute(() => this.platform.pauseRecording());\n }\n /** Resumes a paused recording session when supported. */\n resumeRecording() {\n return this.execute(() => this.platform.resumeRecording());\n }\n /** Returns the current recording state. */\n getCurrentStatus() {\n return this.execute(() => this.platform.getCurrentStatus());\n }\n /** Wraps calls to apply canonical error codes when requested. */\n async execute(fn) {\n try {\n return await fn();\n }\n catch (error) {\n if (this.responseFormat === 'normalized') {\n attachCanonicalErrorCode(error);\n }\n throw error;\n }\n }\n}\n//# sourceMappingURL=VoiceRecorderService.js.map","import { Capacitor, WebPlugin } from '@capacitor/core';\nimport { VoiceRecorderWebAdapter } from './adapters/VoiceRecorderWebAdapter';\nimport { getResponseFormatFromConfig } from './core/response-format';\nimport { VoiceRecorderService } from './service/VoiceRecorderService';\n/** Web implementation of the VoiceRecorder Capacitor plugin. */\nexport class VoiceRecorderWeb extends WebPlugin {\n constructor() {\n var _a, _b;\n super();\n const pluginConfig = (_b = (_a = Capacitor === null || Capacitor === void 0 ? void 0 : Capacitor.config) === null || _a === void 0 ? void 0 : _a.plugins) === null || _b === void 0 ? void 0 : _b.VoiceRecorder;\n const responseFormat = getResponseFormatFromConfig(pluginConfig);\n this.service = new VoiceRecorderService(new VoiceRecorderWebAdapter(), responseFormat);\n }\n /** Checks whether the browser can record audio. */\n canDeviceVoiceRecord() {\n return this.service.canDeviceVoiceRecord();\n }\n /** Returns whether microphone permission is currently granted. */\n hasAudioRecordingPermission() {\n return this.service.hasAudioRecordingPermission();\n }\n /** Requests microphone permission from the user. */\n requestAudioRecordingPermission() {\n return this.service.requestAudioRecordingPermission();\n }\n /** Starts a recording session. */\n startRecording(options) {\n return this.service.startRecording(options);\n }\n /** Stops the current recording session and returns the payload. */\n stopRecording() {\n return this.service.stopRecording();\n }\n /** Pauses the recording session when supported. */\n pauseRecording() {\n return this.service.pauseRecording();\n }\n /** Resumes a paused recording session when supported. */\n resumeRecording() {\n return this.service.resumeRecording();\n }\n /** Returns the current recording state. */\n getCurrentStatus() {\n return this.service.getCurrentStatus();\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","Filesystem","WebPlugin","Capacitor"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/platform/web/get-blob-duration.js","esm/platform/web/predefined-web-responses.js","esm/platform/web/VoiceRecorderImpl.js","esm/adapters/VoiceRecorderWebAdapter.js","esm/core/response-format.js","esm/core/error-codes.js","esm/core/recording-contract.js","esm/service/VoiceRecorderService.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst VoiceRecorder = registerPlugin('VoiceRecorder', {\n web: () => import('./web').then((m) => new m.VoiceRecorderWeb()),\n});\nexport * from './definitions';\nexport { VoiceRecorder };\n//# sourceMappingURL=index.js.map","/**\n * @param {Blob | string} blob\n * @returns {Promise<number>} Blob duration in seconds.\n */\nexport default async function getBlobDuration(blob) {\n // Check for AudioContext or webkitAudioContext (Safari)\n const AudioCtx = window.AudioContext || window.webkitAudioContext;\n if (!AudioCtx) {\n throw new Error('AudioContext is not supported in this environment.');\n }\n let audioContext = null;\n try {\n audioContext = new AudioCtx();\n let arrayBuffer;\n if (typeof blob === 'string') {\n arrayBuffer = base64ToArrayBuffer(blob);\n }\n else {\n arrayBuffer = await blob.arrayBuffer();\n }\n const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);\n return audioBuffer.duration;\n }\n catch (err) {\n throw new Error('Failed to get audio duration (AudioContext may require user interaction or is not supported): ' + (err instanceof Error ? err.message : String(err)));\n }\n finally {\n if (audioContext) {\n await audioContext.close();\n }\n }\n}\n/**\n * Convert base64 string to ArrayBuffer.\n * @param base64 The base64 string to convert.\n * @returns The converted ArrayBuffer.\n * @remarks This function is exported for test coverage purposes.\n */\nexport function base64ToArrayBuffer(base64) {\n const cleanBase64 = base64.replace(/^data:[^;]+;base64,/, '');\n const binaryString = atob(cleanBase64);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n}\n//# sourceMappingURL=get-blob-duration.js.map","/** Success wrapper for boolean plugin responses. */\nexport const successResponse = () => ({ value: true });\n/** Failure wrapper for boolean plugin responses. */\nexport const failureResponse = () => ({ value: false });\n/** Error for missing microphone permission. */\nexport const missingPermissionError = () => new Error('MISSING_PERMISSION');\n/** Error for attempting to start while already recording. */\nexport const alreadyRecordingError = () => new Error('ALREADY_RECORDING');\n/** Error for microphone in use by another app or recorder. */\nexport const microphoneBeingUsedError = () => new Error('MICROPHONE_BEING_USED');\n/** Error for devices that cannot record audio. */\nexport const deviceCannotVoiceRecordError = () => new Error('DEVICE_CANNOT_VOICE_RECORD');\n/** Error for recorder start failures. */\nexport const failedToRecordError = () => new Error('FAILED_TO_RECORD');\n/** Error for empty or zero-length recordings. */\nexport const emptyRecordingError = () => new Error('EMPTY_RECORDING');\n/** Error for stopping without an active recording. */\nexport const recordingHasNotStartedError = () => new Error('RECORDING_HAS_NOT_STARTED');\n/** Error for failures when fetching recording data. */\nexport const failedToFetchRecordingError = () => new Error('FAILED_TO_FETCH_RECORDING');\n/** Error for browsers that do not support permission queries. */\nexport const couldNotQueryPermissionStatusError = () => new Error('COULD_NOT_QUERY_PERMISSION_STATUS');\n//# sourceMappingURL=predefined-web-responses.js.map","import { Filesystem } from '@capacitor/filesystem';\nimport write_blob from 'capacitor-blob-writer';\nimport getBlobDuration from './get-blob-duration';\nimport { alreadyRecordingError, couldNotQueryPermissionStatusError, deviceCannotVoiceRecordError, emptyRecordingError, failedToFetchRecordingError, failedToRecordError, failureResponse, missingPermissionError, recordingHasNotStartedError, successResponse, } from './predefined-web-responses';\n/**\n * Ordered MIME types to probe for audio recording via `MediaRecorder.isTypeSupported()`.\n *\n * ⚠️ The order is intentional and MUST remain stable unless you also update the\n * selection policy in code and test on Safari/iOS + WebViews.\n *\n * ✅ What this list is used for\n * - Selecting a `mimeType` for `new MediaRecorder(stream, { mimeType })`.\n *\n * ❌ What this list does NOT guarantee\n * - It does NOT guarantee that the recorded output will be playable via the\n * HTML `<audio>` element in the same browser.\n *\n * Real-world caveat (important):\n * - We have observed cases where `MediaRecorder.isTypeSupported('audio/webm;codecs=opus')`\n * returned `true`, the recorder produced a Blob, but `<audio>` could not play it.\n * This can happen due to container/codec playback support differences, platform\n * quirks (especially Safari/iOS / WKWebView), or incomplete WebM playback support.\n *\n * Current selection behavior in this implementation:\n * - By default, MIME selection treats recorder support and playback support as separate\n * capabilities and probes both:\n * - Recorder capability: `MediaRecorder.isTypeSupported(type)`\n * - Playback capability: `audio.canPlayType(type)`\n * - This default can be disabled via `RecordingOptions.requirePlaybackSupport = false`\n * to fall back to recorder-only probing.\n *\n * Keeping legacy keys:\n * - Some entries are kept even if they overlap (e.g. `audio/mp4` and explicit codec),\n * to maximize compatibility across differing browser implementations.\n */\nconst POSSIBLE_MIME_TYPES = {\n // ✅ Most universal\n 'audio/mp4;codecs=\"mp4a.40.2\"': '.m4a', // AAC in MP4 (explicit codec helps detection)\n 'audio/mp4': '.m4a', // (legacy key kept; broad support)\n 'audio/aac': '.aac', // (legacy key kept; less common in the wild)\n 'audio/mpeg': '.mp3', // MP3 (universal)\n 'audio/wav': '.wav', // WAV (universal, big files)\n // ✅ Modern high-quality (very widely supported, but slightly less “universal” than MP3/AAC)\n 'audio/webm;codecs=\"opus\"': '.webm', // Opus in WebM (explicit codec helps detection)\n 'audio/webm;codecs=opus': '.webm', // (legacy key kept)\n 'audio/webm': '.webm', // (legacy key kept; container-only, codec-dependent)\n // ⚠️ Least universal (Safari/iOS historically the limiting factor)\n 'audio/ogg;codecs=opus': '.ogg', // (legacy key kept)\n 'audio/ogg;codecs=vorbis': '.ogg', // Ogg Vorbis (weakest mainstream support)\n};\n/** Creates a promise that never resolves. */\nconst neverResolvingPromise = () => new Promise(() => undefined);\n/** Browser implementation backed by MediaRecorder and Capacitor Filesystem. */\nexport class VoiceRecorderImpl {\n constructor() {\n /** Active MediaRecorder instance, if recording. */\n this.mediaRecorder = null;\n /** Collected data chunks from MediaRecorder. */\n this.chunks = [];\n /** Promise resolved when the recorder stops and payload is ready. */\n this.pendingResult = neverResolvingPromise();\n }\n /**\n * Returns whether the browser can start a recording session.\n *\n * On web this checks:\n * - `navigator.mediaDevices.getUserMedia`\n * - at least one supported recording MIME type using {@link getSupportedMimeType}\n *\n * The optional `requirePlaybackSupport` flag is forwarded to MIME selection and defaults\n * to `true` when omitted.\n */\n static async canDeviceVoiceRecord(options) {\n var _a;\n if (((_a = navigator === null || navigator === void 0 ? void 0 : navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.getUserMedia) == null ||\n VoiceRecorderImpl.getSupportedMimeType({\n requirePlaybackSupport: options === null || options === void 0 ? void 0 : options.requirePlaybackSupport,\n }) == null) {\n return failureResponse();\n }\n else {\n return successResponse();\n }\n }\n /**\n * Starts a recording session using `MediaRecorder`.\n *\n * The selected MIME type is resolved once at start time (using the optional\n * `requirePlaybackSupport` flag from `RecordingOptions`) and reused for the final Blob\n * and file extension to keep the recording payload internally consistent.\n */\n async startRecording(options) {\n if (this.mediaRecorder != null) {\n throw alreadyRecordingError();\n }\n const deviceCanRecord = await VoiceRecorderImpl.canDeviceVoiceRecord(options);\n if (!deviceCanRecord.value) {\n throw deviceCannotVoiceRecordError();\n }\n const havingPermission = await VoiceRecorderImpl.hasAudioRecordingPermission().catch(() => successResponse());\n if (!havingPermission.value) {\n throw missingPermissionError();\n }\n return navigator.mediaDevices\n .getUserMedia({ audio: true })\n .then((stream) => this.onSuccessfullyStartedRecording(stream, options))\n .catch(this.onFailedToStartRecording.bind(this));\n }\n /** Stops the current recording and resolves the pending payload. */\n async stopRecording() {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n }\n try {\n this.mediaRecorder.stop();\n this.mediaRecorder.stream.getTracks().forEach((track) => track.stop());\n return this.pendingResult;\n }\n catch (ignore) {\n throw failedToFetchRecordingError();\n }\n finally {\n this.prepareInstanceForNextOperation();\n }\n }\n /** Returns whether the browser has microphone permission. */\n static async hasAudioRecordingPermission() {\n // Safari does not support navigator.permissions.query\n if (!navigator.permissions.query) {\n if (navigator.mediaDevices !== undefined) {\n return navigator.mediaDevices\n .getUserMedia({ audio: true })\n .then(() => successResponse())\n .catch(() => {\n throw couldNotQueryPermissionStatusError();\n });\n }\n }\n return navigator.permissions\n .query({ name: 'microphone' })\n .then((result) => ({ value: result.state === 'granted' }))\n .catch(() => {\n throw couldNotQueryPermissionStatusError();\n });\n }\n /** Requests microphone permission from the browser. */\n static async requestAudioRecordingPermission() {\n const havingPermission = await VoiceRecorderImpl.hasAudioRecordingPermission().catch(() => failureResponse());\n if (havingPermission.value) {\n return successResponse();\n }\n return navigator.mediaDevices\n .getUserMedia({ audio: true })\n .then(() => successResponse())\n .catch(() => failureResponse());\n }\n /** Pauses the recording session when supported. */\n pauseRecording() {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n }\n else if (this.mediaRecorder.state === 'recording') {\n this.mediaRecorder.pause();\n return Promise.resolve(successResponse());\n }\n else {\n return Promise.resolve(failureResponse());\n }\n }\n /** Resumes a paused recording session when supported. */\n resumeRecording() {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n }\n else if (this.mediaRecorder.state === 'paused') {\n this.mediaRecorder.resume();\n return Promise.resolve(successResponse());\n }\n else {\n return Promise.resolve(failureResponse());\n }\n }\n /** Returns the current recording status from MediaRecorder. */\n getCurrentStatus() {\n if (this.mediaRecorder == null) {\n return Promise.resolve({ status: 'NONE' });\n }\n else if (this.mediaRecorder.state === 'recording') {\n return Promise.resolve({ status: 'RECORDING' });\n }\n else if (this.mediaRecorder.state === 'paused') {\n return Promise.resolve({ status: 'PAUSED' });\n }\n else {\n return Promise.resolve({ status: 'NONE' });\n }\n }\n /**\n * Returns the first MIME type (key of {@link POSSIBLE_MIME_TYPES}) that the current\n * environment reports as supported for recording via `MediaRecorder.isTypeSupported()`,\n * optionally requiring native HTML `<audio>` playback support too.\n *\n * The search order is the iteration order of {@link POSSIBLE_MIME_TYPES}.\n *\n * @typeParam T - A MIME type string that exists as a key in {@link POSSIBLE_MIME_TYPES}.\n *\n * @returns The first supported MIME type for `MediaRecorder`, or `null` if:\n * - `MediaRecorder` is unavailable, or\n * - no configured MIME types are supported.\n *\n * ⚠️ Important: `MediaRecorder` support ≠ `<audio>` playback support\n *\n * Some browsers/platforms can claim support for recording a format (notably WebM/Opus)\n * but still fail to play the resulting Blob through the native HTML audio pipeline.\n * This mismatch is especially likely on Safari/iOS / WKWebView variants, so the default\n * behavior also probes `HTMLAudioElement.canPlayType(type)` when available.\n *\n * Selection policy when playback probing is enabled:\n * - keep the global priority order from {@link POSSIBLE_MIME_TYPES}\n * - among recordable types, prefer the first `\"probably\"` playable candidate\n * - otherwise return the first `\"maybe\"` playable candidate\n * - treat `\"\"` as not playable\n *\n * Note: The <audio> element is never attached to the DOM, so it won't appear to users or assistive tech.\n *\n * Fallback behavior:\n * - If `document` / `audio.canPlayType` is unavailable (e.g. SSR-like environments),\n * this falls back to record-only probing.\n */\n static getSupportedMimeType(options) {\n var _a, _b, _c, _d, _e;\n if ((MediaRecorder === null || MediaRecorder === void 0 ? void 0 : MediaRecorder.isTypeSupported) == null)\n return null;\n const orderedTypes = Object.keys(POSSIBLE_MIME_TYPES);\n const recordSupportedTypes = orderedTypes.filter((type) => MediaRecorder.isTypeSupported(type));\n if (recordSupportedTypes.length === 0)\n return null;\n const requirePlaybackSupport = (_a = options === null || options === void 0 ? void 0 : options.requirePlaybackSupport) !== null && _a !== void 0 ? _a : VoiceRecorderImpl.DEFAULT_REQUIRE_PLAYBACK_SUPPORT;\n if (!requirePlaybackSupport) {\n return (_b = recordSupportedTypes[0]) !== null && _b !== void 0 ? _b : null;\n }\n if (typeof document === 'undefined' || typeof document.createElement !== 'function') {\n return (_c = recordSupportedTypes[0]) !== null && _c !== void 0 ? _c : null;\n }\n const audioElement = document.createElement('audio');\n if (typeof audioElement.canPlayType !== 'function') {\n return (_d = recordSupportedTypes[0]) !== null && _d !== void 0 ? _d : null;\n }\n let firstProbably = null;\n let firstMaybe = null;\n for (const type of recordSupportedTypes) {\n const playbackSupport = audioElement.canPlayType(type);\n if (playbackSupport === 'probably') {\n firstProbably = type;\n break;\n }\n if (playbackSupport === 'maybe' && firstMaybe == null) {\n firstMaybe = type;\n }\n }\n return (_e = firstProbably !== null && firstProbably !== void 0 ? firstProbably : firstMaybe) !== null && _e !== void 0 ? _e : null;\n }\n /** Initializes MediaRecorder and wires up handlers. */\n onSuccessfullyStartedRecording(stream, options) {\n this.pendingResult = new Promise((resolve, reject) => {\n const mimeType = VoiceRecorderImpl.getSupportedMimeType({\n requirePlaybackSupport: options === null || options === void 0 ? void 0 : options.requirePlaybackSupport,\n });\n if (mimeType == null) {\n this.prepareInstanceForNextOperation();\n reject(failedToRecordError());\n return;\n }\n this.mediaRecorder = new MediaRecorder(stream, { mimeType });\n this.mediaRecorder.onerror = () => {\n this.prepareInstanceForNextOperation();\n reject(failedToRecordError());\n };\n this.mediaRecorder.onstop = async () => {\n var _a, _b, _c, _d, _e, _f;\n const mt = (_b = (_a = this.mediaRecorder) === null || _a === void 0 ? void 0 : _a.mimeType) !== null && _b !== void 0 ? _b : mimeType;\n const blobVoiceRecording = new Blob(this.chunks, { type: mt });\n if (blobVoiceRecording.size <= 0) {\n this.prepareInstanceForNextOperation();\n reject(emptyRecordingError());\n return;\n }\n let uri = undefined;\n let recordDataBase64 = '';\n const fileExtension = ((_c = POSSIBLE_MIME_TYPES[mimeType]) !== null && _c !== void 0 ? _c : '').replace(/^\\./, '');\n if (options === null || options === void 0 ? void 0 : options.directory) {\n const subDirectory = (_f = (_e = (_d = options.subDirectory) === null || _d === void 0 ? void 0 : _d.match(/^\\/?(.+[^/])\\/?$/)) === null || _e === void 0 ? void 0 : _e[1]) !== null && _f !== void 0 ? _f : '';\n const path = `${subDirectory}/recording-${new Date().getTime()}${POSSIBLE_MIME_TYPES[mt]}`;\n await write_blob({\n blob: blobVoiceRecording,\n directory: options.directory,\n fast_mode: true,\n path,\n recursive: true,\n });\n ({ uri } = await Filesystem.getUri({ directory: options.directory, path }));\n }\n else {\n recordDataBase64 = await VoiceRecorderImpl.blobToBase64(blobVoiceRecording);\n }\n const recordingDuration = await getBlobDuration(blobVoiceRecording);\n this.prepareInstanceForNextOperation();\n resolve({\n value: {\n recordDataBase64,\n mimeType: mt,\n fileExtension,\n msDuration: recordingDuration * 1000,\n uri\n }\n });\n };\n this.mediaRecorder.ondataavailable = (event) => this.chunks.push(event.data);\n this.mediaRecorder.start();\n });\n return successResponse();\n }\n /** Handles failures from getUserMedia. */\n onFailedToStartRecording() {\n this.prepareInstanceForNextOperation();\n throw failedToRecordError();\n }\n /** Converts a Blob payload into a base64 string. */\n static blobToBase64(blob) {\n return new Promise((resolve) => {\n const reader = new FileReader();\n reader.onloadend = () => {\n const recordingResult = String(reader.result);\n const splitResult = recordingResult.split('base64,');\n const toResolve = splitResult.length > 1 ? splitResult[1] : recordingResult;\n resolve(toResolve.trim());\n };\n reader.readAsDataURL(blob);\n });\n }\n /** Resets state for the next recording attempt. */\n prepareInstanceForNextOperation() {\n if (this.mediaRecorder != null && this.mediaRecorder.state === 'recording') {\n try {\n this.mediaRecorder.stop();\n }\n catch (ignore) {\n console.warn('Failed to stop recording during cleanup');\n }\n }\n this.pendingResult = neverResolvingPromise();\n this.mediaRecorder = null;\n this.chunks = [];\n }\n}\n/** Default behavior for web MIME selection: require recorder + playback support. */\nVoiceRecorderImpl.DEFAULT_REQUIRE_PLAYBACK_SUPPORT = true;\n//# sourceMappingURL=VoiceRecorderImpl.js.map","import { VoiceRecorderImpl } from '../platform/web/VoiceRecorderImpl';\n/** Web adapter that delegates to the browser-specific implementation. */\nexport class VoiceRecorderWebAdapter {\n constructor() {\n /** Browser implementation that talks to MediaRecorder APIs. */\n this.voiceRecorderImpl = new VoiceRecorderImpl();\n }\n /** Checks whether the browser can record audio. */\n canDeviceVoiceRecord() {\n return VoiceRecorderImpl.canDeviceVoiceRecord();\n }\n /** Returns whether the browser has microphone permission. */\n hasAudioRecordingPermission() {\n return VoiceRecorderImpl.hasAudioRecordingPermission();\n }\n /** Requests microphone permission through the browser. */\n requestAudioRecordingPermission() {\n return VoiceRecorderImpl.requestAudioRecordingPermission();\n }\n /** Starts a recording session using MediaRecorder. */\n startRecording(options) {\n return this.voiceRecorderImpl.startRecording(options);\n }\n /** Stops the recording session and returns the payload. */\n stopRecording() {\n return this.voiceRecorderImpl.stopRecording();\n }\n /** Pauses the recording session when supported. */\n pauseRecording() {\n return this.voiceRecorderImpl.pauseRecording();\n }\n /** Resumes a paused recording session when supported. */\n resumeRecording() {\n return this.voiceRecorderImpl.resumeRecording();\n }\n /** Returns the current recording state. */\n getCurrentStatus() {\n return this.voiceRecorderImpl.getCurrentStatus();\n }\n}\n//# sourceMappingURL=VoiceRecorderWebAdapter.js.map","/** Default response shape when no config is provided. */\nexport const DEFAULT_RESPONSE_FORMAT = 'legacy';\n/** Parses a user-provided response format into a supported value. */\nexport const resolveResponseFormat = (value) => {\n if (typeof value === 'string' && value.toLowerCase() === 'normalized') {\n return 'normalized';\n }\n return DEFAULT_RESPONSE_FORMAT;\n};\n/** Reads the response format from a Capacitor plugin config object. */\nexport const getResponseFormatFromConfig = (config) => {\n if (config && typeof config === 'object' && 'responseFormat' in config) {\n return resolveResponseFormat(config.responseFormat);\n }\n return DEFAULT_RESPONSE_FORMAT;\n};\n//# sourceMappingURL=response-format.js.map","/** Maps legacy error messages to canonical error codes. */\nconst legacyToCanonical = {\n CANNOT_RECORD_ON_THIS_PHONE: 'DEVICE_CANNOT_VOICE_RECORD',\n};\n/** Normalizes legacy error messages into canonical error codes. */\nexport const toCanonicalErrorCode = (legacyMessage) => {\n var _a;\n return (_a = legacyToCanonical[legacyMessage]) !== null && _a !== void 0 ? _a : legacyMessage;\n};\n/** Adds a canonical `code` field to Error-like objects when possible. */\nexport const attachCanonicalErrorCode = (error) => {\n if (!error || typeof error !== 'object') {\n return;\n }\n const messageValue = error.message;\n if (typeof messageValue !== 'string') {\n return;\n }\n error.code = toCanonicalErrorCode(messageValue);\n};\n//# sourceMappingURL=error-codes.js.map","/** Normalizes recording payloads into a stable contract shape. */\nexport const normalizeRecordingData = (data) => {\n const { recordDataBase64, uri, msDuration, mimeType, fileExtension } = data.value;\n const normalizedValue = { msDuration, mimeType, fileExtension };\n const trimmedUri = typeof uri === 'string' && uri.length > 0 ? uri : undefined;\n const trimmedBase64 = typeof recordDataBase64 === 'string' && recordDataBase64.length > 0 ? recordDataBase64 : undefined;\n if (trimmedUri) {\n normalizedValue.uri = trimmedUri;\n }\n else if (trimmedBase64) {\n normalizedValue.recordDataBase64 = trimmedBase64;\n }\n return { value: normalizedValue };\n};\n//# sourceMappingURL=recording-contract.js.map","import { attachCanonicalErrorCode } from '../core/error-codes';\nimport { normalizeRecordingData } from '../core/recording-contract';\n/** Orchestrates platform calls and normalizes responses when requested. */\nexport class VoiceRecorderService {\n constructor(platform, responseFormat) {\n this.platform = platform;\n this.responseFormat = responseFormat;\n }\n /** Checks whether the device can record audio. */\n canDeviceVoiceRecord() {\n return this.execute(() => this.platform.canDeviceVoiceRecord());\n }\n /** Returns whether microphone permission is currently granted. */\n hasAudioRecordingPermission() {\n return this.execute(() => this.platform.hasAudioRecordingPermission());\n }\n /** Requests microphone permission from the user. */\n requestAudioRecordingPermission() {\n return this.execute(() => this.platform.requestAudioRecordingPermission());\n }\n /** Starts a recording session. */\n startRecording(options) {\n return this.execute(() => this.platform.startRecording(options));\n }\n /** Stops the recording session and formats the payload if needed. */\n async stopRecording() {\n return this.execute(async () => {\n const data = await this.platform.stopRecording();\n if (this.responseFormat === 'normalized') {\n return normalizeRecordingData(data);\n }\n return data;\n });\n }\n /** Pauses the recording session when supported. */\n pauseRecording() {\n return this.execute(() => this.platform.pauseRecording());\n }\n /** Resumes a paused recording session when supported. */\n resumeRecording() {\n return this.execute(() => this.platform.resumeRecording());\n }\n /** Returns the current recording state. */\n getCurrentStatus() {\n return this.execute(() => this.platform.getCurrentStatus());\n }\n /** Wraps calls to apply canonical error codes when requested. */\n async execute(fn) {\n try {\n return await fn();\n }\n catch (error) {\n if (this.responseFormat === 'normalized') {\n attachCanonicalErrorCode(error);\n }\n throw error;\n }\n }\n}\n//# sourceMappingURL=VoiceRecorderService.js.map","import { Capacitor, WebPlugin } from '@capacitor/core';\nimport { VoiceRecorderWebAdapter } from './adapters/VoiceRecorderWebAdapter';\nimport { getResponseFormatFromConfig } from './core/response-format';\nimport { VoiceRecorderService } from './service/VoiceRecorderService';\n/** Web implementation of the VoiceRecorder Capacitor plugin. */\nexport class VoiceRecorderWeb extends WebPlugin {\n constructor() {\n var _a, _b;\n super();\n const pluginConfig = (_b = (_a = Capacitor === null || Capacitor === void 0 ? void 0 : Capacitor.config) === null || _a === void 0 ? void 0 : _a.plugins) === null || _b === void 0 ? void 0 : _b.VoiceRecorder;\n const responseFormat = getResponseFormatFromConfig(pluginConfig);\n this.service = new VoiceRecorderService(new VoiceRecorderWebAdapter(), responseFormat);\n }\n /** Checks whether the browser can record audio. */\n canDeviceVoiceRecord() {\n return this.service.canDeviceVoiceRecord();\n }\n /** Returns whether microphone permission is currently granted. */\n hasAudioRecordingPermission() {\n return this.service.hasAudioRecordingPermission();\n }\n /** Requests microphone permission from the user. */\n requestAudioRecordingPermission() {\n return this.service.requestAudioRecordingPermission();\n }\n /** Starts a recording session. */\n startRecording(options) {\n return this.service.startRecording(options);\n }\n /** Stops the current recording session and returns the payload. */\n stopRecording() {\n return this.service.stopRecording();\n }\n /** Pauses the recording session when supported. */\n pauseRecording() {\n return this.service.pauseRecording();\n }\n /** Resumes a paused recording session when supported. */\n resumeRecording() {\n return this.service.resumeRecording();\n }\n /** Returns the current recording state. */\n getCurrentStatus() {\n return this.service.getCurrentStatus();\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","Filesystem","WebPlugin","Capacitor"],"mappings":"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"}
|
package/dist/plugin.js
CHANGED
|
@@ -349,7 +349,7 @@ var capacitorVoiceRecorder = (function (exports, core, filesystem, write_blob) {
|
|
|
349
349
|
reject(failedToRecordError());
|
|
350
350
|
};
|
|
351
351
|
this.mediaRecorder.onstop = async () => {
|
|
352
|
-
var _a, _b, _c, _d, _e;
|
|
352
|
+
var _a, _b, _c, _d, _e, _f;
|
|
353
353
|
const mt = (_b = (_a = this.mediaRecorder) === null || _a === void 0 ? void 0 : _a.mimeType) !== null && _b !== void 0 ? _b : mimeType;
|
|
354
354
|
const blobVoiceRecording = new Blob(this.chunks, { type: mt });
|
|
355
355
|
if (blobVoiceRecording.size <= 0) {
|
|
@@ -359,8 +359,9 @@ var capacitorVoiceRecorder = (function (exports, core, filesystem, write_blob) {
|
|
|
359
359
|
}
|
|
360
360
|
let uri = undefined;
|
|
361
361
|
let recordDataBase64 = '';
|
|
362
|
+
const fileExtension = ((_c = POSSIBLE_MIME_TYPES[mimeType]) !== null && _c !== void 0 ? _c : '').replace(/^\./, '');
|
|
362
363
|
if (options === null || options === void 0 ? void 0 : options.directory) {
|
|
363
|
-
const subDirectory = (
|
|
364
|
+
const subDirectory = (_f = (_e = (_d = options.subDirectory) === null || _d === void 0 ? void 0 : _d.match(/^\/?(.+[^/])\/?$/)) === null || _e === void 0 ? void 0 : _e[1]) !== null && _f !== void 0 ? _f : '';
|
|
364
365
|
const path = `${subDirectory}/recording-${new Date().getTime()}${POSSIBLE_MIME_TYPES[mt]}`;
|
|
365
366
|
await write_blob({
|
|
366
367
|
blob: blobVoiceRecording,
|
|
@@ -380,6 +381,7 @@ var capacitorVoiceRecorder = (function (exports, core, filesystem, write_blob) {
|
|
|
380
381
|
value: {
|
|
381
382
|
recordDataBase64,
|
|
382
383
|
mimeType: mt,
|
|
384
|
+
fileExtension,
|
|
383
385
|
msDuration: recordingDuration * 1000,
|
|
384
386
|
uri
|
|
385
387
|
}
|
|
@@ -506,8 +508,8 @@ var capacitorVoiceRecorder = (function (exports, core, filesystem, write_blob) {
|
|
|
506
508
|
|
|
507
509
|
/** Normalizes recording payloads into a stable contract shape. */
|
|
508
510
|
const normalizeRecordingData = (data) => {
|
|
509
|
-
const { recordDataBase64, uri, msDuration, mimeType } = data.value;
|
|
510
|
-
const normalizedValue = { msDuration, mimeType };
|
|
511
|
+
const { recordDataBase64, uri, msDuration, mimeType, fileExtension } = data.value;
|
|
512
|
+
const normalizedValue = { msDuration, mimeType, fileExtension };
|
|
511
513
|
const trimmedUri = typeof uri === 'string' && uri.length > 0 ? uri : undefined;
|
|
512
514
|
const trimmedBase64 = typeof recordDataBase64 === 'string' && recordDataBase64.length > 0 ? recordDataBase64 : undefined;
|
|
513
515
|
if (trimmedUri) {
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/platform/web/get-blob-duration.js","esm/platform/web/predefined-web-responses.js","esm/platform/web/VoiceRecorderImpl.js","esm/adapters/VoiceRecorderWebAdapter.js","esm/core/response-format.js","esm/core/error-codes.js","esm/core/recording-contract.js","esm/service/VoiceRecorderService.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst VoiceRecorder = registerPlugin('VoiceRecorder', {\n web: () => import('./web').then((m) => new m.VoiceRecorderWeb()),\n});\nexport * from './definitions';\nexport { VoiceRecorder };\n//# sourceMappingURL=index.js.map","/**\n * @param {Blob | string} blob\n * @returns {Promise<number>} Blob duration in seconds.\n */\nexport default async function getBlobDuration(blob) {\n // Check for AudioContext or webkitAudioContext (Safari)\n const AudioCtx = window.AudioContext || window.webkitAudioContext;\n if (!AudioCtx) {\n throw new Error('AudioContext is not supported in this environment.');\n }\n let audioContext = null;\n try {\n audioContext = new AudioCtx();\n let arrayBuffer;\n if (typeof blob === 'string') {\n arrayBuffer = base64ToArrayBuffer(blob);\n }\n else {\n arrayBuffer = await blob.arrayBuffer();\n }\n const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);\n return audioBuffer.duration;\n }\n catch (err) {\n throw new Error('Failed to get audio duration (AudioContext may require user interaction or is not supported): ' + (err instanceof Error ? err.message : String(err)));\n }\n finally {\n if (audioContext) {\n await audioContext.close();\n }\n }\n}\n/**\n * Convert base64 string to ArrayBuffer.\n * @param base64 The base64 string to convert.\n * @returns The converted ArrayBuffer.\n * @remarks This function is exported for test coverage purposes.\n */\nexport function base64ToArrayBuffer(base64) {\n const cleanBase64 = base64.replace(/^data:[^;]+;base64,/, '');\n const binaryString = atob(cleanBase64);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n}\n//# sourceMappingURL=get-blob-duration.js.map","/** Success wrapper for boolean plugin responses. */\nexport const successResponse = () => ({ value: true });\n/** Failure wrapper for boolean plugin responses. */\nexport const failureResponse = () => ({ value: false });\n/** Error for missing microphone permission. */\nexport const missingPermissionError = () => new Error('MISSING_PERMISSION');\n/** Error for attempting to start while already recording. */\nexport const alreadyRecordingError = () => new Error('ALREADY_RECORDING');\n/** Error for microphone in use by another app or recorder. */\nexport const microphoneBeingUsedError = () => new Error('MICROPHONE_BEING_USED');\n/** Error for devices that cannot record audio. */\nexport const deviceCannotVoiceRecordError = () => new Error('DEVICE_CANNOT_VOICE_RECORD');\n/** Error for recorder start failures. */\nexport const failedToRecordError = () => new Error('FAILED_TO_RECORD');\n/** Error for empty or zero-length recordings. */\nexport const emptyRecordingError = () => new Error('EMPTY_RECORDING');\n/** Error for stopping without an active recording. */\nexport const recordingHasNotStartedError = () => new Error('RECORDING_HAS_NOT_STARTED');\n/** Error for failures when fetching recording data. */\nexport const failedToFetchRecordingError = () => new Error('FAILED_TO_FETCH_RECORDING');\n/** Error for browsers that do not support permission queries. */\nexport const couldNotQueryPermissionStatusError = () => new Error('COULD_NOT_QUERY_PERMISSION_STATUS');\n//# sourceMappingURL=predefined-web-responses.js.map","import { Filesystem } from '@capacitor/filesystem';\nimport write_blob from 'capacitor-blob-writer';\nimport getBlobDuration from './get-blob-duration';\nimport { alreadyRecordingError, couldNotQueryPermissionStatusError, deviceCannotVoiceRecordError, emptyRecordingError, failedToFetchRecordingError, failedToRecordError, failureResponse, missingPermissionError, recordingHasNotStartedError, successResponse, } from './predefined-web-responses';\n/**\n * Ordered MIME types to probe for audio recording via `MediaRecorder.isTypeSupported()`.\n *\n * ⚠️ The order is intentional and MUST remain stable unless you also update the\n * selection policy in code and test on Safari/iOS + WebViews.\n *\n * ✅ What this list is used for\n * - Selecting a `mimeType` for `new MediaRecorder(stream, { mimeType })`.\n *\n * ❌ What this list does NOT guarantee\n * - It does NOT guarantee that the recorded output will be playable via the\n * HTML `<audio>` element in the same browser.\n *\n * Real-world caveat (important):\n * - We have observed cases where `MediaRecorder.isTypeSupported('audio/webm;codecs=opus')`\n * returned `true`, the recorder produced a Blob, but `<audio>` could not play it.\n * This can happen due to container/codec playback support differences, platform\n * quirks (especially Safari/iOS / WKWebView), or incomplete WebM playback support.\n *\n * Current selection behavior in this implementation:\n * - By default, MIME selection treats recorder support and playback support as separate\n * capabilities and probes both:\n * - Recorder capability: `MediaRecorder.isTypeSupported(type)`\n * - Playback capability: `audio.canPlayType(type)`\n * - This default can be disabled via `RecordingOptions.requirePlaybackSupport = false`\n * to fall back to recorder-only probing.\n *\n * Keeping legacy keys:\n * - Some entries are kept even if they overlap (e.g. `audio/mp4` and explicit codec),\n * to maximize compatibility across differing browser implementations.\n */\nconst POSSIBLE_MIME_TYPES = {\n // ✅ Most universal\n 'audio/mp4;codecs=\"mp4a.40.2\"': '.m4a', // AAC in MP4 (explicit codec helps detection)\n 'audio/mp4': '.m4a', // (legacy key kept; broad support)\n 'audio/aac': '.aac', // (legacy key kept; less common in the wild)\n 'audio/mpeg': '.mp3', // MP3 (universal)\n 'audio/wav': '.wav', // WAV (universal, big files)\n // ✅ Modern high-quality (very widely supported, but slightly less “universal” than MP3/AAC)\n 'audio/webm;codecs=\"opus\"': '.webm', // Opus in WebM (explicit codec helps detection)\n 'audio/webm;codecs=opus': '.webm', // (legacy key kept)\n 'audio/webm': '.webm', // (legacy key kept; container-only, codec-dependent)\n // ⚠️ Least universal (Safari/iOS historically the limiting factor)\n 'audio/ogg;codecs=opus': '.ogg', // (legacy key kept)\n 'audio/ogg;codecs=vorbis': '.ogg', // Ogg Vorbis (weakest mainstream support)\n};\n/** Creates a promise that never resolves. */\nconst neverResolvingPromise = () => new Promise(() => undefined);\n/** Browser implementation backed by MediaRecorder and Capacitor Filesystem. */\nexport class VoiceRecorderImpl {\n constructor() {\n /** Active MediaRecorder instance, if recording. */\n this.mediaRecorder = null;\n /** Collected data chunks from MediaRecorder. */\n this.chunks = [];\n /** Promise resolved when the recorder stops and payload is ready. */\n this.pendingResult = neverResolvingPromise();\n }\n /**\n * Returns whether the browser can start a recording session.\n *\n * On web this checks:\n * - `navigator.mediaDevices.getUserMedia`\n * - at least one supported recording MIME type using {@link getSupportedMimeType}\n *\n * The optional `requirePlaybackSupport` flag is forwarded to MIME selection and defaults\n * to `true` when omitted.\n */\n static async canDeviceVoiceRecord(options) {\n var _a;\n if (((_a = navigator === null || navigator === void 0 ? void 0 : navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.getUserMedia) == null ||\n VoiceRecorderImpl.getSupportedMimeType({\n requirePlaybackSupport: options === null || options === void 0 ? void 0 : options.requirePlaybackSupport,\n }) == null) {\n return failureResponse();\n }\n else {\n return successResponse();\n }\n }\n /**\n * Starts a recording session using `MediaRecorder`.\n *\n * The selected MIME type is resolved once at start time (using the optional\n * `requirePlaybackSupport` flag from `RecordingOptions`) and reused for the final Blob\n * and file extension to keep the recording payload internally consistent.\n */\n async startRecording(options) {\n if (this.mediaRecorder != null) {\n throw alreadyRecordingError();\n }\n const deviceCanRecord = await VoiceRecorderImpl.canDeviceVoiceRecord(options);\n if (!deviceCanRecord.value) {\n throw deviceCannotVoiceRecordError();\n }\n const havingPermission = await VoiceRecorderImpl.hasAudioRecordingPermission().catch(() => successResponse());\n if (!havingPermission.value) {\n throw missingPermissionError();\n }\n return navigator.mediaDevices\n .getUserMedia({ audio: true })\n .then((stream) => this.onSuccessfullyStartedRecording(stream, options))\n .catch(this.onFailedToStartRecording.bind(this));\n }\n /** Stops the current recording and resolves the pending payload. */\n async stopRecording() {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n }\n try {\n this.mediaRecorder.stop();\n this.mediaRecorder.stream.getTracks().forEach((track) => track.stop());\n return this.pendingResult;\n }\n catch (ignore) {\n throw failedToFetchRecordingError();\n }\n finally {\n this.prepareInstanceForNextOperation();\n }\n }\n /** Returns whether the browser has microphone permission. */\n static async hasAudioRecordingPermission() {\n // Safari does not support navigator.permissions.query\n if (!navigator.permissions.query) {\n if (navigator.mediaDevices !== undefined) {\n return navigator.mediaDevices\n .getUserMedia({ audio: true })\n .then(() => successResponse())\n .catch(() => {\n throw couldNotQueryPermissionStatusError();\n });\n }\n }\n return navigator.permissions\n .query({ name: 'microphone' })\n .then((result) => ({ value: result.state === 'granted' }))\n .catch(() => {\n throw couldNotQueryPermissionStatusError();\n });\n }\n /** Requests microphone permission from the browser. */\n static async requestAudioRecordingPermission() {\n const havingPermission = await VoiceRecorderImpl.hasAudioRecordingPermission().catch(() => failureResponse());\n if (havingPermission.value) {\n return successResponse();\n }\n return navigator.mediaDevices\n .getUserMedia({ audio: true })\n .then(() => successResponse())\n .catch(() => failureResponse());\n }\n /** Pauses the recording session when supported. */\n pauseRecording() {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n }\n else if (this.mediaRecorder.state === 'recording') {\n this.mediaRecorder.pause();\n return Promise.resolve(successResponse());\n }\n else {\n return Promise.resolve(failureResponse());\n }\n }\n /** Resumes a paused recording session when supported. */\n resumeRecording() {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n }\n else if (this.mediaRecorder.state === 'paused') {\n this.mediaRecorder.resume();\n return Promise.resolve(successResponse());\n }\n else {\n return Promise.resolve(failureResponse());\n }\n }\n /** Returns the current recording status from MediaRecorder. */\n getCurrentStatus() {\n if (this.mediaRecorder == null) {\n return Promise.resolve({ status: 'NONE' });\n }\n else if (this.mediaRecorder.state === 'recording') {\n return Promise.resolve({ status: 'RECORDING' });\n }\n else if (this.mediaRecorder.state === 'paused') {\n return Promise.resolve({ status: 'PAUSED' });\n }\n else {\n return Promise.resolve({ status: 'NONE' });\n }\n }\n /**\n * Returns the first MIME type (key of {@link POSSIBLE_MIME_TYPES}) that the current\n * environment reports as supported for recording via `MediaRecorder.isTypeSupported()`,\n * optionally requiring native HTML `<audio>` playback support too.\n *\n * The search order is the iteration order of {@link POSSIBLE_MIME_TYPES}.\n *\n * @typeParam T - A MIME type string that exists as a key in {@link POSSIBLE_MIME_TYPES}.\n *\n * @returns The first supported MIME type for `MediaRecorder`, or `null` if:\n * - `MediaRecorder` is unavailable, or\n * - no configured MIME types are supported.\n *\n * ⚠️ Important: `MediaRecorder` support ≠ `<audio>` playback support\n *\n * Some browsers/platforms can claim support for recording a format (notably WebM/Opus)\n * but still fail to play the resulting Blob through the native HTML audio pipeline.\n * This mismatch is especially likely on Safari/iOS / WKWebView variants, so the default\n * behavior also probes `HTMLAudioElement.canPlayType(type)` when available.\n *\n * Selection policy when playback probing is enabled:\n * - keep the global priority order from {@link POSSIBLE_MIME_TYPES}\n * - among recordable types, prefer the first `\"probably\"` playable candidate\n * - otherwise return the first `\"maybe\"` playable candidate\n * - treat `\"\"` as not playable\n *\n * Note: The <audio> element is never attached to the DOM, so it won't appear to users or assistive tech.\n *\n * Fallback behavior:\n * - If `document` / `audio.canPlayType` is unavailable (e.g. SSR-like environments),\n * this falls back to record-only probing.\n */\n static getSupportedMimeType(options) {\n var _a, _b, _c, _d, _e;\n if ((MediaRecorder === null || MediaRecorder === void 0 ? void 0 : MediaRecorder.isTypeSupported) == null)\n return null;\n const orderedTypes = Object.keys(POSSIBLE_MIME_TYPES);\n const recordSupportedTypes = orderedTypes.filter((type) => MediaRecorder.isTypeSupported(type));\n if (recordSupportedTypes.length === 0)\n return null;\n const requirePlaybackSupport = (_a = options === null || options === void 0 ? void 0 : options.requirePlaybackSupport) !== null && _a !== void 0 ? _a : VoiceRecorderImpl.DEFAULT_REQUIRE_PLAYBACK_SUPPORT;\n if (!requirePlaybackSupport) {\n return (_b = recordSupportedTypes[0]) !== null && _b !== void 0 ? _b : null;\n }\n if (typeof document === 'undefined' || typeof document.createElement !== 'function') {\n return (_c = recordSupportedTypes[0]) !== null && _c !== void 0 ? _c : null;\n }\n const audioElement = document.createElement('audio');\n if (typeof audioElement.canPlayType !== 'function') {\n return (_d = recordSupportedTypes[0]) !== null && _d !== void 0 ? _d : null;\n }\n let firstProbably = null;\n let firstMaybe = null;\n for (const type of recordSupportedTypes) {\n const playbackSupport = audioElement.canPlayType(type);\n if (playbackSupport === 'probably') {\n firstProbably = type;\n break;\n }\n if (playbackSupport === 'maybe' && firstMaybe == null) {\n firstMaybe = type;\n }\n }\n return (_e = firstProbably !== null && firstProbably !== void 0 ? firstProbably : firstMaybe) !== null && _e !== void 0 ? _e : null;\n }\n /** Initializes MediaRecorder and wires up handlers. */\n onSuccessfullyStartedRecording(stream, options) {\n this.pendingResult = new Promise((resolve, reject) => {\n const mimeType = VoiceRecorderImpl.getSupportedMimeType({\n requirePlaybackSupport: options === null || options === void 0 ? void 0 : options.requirePlaybackSupport,\n });\n if (mimeType == null) {\n this.prepareInstanceForNextOperation();\n reject(failedToRecordError());\n return;\n }\n this.mediaRecorder = new MediaRecorder(stream, { mimeType });\n this.mediaRecorder.onerror = () => {\n this.prepareInstanceForNextOperation();\n reject(failedToRecordError());\n };\n this.mediaRecorder.onstop = async () => {\n var _a, _b, _c, _d, _e;\n const mt = (_b = (_a = this.mediaRecorder) === null || _a === void 0 ? void 0 : _a.mimeType) !== null && _b !== void 0 ? _b : mimeType;\n const blobVoiceRecording = new Blob(this.chunks, { type: mt });\n if (blobVoiceRecording.size <= 0) {\n this.prepareInstanceForNextOperation();\n reject(emptyRecordingError());\n return;\n }\n let uri = undefined;\n let recordDataBase64 = '';\n if (options === null || options === void 0 ? void 0 : options.directory) {\n const subDirectory = (_e = (_d = (_c = options.subDirectory) === null || _c === void 0 ? void 0 : _c.match(/^\\/?(.+[^/])\\/?$/)) === null || _d === void 0 ? void 0 : _d[1]) !== null && _e !== void 0 ? _e : '';\n const path = `${subDirectory}/recording-${new Date().getTime()}${POSSIBLE_MIME_TYPES[mt]}`;\n await write_blob({\n blob: blobVoiceRecording,\n directory: options.directory,\n fast_mode: true,\n path,\n recursive: true,\n });\n ({ uri } = await Filesystem.getUri({ directory: options.directory, path }));\n }\n else {\n recordDataBase64 = await VoiceRecorderImpl.blobToBase64(blobVoiceRecording);\n }\n const recordingDuration = await getBlobDuration(blobVoiceRecording);\n this.prepareInstanceForNextOperation();\n resolve({\n value: {\n recordDataBase64,\n mimeType: mt,\n msDuration: recordingDuration * 1000,\n uri\n }\n });\n };\n this.mediaRecorder.ondataavailable = (event) => this.chunks.push(event.data);\n this.mediaRecorder.start();\n });\n return successResponse();\n }\n /** Handles failures from getUserMedia. */\n onFailedToStartRecording() {\n this.prepareInstanceForNextOperation();\n throw failedToRecordError();\n }\n /** Converts a Blob payload into a base64 string. */\n static blobToBase64(blob) {\n return new Promise((resolve) => {\n const reader = new FileReader();\n reader.onloadend = () => {\n const recordingResult = String(reader.result);\n const splitResult = recordingResult.split('base64,');\n const toResolve = splitResult.length > 1 ? splitResult[1] : recordingResult;\n resolve(toResolve.trim());\n };\n reader.readAsDataURL(blob);\n });\n }\n /** Resets state for the next recording attempt. */\n prepareInstanceForNextOperation() {\n if (this.mediaRecorder != null && this.mediaRecorder.state === 'recording') {\n try {\n this.mediaRecorder.stop();\n }\n catch (ignore) {\n console.warn('Failed to stop recording during cleanup');\n }\n }\n this.pendingResult = neverResolvingPromise();\n this.mediaRecorder = null;\n this.chunks = [];\n }\n}\n/** Default behavior for web MIME selection: require recorder + playback support. */\nVoiceRecorderImpl.DEFAULT_REQUIRE_PLAYBACK_SUPPORT = true;\n//# sourceMappingURL=VoiceRecorderImpl.js.map","import { VoiceRecorderImpl } from '../platform/web/VoiceRecorderImpl';\n/** Web adapter that delegates to the browser-specific implementation. */\nexport class VoiceRecorderWebAdapter {\n constructor() {\n /** Browser implementation that talks to MediaRecorder APIs. */\n this.voiceRecorderImpl = new VoiceRecorderImpl();\n }\n /** Checks whether the browser can record audio. */\n canDeviceVoiceRecord() {\n return VoiceRecorderImpl.canDeviceVoiceRecord();\n }\n /** Returns whether the browser has microphone permission. */\n hasAudioRecordingPermission() {\n return VoiceRecorderImpl.hasAudioRecordingPermission();\n }\n /** Requests microphone permission through the browser. */\n requestAudioRecordingPermission() {\n return VoiceRecorderImpl.requestAudioRecordingPermission();\n }\n /** Starts a recording session using MediaRecorder. */\n startRecording(options) {\n return this.voiceRecorderImpl.startRecording(options);\n }\n /** Stops the recording session and returns the payload. */\n stopRecording() {\n return this.voiceRecorderImpl.stopRecording();\n }\n /** Pauses the recording session when supported. */\n pauseRecording() {\n return this.voiceRecorderImpl.pauseRecording();\n }\n /** Resumes a paused recording session when supported. */\n resumeRecording() {\n return this.voiceRecorderImpl.resumeRecording();\n }\n /** Returns the current recording state. */\n getCurrentStatus() {\n return this.voiceRecorderImpl.getCurrentStatus();\n }\n}\n//# sourceMappingURL=VoiceRecorderWebAdapter.js.map","/** Default response shape when no config is provided. */\nexport const DEFAULT_RESPONSE_FORMAT = 'legacy';\n/** Parses a user-provided response format into a supported value. */\nexport const resolveResponseFormat = (value) => {\n if (typeof value === 'string' && value.toLowerCase() === 'normalized') {\n return 'normalized';\n }\n return DEFAULT_RESPONSE_FORMAT;\n};\n/** Reads the response format from a Capacitor plugin config object. */\nexport const getResponseFormatFromConfig = (config) => {\n if (config && typeof config === 'object' && 'responseFormat' in config) {\n return resolveResponseFormat(config.responseFormat);\n }\n return DEFAULT_RESPONSE_FORMAT;\n};\n//# sourceMappingURL=response-format.js.map","/** Maps legacy error messages to canonical error codes. */\nconst legacyToCanonical = {\n CANNOT_RECORD_ON_THIS_PHONE: 'DEVICE_CANNOT_VOICE_RECORD',\n};\n/** Normalizes legacy error messages into canonical error codes. */\nexport const toCanonicalErrorCode = (legacyMessage) => {\n var _a;\n return (_a = legacyToCanonical[legacyMessage]) !== null && _a !== void 0 ? _a : legacyMessage;\n};\n/** Adds a canonical `code` field to Error-like objects when possible. */\nexport const attachCanonicalErrorCode = (error) => {\n if (!error || typeof error !== 'object') {\n return;\n }\n const messageValue = error.message;\n if (typeof messageValue !== 'string') {\n return;\n }\n error.code = toCanonicalErrorCode(messageValue);\n};\n//# sourceMappingURL=error-codes.js.map","/** Normalizes recording payloads into a stable contract shape. */\nexport const normalizeRecordingData = (data) => {\n const { recordDataBase64, uri, msDuration, mimeType } = data.value;\n const normalizedValue = { msDuration, mimeType };\n const trimmedUri = typeof uri === 'string' && uri.length > 0 ? uri : undefined;\n const trimmedBase64 = typeof recordDataBase64 === 'string' && recordDataBase64.length > 0 ? recordDataBase64 : undefined;\n if (trimmedUri) {\n normalizedValue.uri = trimmedUri;\n }\n else if (trimmedBase64) {\n normalizedValue.recordDataBase64 = trimmedBase64;\n }\n return { value: normalizedValue };\n};\n//# sourceMappingURL=recording-contract.js.map","import { attachCanonicalErrorCode } from '../core/error-codes';\nimport { normalizeRecordingData } from '../core/recording-contract';\n/** Orchestrates platform calls and normalizes responses when requested. */\nexport class VoiceRecorderService {\n constructor(platform, responseFormat) {\n this.platform = platform;\n this.responseFormat = responseFormat;\n }\n /** Checks whether the device can record audio. */\n canDeviceVoiceRecord() {\n return this.execute(() => this.platform.canDeviceVoiceRecord());\n }\n /** Returns whether microphone permission is currently granted. */\n hasAudioRecordingPermission() {\n return this.execute(() => this.platform.hasAudioRecordingPermission());\n }\n /** Requests microphone permission from the user. */\n requestAudioRecordingPermission() {\n return this.execute(() => this.platform.requestAudioRecordingPermission());\n }\n /** Starts a recording session. */\n startRecording(options) {\n return this.execute(() => this.platform.startRecording(options));\n }\n /** Stops the recording session and formats the payload if needed. */\n async stopRecording() {\n return this.execute(async () => {\n const data = await this.platform.stopRecording();\n if (this.responseFormat === 'normalized') {\n return normalizeRecordingData(data);\n }\n return data;\n });\n }\n /** Pauses the recording session when supported. */\n pauseRecording() {\n return this.execute(() => this.platform.pauseRecording());\n }\n /** Resumes a paused recording session when supported. */\n resumeRecording() {\n return this.execute(() => this.platform.resumeRecording());\n }\n /** Returns the current recording state. */\n getCurrentStatus() {\n return this.execute(() => this.platform.getCurrentStatus());\n }\n /** Wraps calls to apply canonical error codes when requested. */\n async execute(fn) {\n try {\n return await fn();\n }\n catch (error) {\n if (this.responseFormat === 'normalized') {\n attachCanonicalErrorCode(error);\n }\n throw error;\n }\n }\n}\n//# sourceMappingURL=VoiceRecorderService.js.map","import { Capacitor, WebPlugin } from '@capacitor/core';\nimport { VoiceRecorderWebAdapter } from './adapters/VoiceRecorderWebAdapter';\nimport { getResponseFormatFromConfig } from './core/response-format';\nimport { VoiceRecorderService } from './service/VoiceRecorderService';\n/** Web implementation of the VoiceRecorder Capacitor plugin. */\nexport class VoiceRecorderWeb extends WebPlugin {\n constructor() {\n var _a, _b;\n super();\n const pluginConfig = (_b = (_a = Capacitor === null || Capacitor === void 0 ? void 0 : Capacitor.config) === null || _a === void 0 ? void 0 : _a.plugins) === null || _b === void 0 ? void 0 : _b.VoiceRecorder;\n const responseFormat = getResponseFormatFromConfig(pluginConfig);\n this.service = new VoiceRecorderService(new VoiceRecorderWebAdapter(), responseFormat);\n }\n /** Checks whether the browser can record audio. */\n canDeviceVoiceRecord() {\n return this.service.canDeviceVoiceRecord();\n }\n /** Returns whether microphone permission is currently granted. */\n hasAudioRecordingPermission() {\n return this.service.hasAudioRecordingPermission();\n }\n /** Requests microphone permission from the user. */\n requestAudioRecordingPermission() {\n return this.service.requestAudioRecordingPermission();\n }\n /** Starts a recording session. */\n startRecording(options) {\n return this.service.startRecording(options);\n }\n /** Stops the current recording session and returns the payload. */\n stopRecording() {\n return this.service.stopRecording();\n }\n /** Pauses the recording session when supported. */\n pauseRecording() {\n return this.service.pauseRecording();\n }\n /** Resumes a paused recording session when supported. */\n resumeRecording() {\n return this.service.resumeRecording();\n }\n /** Returns the current recording state. */\n getCurrentStatus() {\n return this.service.getCurrentStatus();\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","Filesystem","WebPlugin","Capacitor"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/platform/web/get-blob-duration.js","esm/platform/web/predefined-web-responses.js","esm/platform/web/VoiceRecorderImpl.js","esm/adapters/VoiceRecorderWebAdapter.js","esm/core/response-format.js","esm/core/error-codes.js","esm/core/recording-contract.js","esm/service/VoiceRecorderService.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst VoiceRecorder = registerPlugin('VoiceRecorder', {\n web: () => import('./web').then((m) => new m.VoiceRecorderWeb()),\n});\nexport * from './definitions';\nexport { VoiceRecorder };\n//# sourceMappingURL=index.js.map","/**\n * @param {Blob | string} blob\n * @returns {Promise<number>} Blob duration in seconds.\n */\nexport default async function getBlobDuration(blob) {\n // Check for AudioContext or webkitAudioContext (Safari)\n const AudioCtx = window.AudioContext || window.webkitAudioContext;\n if (!AudioCtx) {\n throw new Error('AudioContext is not supported in this environment.');\n }\n let audioContext = null;\n try {\n audioContext = new AudioCtx();\n let arrayBuffer;\n if (typeof blob === 'string') {\n arrayBuffer = base64ToArrayBuffer(blob);\n }\n else {\n arrayBuffer = await blob.arrayBuffer();\n }\n const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);\n return audioBuffer.duration;\n }\n catch (err) {\n throw new Error('Failed to get audio duration (AudioContext may require user interaction or is not supported): ' + (err instanceof Error ? err.message : String(err)));\n }\n finally {\n if (audioContext) {\n await audioContext.close();\n }\n }\n}\n/**\n * Convert base64 string to ArrayBuffer.\n * @param base64 The base64 string to convert.\n * @returns The converted ArrayBuffer.\n * @remarks This function is exported for test coverage purposes.\n */\nexport function base64ToArrayBuffer(base64) {\n const cleanBase64 = base64.replace(/^data:[^;]+;base64,/, '');\n const binaryString = atob(cleanBase64);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n}\n//# sourceMappingURL=get-blob-duration.js.map","/** Success wrapper for boolean plugin responses. */\nexport const successResponse = () => ({ value: true });\n/** Failure wrapper for boolean plugin responses. */\nexport const failureResponse = () => ({ value: false });\n/** Error for missing microphone permission. */\nexport const missingPermissionError = () => new Error('MISSING_PERMISSION');\n/** Error for attempting to start while already recording. */\nexport const alreadyRecordingError = () => new Error('ALREADY_RECORDING');\n/** Error for microphone in use by another app or recorder. */\nexport const microphoneBeingUsedError = () => new Error('MICROPHONE_BEING_USED');\n/** Error for devices that cannot record audio. */\nexport const deviceCannotVoiceRecordError = () => new Error('DEVICE_CANNOT_VOICE_RECORD');\n/** Error for recorder start failures. */\nexport const failedToRecordError = () => new Error('FAILED_TO_RECORD');\n/** Error for empty or zero-length recordings. */\nexport const emptyRecordingError = () => new Error('EMPTY_RECORDING');\n/** Error for stopping without an active recording. */\nexport const recordingHasNotStartedError = () => new Error('RECORDING_HAS_NOT_STARTED');\n/** Error for failures when fetching recording data. */\nexport const failedToFetchRecordingError = () => new Error('FAILED_TO_FETCH_RECORDING');\n/** Error for browsers that do not support permission queries. */\nexport const couldNotQueryPermissionStatusError = () => new Error('COULD_NOT_QUERY_PERMISSION_STATUS');\n//# sourceMappingURL=predefined-web-responses.js.map","import { Filesystem } from '@capacitor/filesystem';\nimport write_blob from 'capacitor-blob-writer';\nimport getBlobDuration from './get-blob-duration';\nimport { alreadyRecordingError, couldNotQueryPermissionStatusError, deviceCannotVoiceRecordError, emptyRecordingError, failedToFetchRecordingError, failedToRecordError, failureResponse, missingPermissionError, recordingHasNotStartedError, successResponse, } from './predefined-web-responses';\n/**\n * Ordered MIME types to probe for audio recording via `MediaRecorder.isTypeSupported()`.\n *\n * ⚠️ The order is intentional and MUST remain stable unless you also update the\n * selection policy in code and test on Safari/iOS + WebViews.\n *\n * ✅ What this list is used for\n * - Selecting a `mimeType` for `new MediaRecorder(stream, { mimeType })`.\n *\n * ❌ What this list does NOT guarantee\n * - It does NOT guarantee that the recorded output will be playable via the\n * HTML `<audio>` element in the same browser.\n *\n * Real-world caveat (important):\n * - We have observed cases where `MediaRecorder.isTypeSupported('audio/webm;codecs=opus')`\n * returned `true`, the recorder produced a Blob, but `<audio>` could not play it.\n * This can happen due to container/codec playback support differences, platform\n * quirks (especially Safari/iOS / WKWebView), or incomplete WebM playback support.\n *\n * Current selection behavior in this implementation:\n * - By default, MIME selection treats recorder support and playback support as separate\n * capabilities and probes both:\n * - Recorder capability: `MediaRecorder.isTypeSupported(type)`\n * - Playback capability: `audio.canPlayType(type)`\n * - This default can be disabled via `RecordingOptions.requirePlaybackSupport = false`\n * to fall back to recorder-only probing.\n *\n * Keeping legacy keys:\n * - Some entries are kept even if they overlap (e.g. `audio/mp4` and explicit codec),\n * to maximize compatibility across differing browser implementations.\n */\nconst POSSIBLE_MIME_TYPES = {\n // ✅ Most universal\n 'audio/mp4;codecs=\"mp4a.40.2\"': '.m4a', // AAC in MP4 (explicit codec helps detection)\n 'audio/mp4': '.m4a', // (legacy key kept; broad support)\n 'audio/aac': '.aac', // (legacy key kept; less common in the wild)\n 'audio/mpeg': '.mp3', // MP3 (universal)\n 'audio/wav': '.wav', // WAV (universal, big files)\n // ✅ Modern high-quality (very widely supported, but slightly less “universal” than MP3/AAC)\n 'audio/webm;codecs=\"opus\"': '.webm', // Opus in WebM (explicit codec helps detection)\n 'audio/webm;codecs=opus': '.webm', // (legacy key kept)\n 'audio/webm': '.webm', // (legacy key kept; container-only, codec-dependent)\n // ⚠️ Least universal (Safari/iOS historically the limiting factor)\n 'audio/ogg;codecs=opus': '.ogg', // (legacy key kept)\n 'audio/ogg;codecs=vorbis': '.ogg', // Ogg Vorbis (weakest mainstream support)\n};\n/** Creates a promise that never resolves. */\nconst neverResolvingPromise = () => new Promise(() => undefined);\n/** Browser implementation backed by MediaRecorder and Capacitor Filesystem. */\nexport class VoiceRecorderImpl {\n constructor() {\n /** Active MediaRecorder instance, if recording. */\n this.mediaRecorder = null;\n /** Collected data chunks from MediaRecorder. */\n this.chunks = [];\n /** Promise resolved when the recorder stops and payload is ready. */\n this.pendingResult = neverResolvingPromise();\n }\n /**\n * Returns whether the browser can start a recording session.\n *\n * On web this checks:\n * - `navigator.mediaDevices.getUserMedia`\n * - at least one supported recording MIME type using {@link getSupportedMimeType}\n *\n * The optional `requirePlaybackSupport` flag is forwarded to MIME selection and defaults\n * to `true` when omitted.\n */\n static async canDeviceVoiceRecord(options) {\n var _a;\n if (((_a = navigator === null || navigator === void 0 ? void 0 : navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.getUserMedia) == null ||\n VoiceRecorderImpl.getSupportedMimeType({\n requirePlaybackSupport: options === null || options === void 0 ? void 0 : options.requirePlaybackSupport,\n }) == null) {\n return failureResponse();\n }\n else {\n return successResponse();\n }\n }\n /**\n * Starts a recording session using `MediaRecorder`.\n *\n * The selected MIME type is resolved once at start time (using the optional\n * `requirePlaybackSupport` flag from `RecordingOptions`) and reused for the final Blob\n * and file extension to keep the recording payload internally consistent.\n */\n async startRecording(options) {\n if (this.mediaRecorder != null) {\n throw alreadyRecordingError();\n }\n const deviceCanRecord = await VoiceRecorderImpl.canDeviceVoiceRecord(options);\n if (!deviceCanRecord.value) {\n throw deviceCannotVoiceRecordError();\n }\n const havingPermission = await VoiceRecorderImpl.hasAudioRecordingPermission().catch(() => successResponse());\n if (!havingPermission.value) {\n throw missingPermissionError();\n }\n return navigator.mediaDevices\n .getUserMedia({ audio: true })\n .then((stream) => this.onSuccessfullyStartedRecording(stream, options))\n .catch(this.onFailedToStartRecording.bind(this));\n }\n /** Stops the current recording and resolves the pending payload. */\n async stopRecording() {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n }\n try {\n this.mediaRecorder.stop();\n this.mediaRecorder.stream.getTracks().forEach((track) => track.stop());\n return this.pendingResult;\n }\n catch (ignore) {\n throw failedToFetchRecordingError();\n }\n finally {\n this.prepareInstanceForNextOperation();\n }\n }\n /** Returns whether the browser has microphone permission. */\n static async hasAudioRecordingPermission() {\n // Safari does not support navigator.permissions.query\n if (!navigator.permissions.query) {\n if (navigator.mediaDevices !== undefined) {\n return navigator.mediaDevices\n .getUserMedia({ audio: true })\n .then(() => successResponse())\n .catch(() => {\n throw couldNotQueryPermissionStatusError();\n });\n }\n }\n return navigator.permissions\n .query({ name: 'microphone' })\n .then((result) => ({ value: result.state === 'granted' }))\n .catch(() => {\n throw couldNotQueryPermissionStatusError();\n });\n }\n /** Requests microphone permission from the browser. */\n static async requestAudioRecordingPermission() {\n const havingPermission = await VoiceRecorderImpl.hasAudioRecordingPermission().catch(() => failureResponse());\n if (havingPermission.value) {\n return successResponse();\n }\n return navigator.mediaDevices\n .getUserMedia({ audio: true })\n .then(() => successResponse())\n .catch(() => failureResponse());\n }\n /** Pauses the recording session when supported. */\n pauseRecording() {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n }\n else if (this.mediaRecorder.state === 'recording') {\n this.mediaRecorder.pause();\n return Promise.resolve(successResponse());\n }\n else {\n return Promise.resolve(failureResponse());\n }\n }\n /** Resumes a paused recording session when supported. */\n resumeRecording() {\n if (this.mediaRecorder == null) {\n throw recordingHasNotStartedError();\n }\n else if (this.mediaRecorder.state === 'paused') {\n this.mediaRecorder.resume();\n return Promise.resolve(successResponse());\n }\n else {\n return Promise.resolve(failureResponse());\n }\n }\n /** Returns the current recording status from MediaRecorder. */\n getCurrentStatus() {\n if (this.mediaRecorder == null) {\n return Promise.resolve({ status: 'NONE' });\n }\n else if (this.mediaRecorder.state === 'recording') {\n return Promise.resolve({ status: 'RECORDING' });\n }\n else if (this.mediaRecorder.state === 'paused') {\n return Promise.resolve({ status: 'PAUSED' });\n }\n else {\n return Promise.resolve({ status: 'NONE' });\n }\n }\n /**\n * Returns the first MIME type (key of {@link POSSIBLE_MIME_TYPES}) that the current\n * environment reports as supported for recording via `MediaRecorder.isTypeSupported()`,\n * optionally requiring native HTML `<audio>` playback support too.\n *\n * The search order is the iteration order of {@link POSSIBLE_MIME_TYPES}.\n *\n * @typeParam T - A MIME type string that exists as a key in {@link POSSIBLE_MIME_TYPES}.\n *\n * @returns The first supported MIME type for `MediaRecorder`, or `null` if:\n * - `MediaRecorder` is unavailable, or\n * - no configured MIME types are supported.\n *\n * ⚠️ Important: `MediaRecorder` support ≠ `<audio>` playback support\n *\n * Some browsers/platforms can claim support for recording a format (notably WebM/Opus)\n * but still fail to play the resulting Blob through the native HTML audio pipeline.\n * This mismatch is especially likely on Safari/iOS / WKWebView variants, so the default\n * behavior also probes `HTMLAudioElement.canPlayType(type)` when available.\n *\n * Selection policy when playback probing is enabled:\n * - keep the global priority order from {@link POSSIBLE_MIME_TYPES}\n * - among recordable types, prefer the first `\"probably\"` playable candidate\n * - otherwise return the first `\"maybe\"` playable candidate\n * - treat `\"\"` as not playable\n *\n * Note: The <audio> element is never attached to the DOM, so it won't appear to users or assistive tech.\n *\n * Fallback behavior:\n * - If `document` / `audio.canPlayType` is unavailable (e.g. SSR-like environments),\n * this falls back to record-only probing.\n */\n static getSupportedMimeType(options) {\n var _a, _b, _c, _d, _e;\n if ((MediaRecorder === null || MediaRecorder === void 0 ? void 0 : MediaRecorder.isTypeSupported) == null)\n return null;\n const orderedTypes = Object.keys(POSSIBLE_MIME_TYPES);\n const recordSupportedTypes = orderedTypes.filter((type) => MediaRecorder.isTypeSupported(type));\n if (recordSupportedTypes.length === 0)\n return null;\n const requirePlaybackSupport = (_a = options === null || options === void 0 ? void 0 : options.requirePlaybackSupport) !== null && _a !== void 0 ? _a : VoiceRecorderImpl.DEFAULT_REQUIRE_PLAYBACK_SUPPORT;\n if (!requirePlaybackSupport) {\n return (_b = recordSupportedTypes[0]) !== null && _b !== void 0 ? _b : null;\n }\n if (typeof document === 'undefined' || typeof document.createElement !== 'function') {\n return (_c = recordSupportedTypes[0]) !== null && _c !== void 0 ? _c : null;\n }\n const audioElement = document.createElement('audio');\n if (typeof audioElement.canPlayType !== 'function') {\n return (_d = recordSupportedTypes[0]) !== null && _d !== void 0 ? _d : null;\n }\n let firstProbably = null;\n let firstMaybe = null;\n for (const type of recordSupportedTypes) {\n const playbackSupport = audioElement.canPlayType(type);\n if (playbackSupport === 'probably') {\n firstProbably = type;\n break;\n }\n if (playbackSupport === 'maybe' && firstMaybe == null) {\n firstMaybe = type;\n }\n }\n return (_e = firstProbably !== null && firstProbably !== void 0 ? firstProbably : firstMaybe) !== null && _e !== void 0 ? _e : null;\n }\n /** Initializes MediaRecorder and wires up handlers. */\n onSuccessfullyStartedRecording(stream, options) {\n this.pendingResult = new Promise((resolve, reject) => {\n const mimeType = VoiceRecorderImpl.getSupportedMimeType({\n requirePlaybackSupport: options === null || options === void 0 ? void 0 : options.requirePlaybackSupport,\n });\n if (mimeType == null) {\n this.prepareInstanceForNextOperation();\n reject(failedToRecordError());\n return;\n }\n this.mediaRecorder = new MediaRecorder(stream, { mimeType });\n this.mediaRecorder.onerror = () => {\n this.prepareInstanceForNextOperation();\n reject(failedToRecordError());\n };\n this.mediaRecorder.onstop = async () => {\n var _a, _b, _c, _d, _e, _f;\n const mt = (_b = (_a = this.mediaRecorder) === null || _a === void 0 ? void 0 : _a.mimeType) !== null && _b !== void 0 ? _b : mimeType;\n const blobVoiceRecording = new Blob(this.chunks, { type: mt });\n if (blobVoiceRecording.size <= 0) {\n this.prepareInstanceForNextOperation();\n reject(emptyRecordingError());\n return;\n }\n let uri = undefined;\n let recordDataBase64 = '';\n const fileExtension = ((_c = POSSIBLE_MIME_TYPES[mimeType]) !== null && _c !== void 0 ? _c : '').replace(/^\\./, '');\n if (options === null || options === void 0 ? void 0 : options.directory) {\n const subDirectory = (_f = (_e = (_d = options.subDirectory) === null || _d === void 0 ? void 0 : _d.match(/^\\/?(.+[^/])\\/?$/)) === null || _e === void 0 ? void 0 : _e[1]) !== null && _f !== void 0 ? _f : '';\n const path = `${subDirectory}/recording-${new Date().getTime()}${POSSIBLE_MIME_TYPES[mt]}`;\n await write_blob({\n blob: blobVoiceRecording,\n directory: options.directory,\n fast_mode: true,\n path,\n recursive: true,\n });\n ({ uri } = await Filesystem.getUri({ directory: options.directory, path }));\n }\n else {\n recordDataBase64 = await VoiceRecorderImpl.blobToBase64(blobVoiceRecording);\n }\n const recordingDuration = await getBlobDuration(blobVoiceRecording);\n this.prepareInstanceForNextOperation();\n resolve({\n value: {\n recordDataBase64,\n mimeType: mt,\n fileExtension,\n msDuration: recordingDuration * 1000,\n uri\n }\n });\n };\n this.mediaRecorder.ondataavailable = (event) => this.chunks.push(event.data);\n this.mediaRecorder.start();\n });\n return successResponse();\n }\n /** Handles failures from getUserMedia. */\n onFailedToStartRecording() {\n this.prepareInstanceForNextOperation();\n throw failedToRecordError();\n }\n /** Converts a Blob payload into a base64 string. */\n static blobToBase64(blob) {\n return new Promise((resolve) => {\n const reader = new FileReader();\n reader.onloadend = () => {\n const recordingResult = String(reader.result);\n const splitResult = recordingResult.split('base64,');\n const toResolve = splitResult.length > 1 ? splitResult[1] : recordingResult;\n resolve(toResolve.trim());\n };\n reader.readAsDataURL(blob);\n });\n }\n /** Resets state for the next recording attempt. */\n prepareInstanceForNextOperation() {\n if (this.mediaRecorder != null && this.mediaRecorder.state === 'recording') {\n try {\n this.mediaRecorder.stop();\n }\n catch (ignore) {\n console.warn('Failed to stop recording during cleanup');\n }\n }\n this.pendingResult = neverResolvingPromise();\n this.mediaRecorder = null;\n this.chunks = [];\n }\n}\n/** Default behavior for web MIME selection: require recorder + playback support. */\nVoiceRecorderImpl.DEFAULT_REQUIRE_PLAYBACK_SUPPORT = true;\n//# sourceMappingURL=VoiceRecorderImpl.js.map","import { VoiceRecorderImpl } from '../platform/web/VoiceRecorderImpl';\n/** Web adapter that delegates to the browser-specific implementation. */\nexport class VoiceRecorderWebAdapter {\n constructor() {\n /** Browser implementation that talks to MediaRecorder APIs. */\n this.voiceRecorderImpl = new VoiceRecorderImpl();\n }\n /** Checks whether the browser can record audio. */\n canDeviceVoiceRecord() {\n return VoiceRecorderImpl.canDeviceVoiceRecord();\n }\n /** Returns whether the browser has microphone permission. */\n hasAudioRecordingPermission() {\n return VoiceRecorderImpl.hasAudioRecordingPermission();\n }\n /** Requests microphone permission through the browser. */\n requestAudioRecordingPermission() {\n return VoiceRecorderImpl.requestAudioRecordingPermission();\n }\n /** Starts a recording session using MediaRecorder. */\n startRecording(options) {\n return this.voiceRecorderImpl.startRecording(options);\n }\n /** Stops the recording session and returns the payload. */\n stopRecording() {\n return this.voiceRecorderImpl.stopRecording();\n }\n /** Pauses the recording session when supported. */\n pauseRecording() {\n return this.voiceRecorderImpl.pauseRecording();\n }\n /** Resumes a paused recording session when supported. */\n resumeRecording() {\n return this.voiceRecorderImpl.resumeRecording();\n }\n /** Returns the current recording state. */\n getCurrentStatus() {\n return this.voiceRecorderImpl.getCurrentStatus();\n }\n}\n//# sourceMappingURL=VoiceRecorderWebAdapter.js.map","/** Default response shape when no config is provided. */\nexport const DEFAULT_RESPONSE_FORMAT = 'legacy';\n/** Parses a user-provided response format into a supported value. */\nexport const resolveResponseFormat = (value) => {\n if (typeof value === 'string' && value.toLowerCase() === 'normalized') {\n return 'normalized';\n }\n return DEFAULT_RESPONSE_FORMAT;\n};\n/** Reads the response format from a Capacitor plugin config object. */\nexport const getResponseFormatFromConfig = (config) => {\n if (config && typeof config === 'object' && 'responseFormat' in config) {\n return resolveResponseFormat(config.responseFormat);\n }\n return DEFAULT_RESPONSE_FORMAT;\n};\n//# sourceMappingURL=response-format.js.map","/** Maps legacy error messages to canonical error codes. */\nconst legacyToCanonical = {\n CANNOT_RECORD_ON_THIS_PHONE: 'DEVICE_CANNOT_VOICE_RECORD',\n};\n/** Normalizes legacy error messages into canonical error codes. */\nexport const toCanonicalErrorCode = (legacyMessage) => {\n var _a;\n return (_a = legacyToCanonical[legacyMessage]) !== null && _a !== void 0 ? _a : legacyMessage;\n};\n/** Adds a canonical `code` field to Error-like objects when possible. */\nexport const attachCanonicalErrorCode = (error) => {\n if (!error || typeof error !== 'object') {\n return;\n }\n const messageValue = error.message;\n if (typeof messageValue !== 'string') {\n return;\n }\n error.code = toCanonicalErrorCode(messageValue);\n};\n//# sourceMappingURL=error-codes.js.map","/** Normalizes recording payloads into a stable contract shape. */\nexport const normalizeRecordingData = (data) => {\n const { recordDataBase64, uri, msDuration, mimeType, fileExtension } = data.value;\n const normalizedValue = { msDuration, mimeType, fileExtension };\n const trimmedUri = typeof uri === 'string' && uri.length > 0 ? uri : undefined;\n const trimmedBase64 = typeof recordDataBase64 === 'string' && recordDataBase64.length > 0 ? recordDataBase64 : undefined;\n if (trimmedUri) {\n normalizedValue.uri = trimmedUri;\n }\n else if (trimmedBase64) {\n normalizedValue.recordDataBase64 = trimmedBase64;\n }\n return { value: normalizedValue };\n};\n//# sourceMappingURL=recording-contract.js.map","import { attachCanonicalErrorCode } from '../core/error-codes';\nimport { normalizeRecordingData } from '../core/recording-contract';\n/** Orchestrates platform calls and normalizes responses when requested. */\nexport class VoiceRecorderService {\n constructor(platform, responseFormat) {\n this.platform = platform;\n this.responseFormat = responseFormat;\n }\n /** Checks whether the device can record audio. */\n canDeviceVoiceRecord() {\n return this.execute(() => this.platform.canDeviceVoiceRecord());\n }\n /** Returns whether microphone permission is currently granted. */\n hasAudioRecordingPermission() {\n return this.execute(() => this.platform.hasAudioRecordingPermission());\n }\n /** Requests microphone permission from the user. */\n requestAudioRecordingPermission() {\n return this.execute(() => this.platform.requestAudioRecordingPermission());\n }\n /** Starts a recording session. */\n startRecording(options) {\n return this.execute(() => this.platform.startRecording(options));\n }\n /** Stops the recording session and formats the payload if needed. */\n async stopRecording() {\n return this.execute(async () => {\n const data = await this.platform.stopRecording();\n if (this.responseFormat === 'normalized') {\n return normalizeRecordingData(data);\n }\n return data;\n });\n }\n /** Pauses the recording session when supported. */\n pauseRecording() {\n return this.execute(() => this.platform.pauseRecording());\n }\n /** Resumes a paused recording session when supported. */\n resumeRecording() {\n return this.execute(() => this.platform.resumeRecording());\n }\n /** Returns the current recording state. */\n getCurrentStatus() {\n return this.execute(() => this.platform.getCurrentStatus());\n }\n /** Wraps calls to apply canonical error codes when requested. */\n async execute(fn) {\n try {\n return await fn();\n }\n catch (error) {\n if (this.responseFormat === 'normalized') {\n attachCanonicalErrorCode(error);\n }\n throw error;\n }\n }\n}\n//# sourceMappingURL=VoiceRecorderService.js.map","import { Capacitor, WebPlugin } from '@capacitor/core';\nimport { VoiceRecorderWebAdapter } from './adapters/VoiceRecorderWebAdapter';\nimport { getResponseFormatFromConfig } from './core/response-format';\nimport { VoiceRecorderService } from './service/VoiceRecorderService';\n/** Web implementation of the VoiceRecorder Capacitor plugin. */\nexport class VoiceRecorderWeb extends WebPlugin {\n constructor() {\n var _a, _b;\n super();\n const pluginConfig = (_b = (_a = Capacitor === null || Capacitor === void 0 ? void 0 : Capacitor.config) === null || _a === void 0 ? void 0 : _a.plugins) === null || _b === void 0 ? void 0 : _b.VoiceRecorder;\n const responseFormat = getResponseFormatFromConfig(pluginConfig);\n this.service = new VoiceRecorderService(new VoiceRecorderWebAdapter(), responseFormat);\n }\n /** Checks whether the browser can record audio. */\n canDeviceVoiceRecord() {\n return this.service.canDeviceVoiceRecord();\n }\n /** Returns whether microphone permission is currently granted. */\n hasAudioRecordingPermission() {\n return this.service.hasAudioRecordingPermission();\n }\n /** Requests microphone permission from the user. */\n requestAudioRecordingPermission() {\n return this.service.requestAudioRecordingPermission();\n }\n /** Starts a recording session. */\n startRecording(options) {\n return this.service.startRecording(options);\n }\n /** Stops the current recording session and returns the payload. */\n stopRecording() {\n return this.service.stopRecording();\n }\n /** Pauses the recording session when supported. */\n pauseRecording() {\n return this.service.pauseRecording();\n }\n /** Resumes a paused recording session when supported. */\n resumeRecording() {\n return this.service.resumeRecording();\n }\n /** Returns the current recording state. */\n getCurrentStatus() {\n return this.service.getCurrentStatus();\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","Filesystem","WebPlugin","Capacitor"],"mappings":"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"}
|
|
@@ -7,6 +7,8 @@ struct RecordData {
|
|
|
7
7
|
public let recordDataBase64: String?
|
|
8
8
|
/// MIME type of the recorded audio.
|
|
9
9
|
public let mimeType: String
|
|
10
|
+
/// File extension / format without a leading dot (for example: aac, m4a, mp3).
|
|
11
|
+
public let fileExtension: String
|
|
10
12
|
/// Recording duration in milliseconds.
|
|
11
13
|
public let msDuration: Int
|
|
12
14
|
/// File path or URI to the recorded audio.
|
|
@@ -18,6 +20,7 @@ struct RecordData {
|
|
|
18
20
|
"recordDataBase64": recordDataBase64 ?? "",
|
|
19
21
|
"msDuration": msDuration,
|
|
20
22
|
"mimeType": mimeType,
|
|
23
|
+
"fileExtension": fileExtension,
|
|
21
24
|
"uri": uri ?? ""
|
|
22
25
|
]
|
|
23
26
|
}
|
package/package.json
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"url": "https://github.com/independo-gmbh/capacitor-voice-recorder.git"
|
|
14
14
|
},
|
|
15
15
|
"description": "Capacitor plugin for voice recording",
|
|
16
|
-
"version": "8.
|
|
16
|
+
"version": "8.2.0",
|
|
17
17
|
"packageManager": "pnpm@10.30.2",
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@capacitor/android": "catalog:",
|