@independo/capacitor-voice-recorder 8.2.12 → 8.3.0-dev.1

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.
Files changed (29) hide show
  1. package/README.md +31 -0
  2. package/android/src/main/java/app/independo/capacitorvoicerecorder/VoiceRecorder.java +6 -0
  3. package/android/src/main/java/app/independo/capacitorvoicerecorder/adapters/RecorderAdapter.java +3 -0
  4. package/android/src/main/java/app/independo/capacitorvoicerecorder/platform/CustomMediaRecorder.java +24 -0
  5. package/android/src/main/java/app/independo/capacitorvoicerecorder/service/VoiceRecorderService.java +8 -0
  6. package/dist/docs.json +33 -0
  7. package/dist/esm/adapters/VoiceRecorderWebAdapter.d.ts +3 -1
  8. package/dist/esm/adapters/VoiceRecorderWebAdapter.js +4 -0
  9. package/dist/esm/adapters/VoiceRecorderWebAdapter.js.map +1 -1
  10. package/dist/esm/definitions.d.ts +23 -0
  11. package/dist/esm/definitions.js.map +1 -1
  12. package/dist/esm/platform/web/VoiceRecorderImpl.d.ts +15 -1
  13. package/dist/esm/platform/web/VoiceRecorderImpl.js +68 -0
  14. package/dist/esm/platform/web/VoiceRecorderImpl.js.map +1 -1
  15. package/dist/esm/service/VoiceRecorderService.d.ts +5 -1
  16. package/dist/esm/service/VoiceRecorderService.js +4 -0
  17. package/dist/esm/service/VoiceRecorderService.js.map +1 -1
  18. package/dist/esm/web.d.ts +3 -1
  19. package/dist/esm/web.js +4 -0
  20. package/dist/esm/web.js.map +1 -1
  21. package/dist/plugin.cjs.js +80 -0
  22. package/dist/plugin.cjs.js.map +1 -1
  23. package/dist/plugin.js +80 -0
  24. package/dist/plugin.js.map +1 -1
  25. package/ios/Sources/VoiceRecorder/Adapters/RecorderAdapter.swift +2 -0
  26. package/ios/Sources/VoiceRecorder/Bridge/VoiceRecorder.swift +6 -0
  27. package/ios/Sources/VoiceRecorder/Platform/CustomMediaRecorder.swift +27 -0
  28. package/ios/Sources/VoiceRecorder/Service/VoiceRecorderService.swift +8 -0
  29. package/package.json +1 -1
@@ -44,6 +44,10 @@ export class VoiceRecorderService {
44
44
  getCurrentStatus() {
45
45
  return this.execute(() => this.platform.getCurrentStatus());
46
46
  }
47
+ /** Returns the current input amplitude. */
48
+ getCurrentAmplitude() {
49
+ return this.execute(() => this.platform.getCurrentAmplitude());
50
+ }
47
51
  /** Wraps calls to apply canonical error codes when requested. */
48
52
  async execute(fn) {
49
53
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"VoiceRecorderService.js","sourceRoot":"","sources":["../../../src/service/VoiceRecorderService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AA6BpE,2EAA2E;AAC3E,MAAM,OAAO,oBAAoB;IAM7B,YAAmB,QAA+B,EAAE,cAA8B;QAC9E,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACzC,CAAC;IAED,kDAAkD;IAC3C,oBAAoB;QACvB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,oBAAoB,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,kEAAkE;IAC3D,2BAA2B;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,2BAA2B,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,oDAAoD;IAC7C,+BAA+B;QAClC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,+BAA+B,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,kCAAkC;IAC3B,cAAc,CAAC,OAA0B;QAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,qEAAqE;IAC9D,KAAK,CAAC,aAAa;QACtB,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE;YAC3B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;YACjD,IAAI,IAAI,CAAC,cAAc,KAAK,YAAY,EAAE,CAAC;gBACvC,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC;YACxC,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,mDAAmD;IAC5C,cAAc;QACjB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,yDAAyD;IAClD,eAAe;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,2CAA2C;IACpC,gBAAgB;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,iEAAiE;IACzD,KAAK,CAAC,OAAO,CAAI,EAAoB;QACzC,IAAI,CAAC;YACD,OAAO,MAAM,EAAE,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,IAAI,IAAI,CAAC,cAAc,KAAK,YAAY,EAAE,CAAC;gBACvC,wBAAwB,CAAC,KAAK,CAAC,CAAC;YACpC,CAAC;YACD,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;CACJ","sourcesContent":["import { attachCanonicalErrorCode } from '../core/error-codes';\nimport { normalizeRecordingData } from '../core/recording-contract';\nimport type { ResponseFormat } from '../core/response-format';\nimport type {\n CurrentRecordingStatus,\n GenericResponse,\n RecordingData,\n RecordingOptions,\n} from '../definitions';\n\n/** Platform abstraction used by the service layer. */\nexport interface VoiceRecorderPlatform {\n /** Checks whether the device can record audio. */\n canDeviceVoiceRecord(): Promise<GenericResponse>;\n /** Returns whether microphone permission is currently granted. */\n hasAudioRecordingPermission(): Promise<GenericResponse>;\n /** Requests microphone permission from the user. */\n requestAudioRecordingPermission(): Promise<GenericResponse>;\n /** Starts a recording session. */\n startRecording(options?: RecordingOptions): Promise<GenericResponse>;\n /** Stops the current recording session and returns the payload. */\n stopRecording(): Promise<RecordingData>;\n /** Pauses the recording session when supported. */\n pauseRecording(): Promise<GenericResponse>;\n /** Resumes a paused recording session when supported. */\n resumeRecording(): Promise<GenericResponse>;\n /** Returns the current recording state. */\n getCurrentStatus(): Promise<CurrentRecordingStatus>;\n}\n\n/** Orchestrates platform calls and normalizes responses when requested. */\nexport class VoiceRecorderService {\n /** Selected response format derived from plugin config. */\n private readonly responseFormat: ResponseFormat;\n /** Platform adapter that performs the actual recording work. */\n private readonly platform: VoiceRecorderPlatform;\n\n public constructor(platform: VoiceRecorderPlatform, responseFormat: ResponseFormat) {\n this.platform = platform;\n this.responseFormat = responseFormat;\n }\n\n /** Checks whether the device can record audio. */\n public canDeviceVoiceRecord(): Promise<GenericResponse> {\n return this.execute(() => this.platform.canDeviceVoiceRecord());\n }\n\n /** Returns whether microphone permission is currently granted. */\n public hasAudioRecordingPermission(): Promise<GenericResponse> {\n return this.execute(() => this.platform.hasAudioRecordingPermission());\n }\n\n /** Requests microphone permission from the user. */\n public requestAudioRecordingPermission(): Promise<GenericResponse> {\n return this.execute(() => this.platform.requestAudioRecordingPermission());\n }\n\n /** Starts a recording session. */\n public startRecording(options?: RecordingOptions): Promise<GenericResponse> {\n return this.execute(() => this.platform.startRecording(options));\n }\n\n /** Stops the recording session and formats the payload if needed. */\n public async stopRecording(): Promise<RecordingData> {\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\n /** Pauses the recording session when supported. */\n public pauseRecording(): Promise<GenericResponse> {\n return this.execute(() => this.platform.pauseRecording());\n }\n\n /** Resumes a paused recording session when supported. */\n public resumeRecording(): Promise<GenericResponse> {\n return this.execute(() => this.platform.resumeRecording());\n }\n\n /** Returns the current recording state. */\n public getCurrentStatus(): Promise<CurrentRecordingStatus> {\n return this.execute(() => this.platform.getCurrentStatus());\n }\n\n /** Wraps calls to apply canonical error codes when requested. */\n private async execute<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n if (this.responseFormat === 'normalized') {\n attachCanonicalErrorCode(error);\n }\n throw error;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"VoiceRecorderService.js","sourceRoot":"","sources":["../../../src/service/VoiceRecorderService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAgCpE,2EAA2E;AAC3E,MAAM,OAAO,oBAAoB;IAM7B,YAAmB,QAA+B,EAAE,cAA8B;QAC9E,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACzC,CAAC;IAED,kDAAkD;IAC3C,oBAAoB;QACvB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,oBAAoB,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,kEAAkE;IAC3D,2BAA2B;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,2BAA2B,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,oDAAoD;IAC7C,+BAA+B;QAClC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,+BAA+B,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,kCAAkC;IAC3B,cAAc,CAAC,OAA0B;QAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,qEAAqE;IAC9D,KAAK,CAAC,aAAa;QACtB,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE;YAC3B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;YACjD,IAAI,IAAI,CAAC,cAAc,KAAK,YAAY,EAAE,CAAC;gBACvC,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC;YACxC,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,mDAAmD;IAC5C,cAAc;QACjB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,yDAAyD;IAClD,eAAe;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,2CAA2C;IACpC,gBAAgB;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,2CAA2C;IACpC,mBAAmB;QACtB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,iEAAiE;IACzD,KAAK,CAAC,OAAO,CAAI,EAAoB;QACzC,IAAI,CAAC;YACD,OAAO,MAAM,EAAE,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,IAAI,IAAI,CAAC,cAAc,KAAK,YAAY,EAAE,CAAC;gBACvC,wBAAwB,CAAC,KAAK,CAAC,CAAC;YACpC,CAAC;YACD,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;CACJ","sourcesContent":["import { attachCanonicalErrorCode } from '../core/error-codes';\nimport { normalizeRecordingData } from '../core/recording-contract';\nimport type { ResponseFormat } from '../core/response-format';\nimport type {\n CurrentAmplitude,\n CurrentRecordingStatus,\n GenericResponse,\n RecordingData,\n RecordingOptions,\n} from '../definitions';\n\n/** Platform abstraction used by the service layer. */\nexport interface VoiceRecorderPlatform {\n /** Checks whether the device can record audio. */\n canDeviceVoiceRecord(): Promise<GenericResponse>;\n /** Returns whether microphone permission is currently granted. */\n hasAudioRecordingPermission(): Promise<GenericResponse>;\n /** Requests microphone permission from the user. */\n requestAudioRecordingPermission(): Promise<GenericResponse>;\n /** Starts a recording session. */\n startRecording(options?: RecordingOptions): Promise<GenericResponse>;\n /** Stops the current recording session and returns the payload. */\n stopRecording(): Promise<RecordingData>;\n /** Pauses the recording session when supported. */\n pauseRecording(): Promise<GenericResponse>;\n /** Resumes a paused recording session when supported. */\n resumeRecording(): Promise<GenericResponse>;\n /** Returns the current recording state. */\n getCurrentStatus(): Promise<CurrentRecordingStatus>;\n /** Returns the current input amplitude. */\n getCurrentAmplitude(): Promise<CurrentAmplitude>;\n}\n\n/** Orchestrates platform calls and normalizes responses when requested. */\nexport class VoiceRecorderService {\n /** Selected response format derived from plugin config. */\n private readonly responseFormat: ResponseFormat;\n /** Platform adapter that performs the actual recording work. */\n private readonly platform: VoiceRecorderPlatform;\n\n public constructor(platform: VoiceRecorderPlatform, responseFormat: ResponseFormat) {\n this.platform = platform;\n this.responseFormat = responseFormat;\n }\n\n /** Checks whether the device can record audio. */\n public canDeviceVoiceRecord(): Promise<GenericResponse> {\n return this.execute(() => this.platform.canDeviceVoiceRecord());\n }\n\n /** Returns whether microphone permission is currently granted. */\n public hasAudioRecordingPermission(): Promise<GenericResponse> {\n return this.execute(() => this.platform.hasAudioRecordingPermission());\n }\n\n /** Requests microphone permission from the user. */\n public requestAudioRecordingPermission(): Promise<GenericResponse> {\n return this.execute(() => this.platform.requestAudioRecordingPermission());\n }\n\n /** Starts a recording session. */\n public startRecording(options?: RecordingOptions): Promise<GenericResponse> {\n return this.execute(() => this.platform.startRecording(options));\n }\n\n /** Stops the recording session and formats the payload if needed. */\n public async stopRecording(): Promise<RecordingData> {\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\n /** Pauses the recording session when supported. */\n public pauseRecording(): Promise<GenericResponse> {\n return this.execute(() => this.platform.pauseRecording());\n }\n\n /** Resumes a paused recording session when supported. */\n public resumeRecording(): Promise<GenericResponse> {\n return this.execute(() => this.platform.resumeRecording());\n }\n\n /** Returns the current recording state. */\n public getCurrentStatus(): Promise<CurrentRecordingStatus> {\n return this.execute(() => this.platform.getCurrentStatus());\n }\n\n /** Returns the current input amplitude. */\n public getCurrentAmplitude(): Promise<CurrentAmplitude> {\n return this.execute(() => this.platform.getCurrentAmplitude());\n }\n\n /** Wraps calls to apply canonical error codes when requested. */\n private async execute<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n if (this.responseFormat === 'normalized') {\n attachCanonicalErrorCode(error);\n }\n throw error;\n }\n }\n}\n"]}
package/dist/esm/web.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { WebPlugin } from '@capacitor/core';
2
- import type { CurrentRecordingStatus, GenericResponse, RecordingData, RecordingOptions, VoiceRecorderPlugin } from './definitions';
2
+ import type { CurrentAmplitude, CurrentRecordingStatus, GenericResponse, RecordingData, RecordingOptions, VoiceRecorderPlugin } from './definitions';
3
3
  /** Web implementation of the VoiceRecorder Capacitor plugin. */
4
4
  export declare class VoiceRecorderWeb extends WebPlugin implements VoiceRecorderPlugin {
5
5
  /** Service layer that normalizes behavior and errors. */
@@ -21,4 +21,6 @@ export declare class VoiceRecorderWeb extends WebPlugin implements VoiceRecorder
21
21
  resumeRecording(): Promise<GenericResponse>;
22
22
  /** Returns the current recording state. */
23
23
  getCurrentStatus(): Promise<CurrentRecordingStatus>;
24
+ /** Returns the current input amplitude. */
25
+ getCurrentAmplitude(): Promise<CurrentAmplitude>;
24
26
  }
package/dist/esm/web.js CHANGED
@@ -43,5 +43,9 @@ export class VoiceRecorderWeb extends WebPlugin {
43
43
  getCurrentStatus() {
44
44
  return this.service.getCurrentStatus();
45
45
  }
46
+ /** Returns the current input amplitude. */
47
+ getCurrentAmplitude() {
48
+ return this.service.getCurrentAmplitude();
49
+ }
46
50
  }
47
51
  //# sourceMappingURL=web.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAQrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAEtE,gEAAgE;AAChE,MAAM,OAAO,gBAAiB,SAAQ,SAAS;IAI7C;;QACE,KAAK,EAAE,CAAC;QACR,MAAM,YAAY,GAAG,MAAA,MAAC,SAAiB,aAAjB,SAAS,uBAAT,SAAS,CAAU,MAAM,0CAAE,OAAO,0CAAE,aAAa,CAAC;QACxE,MAAM,cAAc,GAAG,2BAA2B,CAAC,YAAY,CAAC,CAAC;QACjE,IAAI,CAAC,OAAO,GAAG,IAAI,oBAAoB,CAAC,IAAI,uBAAuB,EAAE,EAAE,cAAc,CAAC,CAAC;IACzF,CAAC;IAED,mDAAmD;IAC5C,oBAAoB;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAC7C,CAAC;IAED,kEAAkE;IAC3D,2BAA2B;QAChC,OAAO,IAAI,CAAC,OAAO,CAAC,2BAA2B,EAAE,CAAC;IACpD,CAAC;IAED,oDAAoD;IAC7C,+BAA+B;QACpC,OAAO,IAAI,CAAC,OAAO,CAAC,+BAA+B,EAAE,CAAC;IACxD,CAAC;IAED,kCAAkC;IAC3B,cAAc,CAAC,OAA0B;QAC9C,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,mEAAmE;IAC5D,aAAa;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;IACtC,CAAC;IAED,mDAAmD;IAC5C,cAAc;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;IACvC,CAAC;IAED,yDAAyD;IAClD,eAAe;QACpB,OAAO,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;IACxC,CAAC;IAED,2CAA2C;IACpC,gBAAgB;QACrB,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;IACzC,CAAC;CACF","sourcesContent":["import { Capacitor, WebPlugin } from '@capacitor/core';\n\nimport { VoiceRecorderWebAdapter } from './adapters/VoiceRecorderWebAdapter';\nimport { getResponseFormatFromConfig } from './core/response-format';\nimport type {\n CurrentRecordingStatus,\n GenericResponse,\n RecordingData,\n RecordingOptions,\n VoiceRecorderPlugin,\n} from './definitions';\nimport { VoiceRecorderService } from './service/VoiceRecorderService';\n\n/** Web implementation of the VoiceRecorder Capacitor plugin. */\nexport class VoiceRecorderWeb extends WebPlugin implements VoiceRecorderPlugin {\n /** Service layer that normalizes behavior and errors. */\n private readonly service: VoiceRecorderService;\n\n public constructor() {\n super();\n const pluginConfig = (Capacitor as any)?.config?.plugins?.VoiceRecorder;\n const responseFormat = getResponseFormatFromConfig(pluginConfig);\n this.service = new VoiceRecorderService(new VoiceRecorderWebAdapter(), responseFormat);\n }\n\n /** Checks whether the browser can record audio. */\n public canDeviceVoiceRecord(): Promise<GenericResponse> {\n return this.service.canDeviceVoiceRecord();\n }\n\n /** Returns whether microphone permission is currently granted. */\n public hasAudioRecordingPermission(): Promise<GenericResponse> {\n return this.service.hasAudioRecordingPermission();\n }\n\n /** Requests microphone permission from the user. */\n public requestAudioRecordingPermission(): Promise<GenericResponse> {\n return this.service.requestAudioRecordingPermission();\n }\n\n /** Starts a recording session. */\n public startRecording(options?: RecordingOptions): Promise<GenericResponse> {\n return this.service.startRecording(options);\n }\n\n /** Stops the current recording session and returns the payload. */\n public stopRecording(): Promise<RecordingData> {\n return this.service.stopRecording();\n }\n\n /** Pauses the recording session when supported. */\n public pauseRecording(): Promise<GenericResponse> {\n return this.service.pauseRecording();\n }\n\n /** Resumes a paused recording session when supported. */\n public resumeRecording(): Promise<GenericResponse> {\n return this.service.resumeRecording();\n }\n\n /** Returns the current recording state. */\n public getCurrentStatus(): Promise<CurrentRecordingStatus> {\n return this.service.getCurrentStatus();\n }\n}\n"]}
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AASrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAEtE,gEAAgE;AAChE,MAAM,OAAO,gBAAiB,SAAQ,SAAS;IAI7C;;QACE,KAAK,EAAE,CAAC;QACR,MAAM,YAAY,GAAG,MAAA,MAAC,SAAiB,aAAjB,SAAS,uBAAT,SAAS,CAAU,MAAM,0CAAE,OAAO,0CAAE,aAAa,CAAC;QACxE,MAAM,cAAc,GAAG,2BAA2B,CAAC,YAAY,CAAC,CAAC;QACjE,IAAI,CAAC,OAAO,GAAG,IAAI,oBAAoB,CAAC,IAAI,uBAAuB,EAAE,EAAE,cAAc,CAAC,CAAC;IACzF,CAAC;IAED,mDAAmD;IAC5C,oBAAoB;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAC7C,CAAC;IAED,kEAAkE;IAC3D,2BAA2B;QAChC,OAAO,IAAI,CAAC,OAAO,CAAC,2BAA2B,EAAE,CAAC;IACpD,CAAC;IAED,oDAAoD;IAC7C,+BAA+B;QACpC,OAAO,IAAI,CAAC,OAAO,CAAC,+BAA+B,EAAE,CAAC;IACxD,CAAC;IAED,kCAAkC;IAC3B,cAAc,CAAC,OAA0B;QAC9C,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,mEAAmE;IAC5D,aAAa;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;IACtC,CAAC;IAED,mDAAmD;IAC5C,cAAc;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;IACvC,CAAC;IAED,yDAAyD;IAClD,eAAe;QACpB,OAAO,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;IACxC,CAAC;IAED,2CAA2C;IACpC,gBAAgB;QACrB,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;IACzC,CAAC;IAED,2CAA2C;IACpC,mBAAmB;QACxB,OAAO,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAC5C,CAAC;CACF","sourcesContent":["import { Capacitor, WebPlugin } from '@capacitor/core';\n\nimport { VoiceRecorderWebAdapter } from './adapters/VoiceRecorderWebAdapter';\nimport { getResponseFormatFromConfig } from './core/response-format';\nimport type {\n CurrentAmplitude,\n CurrentRecordingStatus,\n GenericResponse,\n RecordingData,\n RecordingOptions,\n VoiceRecorderPlugin,\n} from './definitions';\nimport { VoiceRecorderService } from './service/VoiceRecorderService';\n\n/** Web implementation of the VoiceRecorder Capacitor plugin. */\nexport class VoiceRecorderWeb extends WebPlugin implements VoiceRecorderPlugin {\n /** Service layer that normalizes behavior and errors. */\n private readonly service: VoiceRecorderService;\n\n public constructor() {\n super();\n const pluginConfig = (Capacitor as any)?.config?.plugins?.VoiceRecorder;\n const responseFormat = getResponseFormatFromConfig(pluginConfig);\n this.service = new VoiceRecorderService(new VoiceRecorderWebAdapter(), responseFormat);\n }\n\n /** Checks whether the browser can record audio. */\n public canDeviceVoiceRecord(): Promise<GenericResponse> {\n return this.service.canDeviceVoiceRecord();\n }\n\n /** Returns whether microphone permission is currently granted. */\n public hasAudioRecordingPermission(): Promise<GenericResponse> {\n return this.service.hasAudioRecordingPermission();\n }\n\n /** Requests microphone permission from the user. */\n public requestAudioRecordingPermission(): Promise<GenericResponse> {\n return this.service.requestAudioRecordingPermission();\n }\n\n /** Starts a recording session. */\n public startRecording(options?: RecordingOptions): Promise<GenericResponse> {\n return this.service.startRecording(options);\n }\n\n /** Stops the current recording session and returns the payload. */\n public stopRecording(): Promise<RecordingData> {\n return this.service.stopRecording();\n }\n\n /** Pauses the recording session when supported. */\n public pauseRecording(): Promise<GenericResponse> {\n return this.service.pauseRecording();\n }\n\n /** Resumes a paused recording session when supported. */\n public resumeRecording(): Promise<GenericResponse> {\n return this.service.resumeRecording();\n }\n\n /** Returns the current recording state. */\n public getCurrentStatus(): Promise<CurrentRecordingStatus> {\n return this.service.getCurrentStatus();\n }\n\n /** Returns the current input amplitude. */\n public getCurrentAmplitude(): Promise<CurrentAmplitude> {\n return this.service.getCurrentAmplitude();\n }\n}\n"]}
@@ -130,6 +130,14 @@ class VoiceRecorderImpl {
130
130
  constructor() {
131
131
  /** Active MediaRecorder instance, if recording. */
132
132
  this.mediaRecorder = null;
133
+ /** AudioContext used for live amplitude metering. */
134
+ this.audioContext = null;
135
+ /** Web Audio analyser used to sample the active input stream. */
136
+ this.amplitudeAnalyser = null;
137
+ /** Source node that keeps the input stream connected to the analyser. */
138
+ this.amplitudeSource = null;
139
+ /** Reusable buffer for analyser time-domain samples. */
140
+ this.amplitudeSamples = null;
133
141
  /** Collected data chunks from MediaRecorder. */
134
142
  this.chunks = [];
135
143
  /** Promise resolved when the recorder stops and payload is ready. */
@@ -270,6 +278,22 @@ class VoiceRecorderImpl {
270
278
  return Promise.resolve({ status: 'NONE' });
271
279
  }
272
280
  }
281
+ /** Returns the current input amplitude normalized to the [0, 1] range. */
282
+ getCurrentAmplitude() {
283
+ var _a;
284
+ if (((_a = this.mediaRecorder) === null || _a === void 0 ? void 0 : _a.state) !== 'recording' || this.amplitudeAnalyser == null || this.amplitudeSamples == null) {
285
+ return Promise.resolve({ value: 0 });
286
+ }
287
+ this.amplitudeAnalyser.getByteTimeDomainData(this.amplitudeSamples);
288
+ let sumOfSquares = 0;
289
+ for (const sample of this.amplitudeSamples) {
290
+ const centered = (sample - 128) / 128;
291
+ sumOfSquares += centered * centered;
292
+ }
293
+ return Promise.resolve({
294
+ value: VoiceRecorderImpl.clampAmplitude(Math.sqrt(sumOfSquares / this.amplitudeSamples.length)),
295
+ });
296
+ }
273
297
  /**
274
298
  * Returns the first MIME type (key of {@link POSSIBLE_MIME_TYPES}) that the current
275
299
  * environment reports as supported for recording via `MediaRecorder.isTypeSupported()`,
@@ -347,6 +371,7 @@ class VoiceRecorderImpl {
347
371
  return;
348
372
  }
349
373
  this.mediaRecorder = new MediaRecorder(stream, { mimeType });
374
+ this.startAmplitudeMeter(stream);
350
375
  this.mediaRecorder.onerror = () => {
351
376
  this.prepareInstanceForNextOperation();
352
377
  reject(failedToRecordError());
@@ -413,6 +438,34 @@ class VoiceRecorderImpl {
413
438
  reader.readAsDataURL(blob);
414
439
  });
415
440
  }
441
+ /** Connects the recording stream to a lightweight Web Audio analyser for amplitude polling. */
442
+ startAmplitudeMeter(stream) {
443
+ var _a;
444
+ try {
445
+ const AudioContextConstructor = (_a = window.AudioContext) !== null && _a !== void 0 ? _a : window.webkitAudioContext;
446
+ if (AudioContextConstructor == null) {
447
+ return;
448
+ }
449
+ this.audioContext = new AudioContextConstructor();
450
+ this.amplitudeSource = this.audioContext.createMediaStreamSource(stream);
451
+ this.amplitudeAnalyser = this.audioContext.createAnalyser();
452
+ this.amplitudeAnalyser.fftSize = 2048;
453
+ this.amplitudeSamples = new Uint8Array(this.amplitudeAnalyser.fftSize);
454
+ this.amplitudeSource.connect(this.amplitudeAnalyser);
455
+ }
456
+ catch (ignore) {
457
+ this.audioContext = null;
458
+ this.amplitudeAnalyser = null;
459
+ this.amplitudeSource = null;
460
+ this.amplitudeSamples = null;
461
+ }
462
+ }
463
+ /** Clamps platform-specific amplitude calculations into the public range. */
464
+ static clampAmplitude(value) {
465
+ if (!Number.isFinite(value))
466
+ return 0;
467
+ return Math.min(1, Math.max(0, value));
468
+ }
416
469
  /** Resets state for the next recording attempt. */
417
470
  prepareInstanceForNextOperation() {
418
471
  if (this.mediaRecorder != null && this.mediaRecorder.state === 'recording') {
@@ -423,6 +476,21 @@ class VoiceRecorderImpl {
423
476
  console.warn('Failed to stop recording during cleanup');
424
477
  }
425
478
  }
479
+ if (this.amplitudeSource != null) {
480
+ try {
481
+ this.amplitudeSource.disconnect();
482
+ }
483
+ catch (ignore) {
484
+ // The node may already be disconnected during recorder cleanup.
485
+ }
486
+ }
487
+ if (this.audioContext != null && this.audioContext.state !== 'closed') {
488
+ void this.audioContext.close().catch(() => undefined);
489
+ }
490
+ this.audioContext = null;
491
+ this.amplitudeAnalyser = null;
492
+ this.amplitudeSource = null;
493
+ this.amplitudeSamples = null;
426
494
  this.pendingResult = neverResolvingPromise();
427
495
  this.mediaRecorder = null;
428
496
  this.chunks = [];
@@ -469,6 +537,10 @@ class VoiceRecorderWebAdapter {
469
537
  getCurrentStatus() {
470
538
  return this.voiceRecorderImpl.getCurrentStatus();
471
539
  }
540
+ /** Returns the current input amplitude. */
541
+ getCurrentAmplitude() {
542
+ return this.voiceRecorderImpl.getCurrentAmplitude();
543
+ }
472
544
  }
473
545
 
474
546
  /** Default response shape when no config is provided. */
@@ -568,6 +640,10 @@ class VoiceRecorderService {
568
640
  getCurrentStatus() {
569
641
  return this.execute(() => this.platform.getCurrentStatus());
570
642
  }
643
+ /** Returns the current input amplitude. */
644
+ getCurrentAmplitude() {
645
+ return this.execute(() => this.platform.getCurrentAmplitude());
646
+ }
571
647
  /** Wraps calls to apply canonical error codes when requested. */
572
648
  async execute(fn) {
573
649
  try {
@@ -623,6 +699,10 @@ class VoiceRecorderWeb extends core.WebPlugin {
623
699
  getCurrentStatus() {
624
700
  return this.service.getCurrentStatus();
625
701
  }
702
+ /** Returns the current input amplitude. */
703
+ getCurrentAmplitude() {
704
+ return this.service.getCurrentAmplitude();
705
+ }
626
706
  }
627
707
 
628
708
  var web = /*#__PURE__*/Object.freeze({
@@ -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, _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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"}
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 /** AudioContext used for live amplitude metering. */\n this.audioContext = null;\n /** Web Audio analyser used to sample the active input stream. */\n this.amplitudeAnalyser = null;\n /** Source node that keeps the input stream connected to the analyser. */\n this.amplitudeSource = null;\n /** Reusable buffer for analyser time-domain samples. */\n this.amplitudeSamples = 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 /** Returns the current input amplitude normalized to the [0, 1] range. */\n getCurrentAmplitude() {\n var _a;\n if (((_a = this.mediaRecorder) === null || _a === void 0 ? void 0 : _a.state) !== 'recording' || this.amplitudeAnalyser == null || this.amplitudeSamples == null) {\n return Promise.resolve({ value: 0 });\n }\n this.amplitudeAnalyser.getByteTimeDomainData(this.amplitudeSamples);\n let sumOfSquares = 0;\n for (const sample of this.amplitudeSamples) {\n const centered = (sample - 128) / 128;\n sumOfSquares += centered * centered;\n }\n return Promise.resolve({\n value: VoiceRecorderImpl.clampAmplitude(Math.sqrt(sumOfSquares / this.amplitudeSamples.length)),\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.startAmplitudeMeter(stream);\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 /** Connects the recording stream to a lightweight Web Audio analyser for amplitude polling. */\n startAmplitudeMeter(stream) {\n var _a;\n try {\n const AudioContextConstructor = (_a = window.AudioContext) !== null && _a !== void 0 ? _a : window.webkitAudioContext;\n if (AudioContextConstructor == null) {\n return;\n }\n this.audioContext = new AudioContextConstructor();\n this.amplitudeSource = this.audioContext.createMediaStreamSource(stream);\n this.amplitudeAnalyser = this.audioContext.createAnalyser();\n this.amplitudeAnalyser.fftSize = 2048;\n this.amplitudeSamples = new Uint8Array(this.amplitudeAnalyser.fftSize);\n this.amplitudeSource.connect(this.amplitudeAnalyser);\n }\n catch (ignore) {\n this.audioContext = null;\n this.amplitudeAnalyser = null;\n this.amplitudeSource = null;\n this.amplitudeSamples = null;\n }\n }\n /** Clamps platform-specific amplitude calculations into the public range. */\n static clampAmplitude(value) {\n if (!Number.isFinite(value))\n return 0;\n return Math.min(1, Math.max(0, value));\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 if (this.amplitudeSource != null) {\n try {\n this.amplitudeSource.disconnect();\n }\n catch (ignore) {\n // The node may already be disconnected during recorder cleanup.\n }\n }\n if (this.audioContext != null && this.audioContext.state !== 'closed') {\n void this.audioContext.close().catch(() => undefined);\n }\n this.audioContext = null;\n this.amplitudeAnalyser = null;\n this.amplitudeSource = null;\n this.amplitudeSamples = null;\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 /** Returns the current input amplitude. */\n getCurrentAmplitude() {\n return this.voiceRecorderImpl.getCurrentAmplitude();\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 /** Returns the current input amplitude. */\n getCurrentAmplitude() {\n return this.execute(() => this.platform.getCurrentAmplitude());\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 /** Returns the current input amplitude. */\n getCurrentAmplitude() {\n return this.service.getCurrentAmplitude();\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","Filesystem","WebPlugin","Capacitor"],"mappings":"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"}
package/dist/plugin.js CHANGED
@@ -127,6 +127,14 @@ var capacitorVoiceRecorder = (function (exports, core, filesystem, write_blob) {
127
127
  constructor() {
128
128
  /** Active MediaRecorder instance, if recording. */
129
129
  this.mediaRecorder = null;
130
+ /** AudioContext used for live amplitude metering. */
131
+ this.audioContext = null;
132
+ /** Web Audio analyser used to sample the active input stream. */
133
+ this.amplitudeAnalyser = null;
134
+ /** Source node that keeps the input stream connected to the analyser. */
135
+ this.amplitudeSource = null;
136
+ /** Reusable buffer for analyser time-domain samples. */
137
+ this.amplitudeSamples = null;
130
138
  /** Collected data chunks from MediaRecorder. */
131
139
  this.chunks = [];
132
140
  /** Promise resolved when the recorder stops and payload is ready. */
@@ -267,6 +275,22 @@ var capacitorVoiceRecorder = (function (exports, core, filesystem, write_blob) {
267
275
  return Promise.resolve({ status: 'NONE' });
268
276
  }
269
277
  }
278
+ /** Returns the current input amplitude normalized to the [0, 1] range. */
279
+ getCurrentAmplitude() {
280
+ var _a;
281
+ if (((_a = this.mediaRecorder) === null || _a === void 0 ? void 0 : _a.state) !== 'recording' || this.amplitudeAnalyser == null || this.amplitudeSamples == null) {
282
+ return Promise.resolve({ value: 0 });
283
+ }
284
+ this.amplitudeAnalyser.getByteTimeDomainData(this.amplitudeSamples);
285
+ let sumOfSquares = 0;
286
+ for (const sample of this.amplitudeSamples) {
287
+ const centered = (sample - 128) / 128;
288
+ sumOfSquares += centered * centered;
289
+ }
290
+ return Promise.resolve({
291
+ value: VoiceRecorderImpl.clampAmplitude(Math.sqrt(sumOfSquares / this.amplitudeSamples.length)),
292
+ });
293
+ }
270
294
  /**
271
295
  * Returns the first MIME type (key of {@link POSSIBLE_MIME_TYPES}) that the current
272
296
  * environment reports as supported for recording via `MediaRecorder.isTypeSupported()`,
@@ -344,6 +368,7 @@ var capacitorVoiceRecorder = (function (exports, core, filesystem, write_blob) {
344
368
  return;
345
369
  }
346
370
  this.mediaRecorder = new MediaRecorder(stream, { mimeType });
371
+ this.startAmplitudeMeter(stream);
347
372
  this.mediaRecorder.onerror = () => {
348
373
  this.prepareInstanceForNextOperation();
349
374
  reject(failedToRecordError());
@@ -410,6 +435,34 @@ var capacitorVoiceRecorder = (function (exports, core, filesystem, write_blob) {
410
435
  reader.readAsDataURL(blob);
411
436
  });
412
437
  }
438
+ /** Connects the recording stream to a lightweight Web Audio analyser for amplitude polling. */
439
+ startAmplitudeMeter(stream) {
440
+ var _a;
441
+ try {
442
+ const AudioContextConstructor = (_a = window.AudioContext) !== null && _a !== void 0 ? _a : window.webkitAudioContext;
443
+ if (AudioContextConstructor == null) {
444
+ return;
445
+ }
446
+ this.audioContext = new AudioContextConstructor();
447
+ this.amplitudeSource = this.audioContext.createMediaStreamSource(stream);
448
+ this.amplitudeAnalyser = this.audioContext.createAnalyser();
449
+ this.amplitudeAnalyser.fftSize = 2048;
450
+ this.amplitudeSamples = new Uint8Array(this.amplitudeAnalyser.fftSize);
451
+ this.amplitudeSource.connect(this.amplitudeAnalyser);
452
+ }
453
+ catch (ignore) {
454
+ this.audioContext = null;
455
+ this.amplitudeAnalyser = null;
456
+ this.amplitudeSource = null;
457
+ this.amplitudeSamples = null;
458
+ }
459
+ }
460
+ /** Clamps platform-specific amplitude calculations into the public range. */
461
+ static clampAmplitude(value) {
462
+ if (!Number.isFinite(value))
463
+ return 0;
464
+ return Math.min(1, Math.max(0, value));
465
+ }
413
466
  /** Resets state for the next recording attempt. */
414
467
  prepareInstanceForNextOperation() {
415
468
  if (this.mediaRecorder != null && this.mediaRecorder.state === 'recording') {
@@ -420,6 +473,21 @@ var capacitorVoiceRecorder = (function (exports, core, filesystem, write_blob) {
420
473
  console.warn('Failed to stop recording during cleanup');
421
474
  }
422
475
  }
476
+ if (this.amplitudeSource != null) {
477
+ try {
478
+ this.amplitudeSource.disconnect();
479
+ }
480
+ catch (ignore) {
481
+ // The node may already be disconnected during recorder cleanup.
482
+ }
483
+ }
484
+ if (this.audioContext != null && this.audioContext.state !== 'closed') {
485
+ void this.audioContext.close().catch(() => undefined);
486
+ }
487
+ this.audioContext = null;
488
+ this.amplitudeAnalyser = null;
489
+ this.amplitudeSource = null;
490
+ this.amplitudeSamples = null;
423
491
  this.pendingResult = neverResolvingPromise();
424
492
  this.mediaRecorder = null;
425
493
  this.chunks = [];
@@ -466,6 +534,10 @@ var capacitorVoiceRecorder = (function (exports, core, filesystem, write_blob) {
466
534
  getCurrentStatus() {
467
535
  return this.voiceRecorderImpl.getCurrentStatus();
468
536
  }
537
+ /** Returns the current input amplitude. */
538
+ getCurrentAmplitude() {
539
+ return this.voiceRecorderImpl.getCurrentAmplitude();
540
+ }
469
541
  }
470
542
 
471
543
  /** Default response shape when no config is provided. */
@@ -565,6 +637,10 @@ var capacitorVoiceRecorder = (function (exports, core, filesystem, write_blob) {
565
637
  getCurrentStatus() {
566
638
  return this.execute(() => this.platform.getCurrentStatus());
567
639
  }
640
+ /** Returns the current input amplitude. */
641
+ getCurrentAmplitude() {
642
+ return this.execute(() => this.platform.getCurrentAmplitude());
643
+ }
568
644
  /** Wraps calls to apply canonical error codes when requested. */
569
645
  async execute(fn) {
570
646
  try {
@@ -620,6 +696,10 @@ var capacitorVoiceRecorder = (function (exports, core, filesystem, write_blob) {
620
696
  getCurrentStatus() {
621
697
  return this.service.getCurrentStatus();
622
698
  }
699
+ /** Returns the current input amplitude. */
700
+ getCurrentAmplitude() {
701
+ return this.service.getCurrentAmplitude();
702
+ }
623
703
  }
624
704
 
625
705
  var web = /*#__PURE__*/Object.freeze({