@capgo/capacitor-audio-recorder 7.0.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/CapgoCapacitorAudioRecorder.podspec +17 -0
- package/LICENSE +21 -0
- package/Package.swift +28 -0
- package/README.md +359 -0
- package/android/build.gradle +57 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/app/capgo/audiorecorder/CapacitorAudioRecorderPlugin.java +285 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +646 -0
- package/dist/esm/definitions.d.ts +231 -0
- package/dist/esm/definitions.js +43 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +34 -0
- package/dist/esm/web.js +242 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +298 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +301 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/CapacitorAudioRecorderPlugin/CapacitorAudioRecorderPlugin.swift +321 -0
- package/ios/Tests/CapacitorAudioRecorderPluginTests/CapacitorAudioRecorderPluginTests.swift +9 -0
- package/package.json +89 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@capacitor/core');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The recording status.
|
|
7
|
+
*
|
|
8
|
+
* @since 1.0.0
|
|
9
|
+
*/
|
|
10
|
+
exports.RecordingStatus = void 0;
|
|
11
|
+
(function (RecordingStatus) {
|
|
12
|
+
RecordingStatus["Inactive"] = "INACTIVE";
|
|
13
|
+
RecordingStatus["Recording"] = "RECORDING";
|
|
14
|
+
RecordingStatus["Paused"] = "PAUSED";
|
|
15
|
+
})(exports.RecordingStatus || (exports.RecordingStatus = {}));
|
|
16
|
+
/**
|
|
17
|
+
* Audio session category options available on iOS.
|
|
18
|
+
*
|
|
19
|
+
* @since 1.0.0
|
|
20
|
+
*/
|
|
21
|
+
exports.AudioSessionCategoryOption = void 0;
|
|
22
|
+
(function (AudioSessionCategoryOption) {
|
|
23
|
+
AudioSessionCategoryOption["AllowAirPlay"] = "ALLOW_AIR_PLAY";
|
|
24
|
+
AudioSessionCategoryOption["AllowBluetooth"] = "ALLOW_BLUETOOTH";
|
|
25
|
+
AudioSessionCategoryOption["AllowBluetoothA2DP"] = "ALLOW_BLUETOOTH_A2DP";
|
|
26
|
+
AudioSessionCategoryOption["DefaultToSpeaker"] = "DEFAULT_TO_SPEAKER";
|
|
27
|
+
AudioSessionCategoryOption["DuckOthers"] = "DUCK_OTHERS";
|
|
28
|
+
AudioSessionCategoryOption["InterruptSpokenAudioAndMixWithOthers"] = "INTERRUPT_SPOKEN_AUDIO_AND_MIX_WITH_OTHERS";
|
|
29
|
+
AudioSessionCategoryOption["MixWithOthers"] = "MIX_WITH_OTHERS";
|
|
30
|
+
AudioSessionCategoryOption["OverrideMutedMicrophoneInterruption"] = "OVERRIDE_MUTED_MICROPHONE_INTERRUPTION";
|
|
31
|
+
})(exports.AudioSessionCategoryOption || (exports.AudioSessionCategoryOption = {}));
|
|
32
|
+
/**
|
|
33
|
+
* Audio session modes available on iOS.
|
|
34
|
+
*
|
|
35
|
+
* @since 1.0.0
|
|
36
|
+
*/
|
|
37
|
+
exports.AudioSessionMode = void 0;
|
|
38
|
+
(function (AudioSessionMode) {
|
|
39
|
+
AudioSessionMode["Default"] = "DEFAULT";
|
|
40
|
+
AudioSessionMode["GameChat"] = "GAME_CHAT";
|
|
41
|
+
AudioSessionMode["Measurement"] = "MEASUREMENT";
|
|
42
|
+
AudioSessionMode["SpokenAudio"] = "SPOKEN_AUDIO";
|
|
43
|
+
AudioSessionMode["VideoChat"] = "VIDEO_CHAT";
|
|
44
|
+
AudioSessionMode["VideoRecording"] = "VIDEO_RECORDING";
|
|
45
|
+
AudioSessionMode["VoiceChat"] = "VOICE_CHAT";
|
|
46
|
+
})(exports.AudioSessionMode || (exports.AudioSessionMode = {}));
|
|
47
|
+
|
|
48
|
+
const CapacitorAudioRecorder = core.registerPlugin('CapacitorAudioRecorder', {
|
|
49
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.CapacitorAudioRecorderWeb()),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
class CapacitorAudioRecorderWeb extends core.WebPlugin {
|
|
53
|
+
constructor() {
|
|
54
|
+
super(...arguments);
|
|
55
|
+
this.mediaRecorder = null;
|
|
56
|
+
this.mediaStream = null;
|
|
57
|
+
this.recordedChunks = [];
|
|
58
|
+
this.status = exports.RecordingStatus.Inactive;
|
|
59
|
+
this.startTimestamp = null;
|
|
60
|
+
this.pausedTimestamp = null;
|
|
61
|
+
this.accumulatedPauseDuration = 0;
|
|
62
|
+
this.stopResolver = null;
|
|
63
|
+
this.stopRejector = null;
|
|
64
|
+
}
|
|
65
|
+
async startRecording(_options) {
|
|
66
|
+
var _a, _b;
|
|
67
|
+
if (this.status === exports.RecordingStatus.Recording || this.status === exports.RecordingStatus.Paused) {
|
|
68
|
+
throw this.unavailable('Recording already in progress.');
|
|
69
|
+
}
|
|
70
|
+
await this.ensurePermission(true);
|
|
71
|
+
try {
|
|
72
|
+
this.mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
this.handleError(`Unable to acquire microphone: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
const mimeType = this.pickMimeType();
|
|
79
|
+
try {
|
|
80
|
+
this.mediaRecorder = new MediaRecorder(this.mediaStream, mimeType ? { mimeType } : undefined);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
this.cleanupMediaStream();
|
|
84
|
+
this.handleError(`Unable to initialise MediaRecorder: ${(_b = error === null || error === void 0 ? void 0 : error.message) !== null && _b !== void 0 ? _b : error}`);
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
this.recordedChunks = [];
|
|
88
|
+
this.startTimestamp = Date.now();
|
|
89
|
+
this.accumulatedPauseDuration = 0;
|
|
90
|
+
this.pausedTimestamp = null;
|
|
91
|
+
this.mediaRecorder.addEventListener('dataavailable', (event) => {
|
|
92
|
+
if (event.data.size > 0) {
|
|
93
|
+
this.recordedChunks.push(event.data);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
this.mediaRecorder.addEventListener('stop', () => {
|
|
97
|
+
const result = this.buildStopResult();
|
|
98
|
+
if (this.stopResolver) {
|
|
99
|
+
this.stopResolver(result);
|
|
100
|
+
}
|
|
101
|
+
this.notifyListeners('recordingStopped', result);
|
|
102
|
+
this.resetStopHandlers();
|
|
103
|
+
this.resetState();
|
|
104
|
+
});
|
|
105
|
+
this.mediaRecorder.addEventListener('error', (event) => {
|
|
106
|
+
var _a, _b;
|
|
107
|
+
const message = (_b = (_a = event === null || event === void 0 ? void 0 : event.error) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : 'Recording error.';
|
|
108
|
+
this.handleError(message);
|
|
109
|
+
if (this.stopRejector) {
|
|
110
|
+
this.stopRejector(new Error(message));
|
|
111
|
+
}
|
|
112
|
+
this.resetStopHandlers();
|
|
113
|
+
this.resetState();
|
|
114
|
+
});
|
|
115
|
+
this.mediaRecorder.start();
|
|
116
|
+
this.status = exports.RecordingStatus.Recording;
|
|
117
|
+
}
|
|
118
|
+
async pauseRecording() {
|
|
119
|
+
if (!this.mediaRecorder || this.status !== exports.RecordingStatus.Recording) {
|
|
120
|
+
throw this.unavailable('No active recording to pause.');
|
|
121
|
+
}
|
|
122
|
+
if (this.supportsRecorderPause()) {
|
|
123
|
+
this.mediaRecorder.pause();
|
|
124
|
+
this.status = exports.RecordingStatus.Paused;
|
|
125
|
+
this.pausedTimestamp = Date.now();
|
|
126
|
+
this.notifyListeners('recordingPaused', {});
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
throw this.unavailable('Pausing recordings is not supported in this browser.');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async resumeRecording() {
|
|
133
|
+
if (!this.mediaRecorder || this.status !== exports.RecordingStatus.Paused) {
|
|
134
|
+
throw this.unavailable('No paused recording to resume.');
|
|
135
|
+
}
|
|
136
|
+
if (this.supportsRecorderPause()) {
|
|
137
|
+
this.mediaRecorder.resume();
|
|
138
|
+
if (this.pausedTimestamp) {
|
|
139
|
+
this.accumulatedPauseDuration += Date.now() - this.pausedTimestamp;
|
|
140
|
+
}
|
|
141
|
+
this.pausedTimestamp = null;
|
|
142
|
+
this.status = exports.RecordingStatus.Recording;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
throw this.unavailable('Resuming recordings is not supported in this browser.');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async stopRecording() {
|
|
149
|
+
var _a;
|
|
150
|
+
if (!this.mediaRecorder || this.status === exports.RecordingStatus.Inactive) {
|
|
151
|
+
throw this.unavailable('No active recording to stop.');
|
|
152
|
+
}
|
|
153
|
+
if (this.status === exports.RecordingStatus.Paused && this.pausedTimestamp) {
|
|
154
|
+
this.accumulatedPauseDuration += Date.now() - this.pausedTimestamp;
|
|
155
|
+
this.pausedTimestamp = null;
|
|
156
|
+
}
|
|
157
|
+
const stopPromise = new Promise((resolve, reject) => {
|
|
158
|
+
this.stopResolver = resolve;
|
|
159
|
+
this.stopRejector = reject;
|
|
160
|
+
});
|
|
161
|
+
try {
|
|
162
|
+
this.mediaRecorder.stop();
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
this.resetStopHandlers();
|
|
166
|
+
this.resetState();
|
|
167
|
+
this.handleError(`Unable to stop recorder: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
return stopPromise;
|
|
171
|
+
}
|
|
172
|
+
async cancelRecording() {
|
|
173
|
+
if (!this.mediaRecorder || this.status === exports.RecordingStatus.Inactive) {
|
|
174
|
+
this.resetState();
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
try {
|
|
178
|
+
this.mediaRecorder.stop();
|
|
179
|
+
}
|
|
180
|
+
catch (_a) {
|
|
181
|
+
// Ignored.
|
|
182
|
+
}
|
|
183
|
+
this.resetStopHandlers();
|
|
184
|
+
this.resetState();
|
|
185
|
+
}
|
|
186
|
+
async getRecordingStatus() {
|
|
187
|
+
return { status: this.status };
|
|
188
|
+
}
|
|
189
|
+
async checkPermissions() {
|
|
190
|
+
const state = await this.getPermissionState();
|
|
191
|
+
return { recordAudio: state };
|
|
192
|
+
}
|
|
193
|
+
async requestPermissions() {
|
|
194
|
+
const state = await this.ensurePermission(true);
|
|
195
|
+
return { recordAudio: state };
|
|
196
|
+
}
|
|
197
|
+
async addListener(eventName, listenerFunc) {
|
|
198
|
+
return super.addListener(eventName, listenerFunc);
|
|
199
|
+
}
|
|
200
|
+
async removeAllListeners() {
|
|
201
|
+
await super.removeAllListeners();
|
|
202
|
+
}
|
|
203
|
+
// Helpers
|
|
204
|
+
supportsRecorderPause() {
|
|
205
|
+
return !!this.mediaRecorder && typeof this.mediaRecorder.pause === 'function' && typeof this.mediaRecorder.resume === 'function';
|
|
206
|
+
}
|
|
207
|
+
pickMimeType() {
|
|
208
|
+
const preferred = ['audio/webm;codecs=opus', 'audio/ogg;codecs=opus', 'audio/mp4'];
|
|
209
|
+
for (const type of preferred) {
|
|
210
|
+
if (window.MediaRecorder && MediaRecorder.isTypeSupported && MediaRecorder.isTypeSupported(type)) {
|
|
211
|
+
return type;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return undefined;
|
|
215
|
+
}
|
|
216
|
+
buildStopResult() {
|
|
217
|
+
const blob = this.recordedChunks.length > 0 ? new Blob(this.recordedChunks, { type: this.pickMimeType() || 'audio/webm' }) : undefined;
|
|
218
|
+
let duration;
|
|
219
|
+
if (this.startTimestamp) {
|
|
220
|
+
duration = Date.now() - this.startTimestamp - this.accumulatedPauseDuration;
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
blob,
|
|
224
|
+
duration,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
resetStopHandlers() {
|
|
228
|
+
this.stopResolver = null;
|
|
229
|
+
this.stopRejector = null;
|
|
230
|
+
}
|
|
231
|
+
resetState() {
|
|
232
|
+
this.status = exports.RecordingStatus.Inactive;
|
|
233
|
+
this.startTimestamp = null;
|
|
234
|
+
this.pausedTimestamp = null;
|
|
235
|
+
this.accumulatedPauseDuration = 0;
|
|
236
|
+
this.recordedChunks = [];
|
|
237
|
+
this.cleanupMediaStream();
|
|
238
|
+
if (this.mediaRecorder) {
|
|
239
|
+
const recorder = this.mediaRecorder;
|
|
240
|
+
recorder.ondataavailable = null;
|
|
241
|
+
recorder.onstop = null;
|
|
242
|
+
recorder.onerror = null;
|
|
243
|
+
}
|
|
244
|
+
this.mediaRecorder = null;
|
|
245
|
+
}
|
|
246
|
+
cleanupMediaStream() {
|
|
247
|
+
if (this.mediaStream) {
|
|
248
|
+
this.mediaStream.getTracks().forEach((track) => track.stop());
|
|
249
|
+
}
|
|
250
|
+
this.mediaStream = null;
|
|
251
|
+
}
|
|
252
|
+
async ensurePermission(request) {
|
|
253
|
+
const currentState = await this.getPermissionState();
|
|
254
|
+
if (currentState === 'granted' || !request) {
|
|
255
|
+
return currentState;
|
|
256
|
+
}
|
|
257
|
+
try {
|
|
258
|
+
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
259
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
260
|
+
return 'granted';
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
return 'denied';
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
async getPermissionState() {
|
|
267
|
+
var _a;
|
|
268
|
+
if (!((_a = navigator.permissions) === null || _a === void 0 ? void 0 : _a.query)) {
|
|
269
|
+
return 'prompt';
|
|
270
|
+
}
|
|
271
|
+
try {
|
|
272
|
+
const result = await navigator.permissions.query({ name: 'microphone' });
|
|
273
|
+
switch (result.state) {
|
|
274
|
+
case 'granted':
|
|
275
|
+
return 'granted';
|
|
276
|
+
case 'denied':
|
|
277
|
+
return 'denied';
|
|
278
|
+
default:
|
|
279
|
+
return 'prompt';
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
catch (_b) {
|
|
283
|
+
return 'prompt';
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
handleError(message) {
|
|
287
|
+
this.status = exports.RecordingStatus.Inactive;
|
|
288
|
+
this.notifyListeners('recordingError', { message });
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
293
|
+
__proto__: null,
|
|
294
|
+
CapacitorAudioRecorderWeb: CapacitorAudioRecorderWeb
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
exports.CapacitorAudioRecorder = CapacitorAudioRecorder;
|
|
298
|
+
//# sourceMappingURL=plugin.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/definitions.js","esm/index.js","esm/web.js"],"sourcesContent":["/**\n * The recording status.\n *\n * @since 1.0.0\n */\nexport var RecordingStatus;\n(function (RecordingStatus) {\n RecordingStatus[\"Inactive\"] = \"INACTIVE\";\n RecordingStatus[\"Recording\"] = \"RECORDING\";\n RecordingStatus[\"Paused\"] = \"PAUSED\";\n})(RecordingStatus || (RecordingStatus = {}));\n/**\n * Audio session category options available on iOS.\n *\n * @since 1.0.0\n */\nexport var AudioSessionCategoryOption;\n(function (AudioSessionCategoryOption) {\n AudioSessionCategoryOption[\"AllowAirPlay\"] = \"ALLOW_AIR_PLAY\";\n AudioSessionCategoryOption[\"AllowBluetooth\"] = \"ALLOW_BLUETOOTH\";\n AudioSessionCategoryOption[\"AllowBluetoothA2DP\"] = \"ALLOW_BLUETOOTH_A2DP\";\n AudioSessionCategoryOption[\"DefaultToSpeaker\"] = \"DEFAULT_TO_SPEAKER\";\n AudioSessionCategoryOption[\"DuckOthers\"] = \"DUCK_OTHERS\";\n AudioSessionCategoryOption[\"InterruptSpokenAudioAndMixWithOthers\"] = \"INTERRUPT_SPOKEN_AUDIO_AND_MIX_WITH_OTHERS\";\n AudioSessionCategoryOption[\"MixWithOthers\"] = \"MIX_WITH_OTHERS\";\n AudioSessionCategoryOption[\"OverrideMutedMicrophoneInterruption\"] = \"OVERRIDE_MUTED_MICROPHONE_INTERRUPTION\";\n})(AudioSessionCategoryOption || (AudioSessionCategoryOption = {}));\n/**\n * Audio session modes available on iOS.\n *\n * @since 1.0.0\n */\nexport var AudioSessionMode;\n(function (AudioSessionMode) {\n AudioSessionMode[\"Default\"] = \"DEFAULT\";\n AudioSessionMode[\"GameChat\"] = \"GAME_CHAT\";\n AudioSessionMode[\"Measurement\"] = \"MEASUREMENT\";\n AudioSessionMode[\"SpokenAudio\"] = \"SPOKEN_AUDIO\";\n AudioSessionMode[\"VideoChat\"] = \"VIDEO_CHAT\";\n AudioSessionMode[\"VideoRecording\"] = \"VIDEO_RECORDING\";\n AudioSessionMode[\"VoiceChat\"] = \"VOICE_CHAT\";\n})(AudioSessionMode || (AudioSessionMode = {}));\n//# sourceMappingURL=definitions.js.map","import { registerPlugin } from '@capacitor/core';\nconst CapacitorAudioRecorder = registerPlugin('CapacitorAudioRecorder', {\n web: () => import('./web').then((m) => new m.CapacitorAudioRecorderWeb()),\n});\nexport * from './definitions';\nexport { CapacitorAudioRecorder };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nimport { RecordingStatus, } from './definitions';\nexport class CapacitorAudioRecorderWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.mediaRecorder = null;\n this.mediaStream = null;\n this.recordedChunks = [];\n this.status = RecordingStatus.Inactive;\n this.startTimestamp = null;\n this.pausedTimestamp = null;\n this.accumulatedPauseDuration = 0;\n this.stopResolver = null;\n this.stopRejector = null;\n }\n async startRecording(_options) {\n var _a, _b;\n if (this.status === RecordingStatus.Recording || this.status === RecordingStatus.Paused) {\n throw this.unavailable('Recording already in progress.');\n }\n await this.ensurePermission(true);\n try {\n this.mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });\n }\n catch (error) {\n this.handleError(`Unable to acquire microphone: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);\n throw error;\n }\n const mimeType = this.pickMimeType();\n try {\n this.mediaRecorder = new MediaRecorder(this.mediaStream, mimeType ? { mimeType } : undefined);\n }\n catch (error) {\n this.cleanupMediaStream();\n this.handleError(`Unable to initialise MediaRecorder: ${(_b = error === null || error === void 0 ? void 0 : error.message) !== null && _b !== void 0 ? _b : error}`);\n throw error;\n }\n this.recordedChunks = [];\n this.startTimestamp = Date.now();\n this.accumulatedPauseDuration = 0;\n this.pausedTimestamp = null;\n this.mediaRecorder.addEventListener('dataavailable', (event) => {\n if (event.data.size > 0) {\n this.recordedChunks.push(event.data);\n }\n });\n this.mediaRecorder.addEventListener('stop', () => {\n const result = this.buildStopResult();\n if (this.stopResolver) {\n this.stopResolver(result);\n }\n this.notifyListeners('recordingStopped', result);\n this.resetStopHandlers();\n this.resetState();\n });\n this.mediaRecorder.addEventListener('error', (event) => {\n var _a, _b;\n const message = (_b = (_a = event === null || event === void 0 ? void 0 : event.error) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : 'Recording error.';\n this.handleError(message);\n if (this.stopRejector) {\n this.stopRejector(new Error(message));\n }\n this.resetStopHandlers();\n this.resetState();\n });\n this.mediaRecorder.start();\n this.status = RecordingStatus.Recording;\n }\n async pauseRecording() {\n if (!this.mediaRecorder || this.status !== RecordingStatus.Recording) {\n throw this.unavailable('No active recording to pause.');\n }\n if (this.supportsRecorderPause()) {\n this.mediaRecorder.pause();\n this.status = RecordingStatus.Paused;\n this.pausedTimestamp = Date.now();\n this.notifyListeners('recordingPaused', {});\n }\n else {\n throw this.unavailable('Pausing recordings is not supported in this browser.');\n }\n }\n async resumeRecording() {\n if (!this.mediaRecorder || this.status !== RecordingStatus.Paused) {\n throw this.unavailable('No paused recording to resume.');\n }\n if (this.supportsRecorderPause()) {\n this.mediaRecorder.resume();\n if (this.pausedTimestamp) {\n this.accumulatedPauseDuration += Date.now() - this.pausedTimestamp;\n }\n this.pausedTimestamp = null;\n this.status = RecordingStatus.Recording;\n }\n else {\n throw this.unavailable('Resuming recordings is not supported in this browser.');\n }\n }\n async stopRecording() {\n var _a;\n if (!this.mediaRecorder || this.status === RecordingStatus.Inactive) {\n throw this.unavailable('No active recording to stop.');\n }\n if (this.status === RecordingStatus.Paused && this.pausedTimestamp) {\n this.accumulatedPauseDuration += Date.now() - this.pausedTimestamp;\n this.pausedTimestamp = null;\n }\n const stopPromise = new Promise((resolve, reject) => {\n this.stopResolver = resolve;\n this.stopRejector = reject;\n });\n try {\n this.mediaRecorder.stop();\n }\n catch (error) {\n this.resetStopHandlers();\n this.resetState();\n this.handleError(`Unable to stop recorder: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);\n throw error;\n }\n return stopPromise;\n }\n async cancelRecording() {\n if (!this.mediaRecorder || this.status === RecordingStatus.Inactive) {\n this.resetState();\n return;\n }\n try {\n this.mediaRecorder.stop();\n }\n catch (_a) {\n // Ignored.\n }\n this.resetStopHandlers();\n this.resetState();\n }\n async getRecordingStatus() {\n return { status: this.status };\n }\n async checkPermissions() {\n const state = await this.getPermissionState();\n return { recordAudio: state };\n }\n async requestPermissions() {\n const state = await this.ensurePermission(true);\n return { recordAudio: state };\n }\n async addListener(eventName, listenerFunc) {\n return super.addListener(eventName, listenerFunc);\n }\n async removeAllListeners() {\n await super.removeAllListeners();\n }\n // Helpers\n supportsRecorderPause() {\n return !!this.mediaRecorder && typeof this.mediaRecorder.pause === 'function' && typeof this.mediaRecorder.resume === 'function';\n }\n pickMimeType() {\n const preferred = ['audio/webm;codecs=opus', 'audio/ogg;codecs=opus', 'audio/mp4'];\n for (const type of preferred) {\n if (window.MediaRecorder && MediaRecorder.isTypeSupported && MediaRecorder.isTypeSupported(type)) {\n return type;\n }\n }\n return undefined;\n }\n buildStopResult() {\n const blob = this.recordedChunks.length > 0 ? new Blob(this.recordedChunks, { type: this.pickMimeType() || 'audio/webm' }) : undefined;\n let duration;\n if (this.startTimestamp) {\n duration = Date.now() - this.startTimestamp - this.accumulatedPauseDuration;\n }\n return {\n blob,\n duration,\n };\n }\n resetStopHandlers() {\n this.stopResolver = null;\n this.stopRejector = null;\n }\n resetState() {\n this.status = RecordingStatus.Inactive;\n this.startTimestamp = null;\n this.pausedTimestamp = null;\n this.accumulatedPauseDuration = 0;\n this.recordedChunks = [];\n this.cleanupMediaStream();\n if (this.mediaRecorder) {\n const recorder = this.mediaRecorder;\n recorder.ondataavailable = null;\n recorder.onstop = null;\n recorder.onerror = null;\n }\n this.mediaRecorder = null;\n }\n cleanupMediaStream() {\n if (this.mediaStream) {\n this.mediaStream.getTracks().forEach((track) => track.stop());\n }\n this.mediaStream = null;\n }\n async ensurePermission(request) {\n const currentState = await this.getPermissionState();\n if (currentState === 'granted' || !request) {\n return currentState;\n }\n try {\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n stream.getTracks().forEach((track) => track.stop());\n return 'granted';\n }\n catch (error) {\n return 'denied';\n }\n }\n async getPermissionState() {\n var _a;\n if (!((_a = navigator.permissions) === null || _a === void 0 ? void 0 : _a.query)) {\n return 'prompt';\n }\n try {\n const result = await navigator.permissions.query({ name: 'microphone' });\n switch (result.state) {\n case 'granted':\n return 'granted';\n case 'denied':\n return 'denied';\n default:\n return 'prompt';\n }\n }\n catch (_b) {\n return 'prompt';\n }\n }\n handleError(message) {\n this.status = RecordingStatus.Inactive;\n this.notifyListeners('recordingError', { message });\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["RecordingStatus","AudioSessionCategoryOption","AudioSessionMode","registerPlugin","WebPlugin"],"mappings":"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"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
var capacitorCapacitorAudioRecorder = (function (exports, core) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The recording status.
|
|
6
|
+
*
|
|
7
|
+
* @since 1.0.0
|
|
8
|
+
*/
|
|
9
|
+
exports.RecordingStatus = void 0;
|
|
10
|
+
(function (RecordingStatus) {
|
|
11
|
+
RecordingStatus["Inactive"] = "INACTIVE";
|
|
12
|
+
RecordingStatus["Recording"] = "RECORDING";
|
|
13
|
+
RecordingStatus["Paused"] = "PAUSED";
|
|
14
|
+
})(exports.RecordingStatus || (exports.RecordingStatus = {}));
|
|
15
|
+
/**
|
|
16
|
+
* Audio session category options available on iOS.
|
|
17
|
+
*
|
|
18
|
+
* @since 1.0.0
|
|
19
|
+
*/
|
|
20
|
+
exports.AudioSessionCategoryOption = void 0;
|
|
21
|
+
(function (AudioSessionCategoryOption) {
|
|
22
|
+
AudioSessionCategoryOption["AllowAirPlay"] = "ALLOW_AIR_PLAY";
|
|
23
|
+
AudioSessionCategoryOption["AllowBluetooth"] = "ALLOW_BLUETOOTH";
|
|
24
|
+
AudioSessionCategoryOption["AllowBluetoothA2DP"] = "ALLOW_BLUETOOTH_A2DP";
|
|
25
|
+
AudioSessionCategoryOption["DefaultToSpeaker"] = "DEFAULT_TO_SPEAKER";
|
|
26
|
+
AudioSessionCategoryOption["DuckOthers"] = "DUCK_OTHERS";
|
|
27
|
+
AudioSessionCategoryOption["InterruptSpokenAudioAndMixWithOthers"] = "INTERRUPT_SPOKEN_AUDIO_AND_MIX_WITH_OTHERS";
|
|
28
|
+
AudioSessionCategoryOption["MixWithOthers"] = "MIX_WITH_OTHERS";
|
|
29
|
+
AudioSessionCategoryOption["OverrideMutedMicrophoneInterruption"] = "OVERRIDE_MUTED_MICROPHONE_INTERRUPTION";
|
|
30
|
+
})(exports.AudioSessionCategoryOption || (exports.AudioSessionCategoryOption = {}));
|
|
31
|
+
/**
|
|
32
|
+
* Audio session modes available on iOS.
|
|
33
|
+
*
|
|
34
|
+
* @since 1.0.0
|
|
35
|
+
*/
|
|
36
|
+
exports.AudioSessionMode = void 0;
|
|
37
|
+
(function (AudioSessionMode) {
|
|
38
|
+
AudioSessionMode["Default"] = "DEFAULT";
|
|
39
|
+
AudioSessionMode["GameChat"] = "GAME_CHAT";
|
|
40
|
+
AudioSessionMode["Measurement"] = "MEASUREMENT";
|
|
41
|
+
AudioSessionMode["SpokenAudio"] = "SPOKEN_AUDIO";
|
|
42
|
+
AudioSessionMode["VideoChat"] = "VIDEO_CHAT";
|
|
43
|
+
AudioSessionMode["VideoRecording"] = "VIDEO_RECORDING";
|
|
44
|
+
AudioSessionMode["VoiceChat"] = "VOICE_CHAT";
|
|
45
|
+
})(exports.AudioSessionMode || (exports.AudioSessionMode = {}));
|
|
46
|
+
|
|
47
|
+
const CapacitorAudioRecorder = core.registerPlugin('CapacitorAudioRecorder', {
|
|
48
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.CapacitorAudioRecorderWeb()),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
class CapacitorAudioRecorderWeb extends core.WebPlugin {
|
|
52
|
+
constructor() {
|
|
53
|
+
super(...arguments);
|
|
54
|
+
this.mediaRecorder = null;
|
|
55
|
+
this.mediaStream = null;
|
|
56
|
+
this.recordedChunks = [];
|
|
57
|
+
this.status = exports.RecordingStatus.Inactive;
|
|
58
|
+
this.startTimestamp = null;
|
|
59
|
+
this.pausedTimestamp = null;
|
|
60
|
+
this.accumulatedPauseDuration = 0;
|
|
61
|
+
this.stopResolver = null;
|
|
62
|
+
this.stopRejector = null;
|
|
63
|
+
}
|
|
64
|
+
async startRecording(_options) {
|
|
65
|
+
var _a, _b;
|
|
66
|
+
if (this.status === exports.RecordingStatus.Recording || this.status === exports.RecordingStatus.Paused) {
|
|
67
|
+
throw this.unavailable('Recording already in progress.');
|
|
68
|
+
}
|
|
69
|
+
await this.ensurePermission(true);
|
|
70
|
+
try {
|
|
71
|
+
this.mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
this.handleError(`Unable to acquire microphone: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
const mimeType = this.pickMimeType();
|
|
78
|
+
try {
|
|
79
|
+
this.mediaRecorder = new MediaRecorder(this.mediaStream, mimeType ? { mimeType } : undefined);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
this.cleanupMediaStream();
|
|
83
|
+
this.handleError(`Unable to initialise MediaRecorder: ${(_b = error === null || error === void 0 ? void 0 : error.message) !== null && _b !== void 0 ? _b : error}`);
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
this.recordedChunks = [];
|
|
87
|
+
this.startTimestamp = Date.now();
|
|
88
|
+
this.accumulatedPauseDuration = 0;
|
|
89
|
+
this.pausedTimestamp = null;
|
|
90
|
+
this.mediaRecorder.addEventListener('dataavailable', (event) => {
|
|
91
|
+
if (event.data.size > 0) {
|
|
92
|
+
this.recordedChunks.push(event.data);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
this.mediaRecorder.addEventListener('stop', () => {
|
|
96
|
+
const result = this.buildStopResult();
|
|
97
|
+
if (this.stopResolver) {
|
|
98
|
+
this.stopResolver(result);
|
|
99
|
+
}
|
|
100
|
+
this.notifyListeners('recordingStopped', result);
|
|
101
|
+
this.resetStopHandlers();
|
|
102
|
+
this.resetState();
|
|
103
|
+
});
|
|
104
|
+
this.mediaRecorder.addEventListener('error', (event) => {
|
|
105
|
+
var _a, _b;
|
|
106
|
+
const message = (_b = (_a = event === null || event === void 0 ? void 0 : event.error) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : 'Recording error.';
|
|
107
|
+
this.handleError(message);
|
|
108
|
+
if (this.stopRejector) {
|
|
109
|
+
this.stopRejector(new Error(message));
|
|
110
|
+
}
|
|
111
|
+
this.resetStopHandlers();
|
|
112
|
+
this.resetState();
|
|
113
|
+
});
|
|
114
|
+
this.mediaRecorder.start();
|
|
115
|
+
this.status = exports.RecordingStatus.Recording;
|
|
116
|
+
}
|
|
117
|
+
async pauseRecording() {
|
|
118
|
+
if (!this.mediaRecorder || this.status !== exports.RecordingStatus.Recording) {
|
|
119
|
+
throw this.unavailable('No active recording to pause.');
|
|
120
|
+
}
|
|
121
|
+
if (this.supportsRecorderPause()) {
|
|
122
|
+
this.mediaRecorder.pause();
|
|
123
|
+
this.status = exports.RecordingStatus.Paused;
|
|
124
|
+
this.pausedTimestamp = Date.now();
|
|
125
|
+
this.notifyListeners('recordingPaused', {});
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
throw this.unavailable('Pausing recordings is not supported in this browser.');
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async resumeRecording() {
|
|
132
|
+
if (!this.mediaRecorder || this.status !== exports.RecordingStatus.Paused) {
|
|
133
|
+
throw this.unavailable('No paused recording to resume.');
|
|
134
|
+
}
|
|
135
|
+
if (this.supportsRecorderPause()) {
|
|
136
|
+
this.mediaRecorder.resume();
|
|
137
|
+
if (this.pausedTimestamp) {
|
|
138
|
+
this.accumulatedPauseDuration += Date.now() - this.pausedTimestamp;
|
|
139
|
+
}
|
|
140
|
+
this.pausedTimestamp = null;
|
|
141
|
+
this.status = exports.RecordingStatus.Recording;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
throw this.unavailable('Resuming recordings is not supported in this browser.');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async stopRecording() {
|
|
148
|
+
var _a;
|
|
149
|
+
if (!this.mediaRecorder || this.status === exports.RecordingStatus.Inactive) {
|
|
150
|
+
throw this.unavailable('No active recording to stop.');
|
|
151
|
+
}
|
|
152
|
+
if (this.status === exports.RecordingStatus.Paused && this.pausedTimestamp) {
|
|
153
|
+
this.accumulatedPauseDuration += Date.now() - this.pausedTimestamp;
|
|
154
|
+
this.pausedTimestamp = null;
|
|
155
|
+
}
|
|
156
|
+
const stopPromise = new Promise((resolve, reject) => {
|
|
157
|
+
this.stopResolver = resolve;
|
|
158
|
+
this.stopRejector = reject;
|
|
159
|
+
});
|
|
160
|
+
try {
|
|
161
|
+
this.mediaRecorder.stop();
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
this.resetStopHandlers();
|
|
165
|
+
this.resetState();
|
|
166
|
+
this.handleError(`Unable to stop recorder: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
return stopPromise;
|
|
170
|
+
}
|
|
171
|
+
async cancelRecording() {
|
|
172
|
+
if (!this.mediaRecorder || this.status === exports.RecordingStatus.Inactive) {
|
|
173
|
+
this.resetState();
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
this.mediaRecorder.stop();
|
|
178
|
+
}
|
|
179
|
+
catch (_a) {
|
|
180
|
+
// Ignored.
|
|
181
|
+
}
|
|
182
|
+
this.resetStopHandlers();
|
|
183
|
+
this.resetState();
|
|
184
|
+
}
|
|
185
|
+
async getRecordingStatus() {
|
|
186
|
+
return { status: this.status };
|
|
187
|
+
}
|
|
188
|
+
async checkPermissions() {
|
|
189
|
+
const state = await this.getPermissionState();
|
|
190
|
+
return { recordAudio: state };
|
|
191
|
+
}
|
|
192
|
+
async requestPermissions() {
|
|
193
|
+
const state = await this.ensurePermission(true);
|
|
194
|
+
return { recordAudio: state };
|
|
195
|
+
}
|
|
196
|
+
async addListener(eventName, listenerFunc) {
|
|
197
|
+
return super.addListener(eventName, listenerFunc);
|
|
198
|
+
}
|
|
199
|
+
async removeAllListeners() {
|
|
200
|
+
await super.removeAllListeners();
|
|
201
|
+
}
|
|
202
|
+
// Helpers
|
|
203
|
+
supportsRecorderPause() {
|
|
204
|
+
return !!this.mediaRecorder && typeof this.mediaRecorder.pause === 'function' && typeof this.mediaRecorder.resume === 'function';
|
|
205
|
+
}
|
|
206
|
+
pickMimeType() {
|
|
207
|
+
const preferred = ['audio/webm;codecs=opus', 'audio/ogg;codecs=opus', 'audio/mp4'];
|
|
208
|
+
for (const type of preferred) {
|
|
209
|
+
if (window.MediaRecorder && MediaRecorder.isTypeSupported && MediaRecorder.isTypeSupported(type)) {
|
|
210
|
+
return type;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return undefined;
|
|
214
|
+
}
|
|
215
|
+
buildStopResult() {
|
|
216
|
+
const blob = this.recordedChunks.length > 0 ? new Blob(this.recordedChunks, { type: this.pickMimeType() || 'audio/webm' }) : undefined;
|
|
217
|
+
let duration;
|
|
218
|
+
if (this.startTimestamp) {
|
|
219
|
+
duration = Date.now() - this.startTimestamp - this.accumulatedPauseDuration;
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
blob,
|
|
223
|
+
duration,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
resetStopHandlers() {
|
|
227
|
+
this.stopResolver = null;
|
|
228
|
+
this.stopRejector = null;
|
|
229
|
+
}
|
|
230
|
+
resetState() {
|
|
231
|
+
this.status = exports.RecordingStatus.Inactive;
|
|
232
|
+
this.startTimestamp = null;
|
|
233
|
+
this.pausedTimestamp = null;
|
|
234
|
+
this.accumulatedPauseDuration = 0;
|
|
235
|
+
this.recordedChunks = [];
|
|
236
|
+
this.cleanupMediaStream();
|
|
237
|
+
if (this.mediaRecorder) {
|
|
238
|
+
const recorder = this.mediaRecorder;
|
|
239
|
+
recorder.ondataavailable = null;
|
|
240
|
+
recorder.onstop = null;
|
|
241
|
+
recorder.onerror = null;
|
|
242
|
+
}
|
|
243
|
+
this.mediaRecorder = null;
|
|
244
|
+
}
|
|
245
|
+
cleanupMediaStream() {
|
|
246
|
+
if (this.mediaStream) {
|
|
247
|
+
this.mediaStream.getTracks().forEach((track) => track.stop());
|
|
248
|
+
}
|
|
249
|
+
this.mediaStream = null;
|
|
250
|
+
}
|
|
251
|
+
async ensurePermission(request) {
|
|
252
|
+
const currentState = await this.getPermissionState();
|
|
253
|
+
if (currentState === 'granted' || !request) {
|
|
254
|
+
return currentState;
|
|
255
|
+
}
|
|
256
|
+
try {
|
|
257
|
+
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
258
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
259
|
+
return 'granted';
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
return 'denied';
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
async getPermissionState() {
|
|
266
|
+
var _a;
|
|
267
|
+
if (!((_a = navigator.permissions) === null || _a === void 0 ? void 0 : _a.query)) {
|
|
268
|
+
return 'prompt';
|
|
269
|
+
}
|
|
270
|
+
try {
|
|
271
|
+
const result = await navigator.permissions.query({ name: 'microphone' });
|
|
272
|
+
switch (result.state) {
|
|
273
|
+
case 'granted':
|
|
274
|
+
return 'granted';
|
|
275
|
+
case 'denied':
|
|
276
|
+
return 'denied';
|
|
277
|
+
default:
|
|
278
|
+
return 'prompt';
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
catch (_b) {
|
|
282
|
+
return 'prompt';
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
handleError(message) {
|
|
286
|
+
this.status = exports.RecordingStatus.Inactive;
|
|
287
|
+
this.notifyListeners('recordingError', { message });
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
292
|
+
__proto__: null,
|
|
293
|
+
CapacitorAudioRecorderWeb: CapacitorAudioRecorderWeb
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
exports.CapacitorAudioRecorder = CapacitorAudioRecorder;
|
|
297
|
+
|
|
298
|
+
return exports;
|
|
299
|
+
|
|
300
|
+
})({}, capacitorExports);
|
|
301
|
+
//# sourceMappingURL=plugin.js.map
|