@siteed/expo-audio-stream 1.15.0 → 1.16.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/CHANGELOG.md CHANGED
@@ -8,6 +8,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
  ## [Unreleased]
9
9
 
10
10
 
11
+ ## [1.16.0] - 2025-02-17
12
+ ### Changed
13
+ - fix(expo-audio-stream): prevent adding iOS background modes when disabled ([5c9d09c](https://github.com/deeeed/expo-audio-stream/commit/5c9d09c715ce008fe72177431224a10f5fd7a865))
14
+ - fix(ios): replace CallKit with AVAudioSession for phone call detection ([e3b664b](https://github.com/deeeed/expo-audio-stream/commit/e3b664ba6925c379b323ded5fc408154e5f092c6))
15
+ - chore(expo-audio-stream): release @siteed/expo-audio-stream@1.15.1 ([cbc3d10](https://github.com/deeeed/expo-audio-stream/commit/cbc3d10661a415811f1fe46cb3acaf63451a9df9))
16
+ ## [1.15.1] - 2025-02-17
17
+ ### Changed
18
+ - fix: restore Opus compression support on iOS (#122) ([06614e6](https://github.com/deeeed/expo-audio-stream/commit/06614e6d96fa2a6af56edf0fd2e2b3966e13c8f7))
19
+ - feat: dont block while emitting audio analysis ([01d91d1](https://github.com/deeeed/expo-audio-stream/commit/01d91d1504ccda8ad3569980c79fcf4ae4526a76))
20
+ - chore(expo-audio-stream): release @siteed/expo-audio-stream@1.15.0 ([f94c601](https://github.com/deeeed/expo-audio-stream/commit/f94c6016ba4ce968cafbf68644199405f5991d7f))
11
21
  ## [1.15.0] - 2025-02-15
12
22
  ### Changed
13
23
  - fix(ios): improve audio recording interruption handling and auto-resume functionality (#119) ([7767dff](https://github.com/deeeed/expo-audio-stream/commit/7767dff09c7c8d2f2dc8558d24fd2419cb981f4d))
@@ -119,7 +129,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
119
129
  - Feature: Audio features extraction during recording.
120
130
  - Feature: Consistent WAV PCM recording format across all platforms.
121
131
 
122
- [unreleased]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-stream@1.15.0...HEAD
132
+ [unreleased]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-stream@1.16.0...HEAD
133
+ [1.16.0]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-stream@1.15.1...@siteed/expo-audio-stream@1.16.0
134
+ [1.15.1]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-stream@1.15.0...@siteed/expo-audio-stream@1.15.1
123
135
  [1.15.0]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-stream@1.14.2...@siteed/expo-audio-stream@1.15.0
124
136
  [1.14.2]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-stream@1.14.1...@siteed/expo-audio-stream@1.14.2
125
137
  [1.14.1]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-stream@1.14.0...@siteed/expo-audio-stream@1.14.1
@@ -104,7 +104,7 @@ export interface RecordingConfig {
104
104
  onAudioAnalysis?: (_: AudioAnalysisEvent) => Promise<void>;
105
105
  compression?: {
106
106
  enabled: boolean;
107
- format: 'aac' | 'opus' | 'mp3';
107
+ format: 'aac' | 'opus';
108
108
  bitrate?: number;
109
109
  };
110
110
  autoResumeAfterInterruption?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoAudioStream.types.d.ts","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ExpoAudioStream.types.d.ts","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"AACA,OAAO,EACH,kBAAkB,EAClB,aAAa,EACb,oBAAoB,EACvB,MAAM,qCAAqC,CAAA;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAE7C,MAAM,WAAW,eAAe;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAC9B,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,OAAO,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,eAAe,CAAA;CAChC;AAED,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,MAAM,GAAG,YAAY,CAAA;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,eAAe,GAAG;QAC5B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KACvB,CAAA;CACJ;AAED,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,CAAA;AACjE,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAA;AAC9C,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAA;AAElC,MAAM,MAAM,WAAW,GAAG;IACtB,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;IAClD,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;IACpD,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;IACnD,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;CACvD,CAAA;AAED,MAAM,WAAW,KAAK;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAA;CACrC;AAED,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,OAAO,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,KAAK,EAAE,CAAA;CAClB;AAED,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,QAAQ,CAAA;IAClB,UAAU,EAAE,UAAU,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,eAAe,EAAE,CAAA;IAC/B,YAAY,CAAC,EAAE,aAAa,CAAA;IAC5B,WAAW,CAAC,EAAE,eAAe,GAAG;QAC5B,iBAAiB,EAAE,MAAM,CAAA;KAC5B,CAAA;CACJ;AAED,MAAM,WAAW,oBAAoB;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,WAAW,CAAC,EAAE,eAAe,GAAG;QAC5B,iBAAiB,EAAE,MAAM,CAAA;KAC5B,CAAA;CACJ;AAED,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,CAAC,EACH,SAAS,GACT,aAAa,GACb,UAAU,GACV,QAAQ,GACR,eAAe,GACf,YAAY,CAAA;IAClB,IAAI,CAAC,EACC,SAAS,GACT,WAAW,GACX,WAAW,GACX,UAAU,GACV,gBAAgB,GAChB,aAAa,GACb,eAAe,GACf,aAAa,CAAA;IACnB,eAAe,CAAC,EAAE,CACZ,eAAe,GACf,YAAY,GACZ,sCAAsC,GACtC,gBAAgB,GAChB,oBAAoB,GACpB,cAAc,GACd,kBAAkB,CACvB,EAAE,CAAA;CACN;AAED,MAAM,WAAW,SAAS;IACtB,YAAY,CAAC,EAAE,kBAAkB,CAAA;CACpC;AAGD,MAAM,MAAM,2BAA2B,GACjC,gBAAgB,GAChB,gBAAgB,GAChB,WAAW,GACX,gBAAgB,GAChB,kBAAkB,CAAA;AAGxB,MAAM,WAAW,0BAA0B;IACvC,MAAM,EAAE,2BAA2B,CAAA;IACnC,QAAQ,EAAE,OAAO,CAAA;CACpB;AAED,MAAM,WAAW,eAAe;IAE5B,UAAU,CAAC,EAAE,UAAU,CAAA;IAGvB,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;IAGhB,QAAQ,CAAC,EAAE,YAAY,CAAA;IAGvB,QAAQ,CAAC,EAAE,MAAM,CAAA;IAGjB,SAAS,CAAC,EAAE,OAAO,CAAA;IAGnB,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAG1B,0BAA0B,CAAC,EAAE,OAAO,CAAA;IAGpC,YAAY,CAAC,EAAE,kBAAkB,CAAA;IAGjC,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAG1B,GAAG,CAAC,EAAE,SAAS,CAAA;IAGf,eAAe,CAAC,EAAE,MAAM,CAAA;IAGxB,SAAS,CAAC,EAAE,kBAAkB,CAAA;IAG9B,QAAQ,CAAC,EAAE,oBAAoB,CAAA;IAG/B,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAGpD,eAAe,CAAC,EAAE,CAAC,CAAC,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAE1D,WAAW,CAAC,EAAE;QACV,OAAO,EAAE,OAAO,CAAA;QAChB,MAAM,EAAE,KAAK,GAAG,MAAM,CAAA;QACtB,OAAO,CAAC,EAAE,MAAM,CAAA;KACnB,CAAA;IAGD,2BAA2B,CAAC,EAAE,OAAO,CAAA;IAGrC,sBAAsB,CAAC,EAAE,CAAC,CAAC,EAAE,0BAA0B,KAAK,IAAI,CAAA;IAGhE,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,kBAAkB;IAE/B,KAAK,CAAC,EAAE,MAAM,CAAA;IAGd,IAAI,CAAC,EAAE,MAAM,CAAA;IAGb,IAAI,CAAC,EAAE,MAAM,CAAA;IAGb,OAAO,CAAC,EAAE;QAEN,SAAS,CAAC,EAAE,MAAM,CAAA;QAGlB,WAAW,CAAC,EAAE,MAAM,CAAA;QAGpB,kBAAkB,CAAC,EAAE,MAAM,CAAA;QAG3B,cAAc,CAAC,EAAE,MAAM,CAAA;QAGvB,OAAO,CAAC,EAAE,kBAAkB,EAAE,CAAA;QAG9B,QAAQ,CAAC,EAAE,cAAc,CAAA;QAGzB,UAAU,CAAC,EAAE,MAAM,CAAA;QAGnB,QAAQ,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,KAAK,CAAA;QAGrD,WAAW,CAAC,EAAE,MAAM,CAAA;KACvB,CAAA;IAGD,GAAG,CAAC,EAAE;QAEF,kBAAkB,CAAC,EAAE,MAAM,CAAA;KAC9B,CAAA;CACJ;AAED,MAAM,WAAW,kBAAkB;IAE/B,KAAK,EAAE,MAAM,CAAA;IAGb,UAAU,EAAE,MAAM,CAAA;IAGlB,IAAI,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,cAAc;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAA;IACzB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,qBAAqB;IAClC,cAAc,EAAE,CAAC,CAAC,EAAE,eAAe,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAA;IACrE,aAAa,EAAE,MAAM,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;IACnD,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACnC,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACpC,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,OAAO,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,eAAe,CAAA;IAC7B,YAAY,CAAC,EAAE,aAAa,CAAA;IAC5B,sBAAsB,CAAC,EAAE,CAAC,CAAC,EAAE,0BAA0B,KAAK,IAAI,CAAA;CACnE"}
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoAudioStream.types.js","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"","sourcesContent":["// packages/expo-audio-stream/src/ExpoAudioStream.types.ts\nimport {\n AmplitudeAlgorithm,\n AudioAnalysis,\n AudioFeaturesOptions,\n} from './AudioAnalysis/AudioAnalysis.types'\nimport { AudioAnalysisEvent } from './events'\n\nexport interface CompressionInfo {\n size: number\n mimeType: string\n bitrate: number\n format: string\n compressedFileUri?: string\n}\n\nexport interface AudioStreamStatus {\n isRecording: boolean\n isPaused: boolean\n durationMs: number\n size: number\n interval: number\n mimeType: string\n compression?: CompressionInfo\n}\n\nexport interface AudioDataEvent {\n data: string | Float32Array\n position: number\n fileUri: string\n eventDataSize: number\n totalSize: number\n compression?: CompressionInfo & {\n data?: string | Blob // Base64 (native) or Float32Array (web) encoded compressed data chunk\n }\n}\n\nexport type EncodingType = 'pcm_32bit' | 'pcm_16bit' | 'pcm_8bit'\nexport type SampleRate = 16000 | 44100 | 48000\nexport type BitDepth = 8 | 16 | 32\n\nexport type ConsoleLike = {\n log: (message: string, ...args: unknown[]) => void\n debug: (message: string, ...args: unknown[]) => void\n warn: (message: string, ...args: unknown[]) => void\n error: (message: string, ...args: unknown[]) => void\n}\n\nexport interface Chunk {\n text: string\n timestamp: [number, number | null]\n}\n\nexport interface TranscriberData {\n id: string\n isBusy: boolean\n text: string\n startTime: number\n endTime: number\n chunks: Chunk[]\n}\n\nexport interface AudioRecording {\n fileUri: string\n filename: string\n durationMs: number\n size: number\n mimeType: string\n channels: number\n bitDepth: BitDepth\n sampleRate: SampleRate\n createdAt?: number\n transcripts?: TranscriberData[]\n analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag\n compression?: CompressionInfo & {\n compressedFileUri: string\n }\n}\n\nexport interface StartRecordingResult {\n fileUri: string\n mimeType: string\n channels?: number\n bitDepth?: BitDepth\n sampleRate?: SampleRate\n compression?: CompressionInfo & {\n compressedFileUri: string\n }\n}\n\nexport interface AudioSessionConfig {\n category?:\n | 'Ambient'\n | 'SoloAmbient'\n | 'Playback'\n | 'Record'\n | 'PlayAndRecord'\n | 'MultiRoute'\n mode?:\n | 'Default'\n | 'VoiceChat'\n | 'VideoChat'\n | 'GameChat'\n | 'VideoRecording'\n | 'Measurement'\n | 'MoviePlayback'\n | 'SpokenAudio'\n categoryOptions?: (\n | 'MixWithOthers'\n | 'DuckOthers'\n | 'InterruptSpokenAudioAndMixWithOthers'\n | 'AllowBluetooth'\n | 'AllowBluetoothA2DP'\n | 'AllowAirPlay'\n | 'DefaultToSpeaker'\n )[]\n}\n\nexport interface IOSConfig {\n audioSession?: AudioSessionConfig\n}\n\n// Add new type for interruption reasons\nexport type RecordingInterruptionReason =\n | 'audioFocusLoss'\n | 'audioFocusGain'\n | 'phoneCall'\n | 'phoneCallEnded'\n | 'recordingStopped'\n\n// Add new interface for interruption events\nexport interface RecordingInterruptionEvent {\n reason: RecordingInterruptionReason\n isPaused: boolean\n}\n\nexport interface RecordingConfig {\n // Sample rate for recording (16000, 44100, or 48000 Hz)\n sampleRate?: SampleRate\n\n // Number of audio channels (1 for mono, 2 for stereo)\n channels?: 1 | 2\n\n // Encoding type for the recording (pcm_32bit, pcm_16bit, pcm_8bit)\n encoding?: EncodingType\n\n // Interval in milliseconds at which to emit recording data\n interval?: number\n\n // Continue recording when app is in background (default is true)\n keepAwake?: boolean\n\n // Show a notification during recording (default is false)\n showNotification?: boolean\n\n // Show waveform in the notification (Android only, when showNotification is true)\n showWaveformInNotification?: boolean\n\n // Configuration for the notification\n notification?: NotificationConfig\n\n // Enable audio processing (default is false)\n enableProcessing?: boolean\n\n // iOS-specific configuration\n ios?: IOSConfig\n\n // Number of data points to extract per second of audio (default is 1000)\n pointsPerSecond?: number\n\n // Algorithm to use for amplitude computation (default is \"rms\")\n algorithm?: AmplitudeAlgorithm\n\n // Feature options to extract (default is empty)\n features?: AudioFeaturesOptions\n\n // Callback function to handle audio stream\n onAudioStream?: (_: AudioDataEvent) => Promise<void>\n\n // Callback function to handle audio features extraction results\n onAudioAnalysis?: (_: AudioAnalysisEvent) => Promise<void>\n\n compression?: {\n enabled: boolean\n format: 'aac' | 'opus' | 'mp3'\n bitrate?: number\n }\n\n // Whether to automatically resume recording after an interruption (default is false)\n autoResumeAfterInterruption?: boolean\n\n // Optional callback to handle recording interruptions\n onRecordingInterrupted?: (_: RecordingInterruptionEvent) => void\n\n // Optional output configuration\n outputDirectory?: string // If not provided, uses default app directory\n filename?: string // If not provided, uses UUID\n}\n\nexport interface NotificationConfig {\n // Title of the notification\n title?: string\n\n // Main text content of the notification\n text?: string\n\n // Icon to be displayed in the notification (resource name or URI)\n icon?: string\n\n // Android-specific notification configuration\n android?: {\n // Unique identifier for the notification channel\n channelId?: string\n\n // User-visible name of the notification channel\n channelName?: string\n\n // User-visible description of the notification channel\n channelDescription?: string\n\n // Unique identifier for this notification\n notificationId?: number\n\n // List of actions that can be performed from the notification\n actions?: NotificationAction[]\n\n // Configuration for the waveform visualization in the notification\n waveform?: WaveformConfig\n\n // Color of the notification LED (if device supports it)\n lightColor?: string\n\n // Priority of the notification (affects how it's displayed)\n priority?: 'min' | 'low' | 'default' | 'high' | 'max'\n\n // Accent color for the notification (used for the app icon and buttons)\n accentColor?: string\n }\n\n // iOS-specific notification configuration\n ios?: {\n // Identifier for the notification category (used for grouping similar notifications)\n categoryIdentifier?: string\n }\n}\n\nexport interface NotificationAction {\n // Display title for the action\n title: string\n\n // Unique identifier for the action\n identifier: string\n\n // Icon to be displayed for the action (Android only)\n icon?: string\n}\n\nexport interface WaveformConfig {\n color?: string // The color of the waveform (e.g., \"#FFFFFF\" for white)\n opacity?: number // Opacity of the waveform (0.0 - 1.0)\n strokeWidth?: number // Width of the waveform line (default: 1.5)\n style?: 'stroke' | 'fill' // Drawing style: \"stroke\" for outline, \"fill\" for solid\n mirror?: boolean // Whether to mirror the waveform (symmetrical display)\n height?: number // Height of the waveform view in dp (default: 64)\n}\n\nexport interface UseAudioRecorderState {\n startRecording: (_: RecordingConfig) => Promise<StartRecordingResult>\n stopRecording: () => Promise<AudioRecording | null>\n pauseRecording: () => Promise<void>\n resumeRecording: () => Promise<void>\n isRecording: boolean\n isPaused: boolean\n durationMs: number // Duration of the recording\n size: number // Size in bytes of the recorded audio\n compression?: CompressionInfo\n analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag\n onRecordingInterrupted?: (_: RecordingInterruptionEvent) => void\n}\n"]}
1
+ {"version":3,"file":"ExpoAudioStream.types.js","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"","sourcesContent":["// packages/expo-audio-stream/src/ExpoAudioStream.types.ts\nimport {\n AmplitudeAlgorithm,\n AudioAnalysis,\n AudioFeaturesOptions,\n} from './AudioAnalysis/AudioAnalysis.types'\nimport { AudioAnalysisEvent } from './events'\n\nexport interface CompressionInfo {\n size: number\n mimeType: string\n bitrate: number\n format: string\n compressedFileUri?: string\n}\n\nexport interface AudioStreamStatus {\n isRecording: boolean\n isPaused: boolean\n durationMs: number\n size: number\n interval: number\n mimeType: string\n compression?: CompressionInfo\n}\n\nexport interface AudioDataEvent {\n data: string | Float32Array\n position: number\n fileUri: string\n eventDataSize: number\n totalSize: number\n compression?: CompressionInfo & {\n data?: string | Blob // Base64 (native) or Float32Array (web) encoded compressed data chunk\n }\n}\n\nexport type EncodingType = 'pcm_32bit' | 'pcm_16bit' | 'pcm_8bit'\nexport type SampleRate = 16000 | 44100 | 48000\nexport type BitDepth = 8 | 16 | 32\n\nexport type ConsoleLike = {\n log: (message: string, ...args: unknown[]) => void\n debug: (message: string, ...args: unknown[]) => void\n warn: (message: string, ...args: unknown[]) => void\n error: (message: string, ...args: unknown[]) => void\n}\n\nexport interface Chunk {\n text: string\n timestamp: [number, number | null]\n}\n\nexport interface TranscriberData {\n id: string\n isBusy: boolean\n text: string\n startTime: number\n endTime: number\n chunks: Chunk[]\n}\n\nexport interface AudioRecording {\n fileUri: string\n filename: string\n durationMs: number\n size: number\n mimeType: string\n channels: number\n bitDepth: BitDepth\n sampleRate: SampleRate\n createdAt?: number\n transcripts?: TranscriberData[]\n analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag\n compression?: CompressionInfo & {\n compressedFileUri: string\n }\n}\n\nexport interface StartRecordingResult {\n fileUri: string\n mimeType: string\n channels?: number\n bitDepth?: BitDepth\n sampleRate?: SampleRate\n compression?: CompressionInfo & {\n compressedFileUri: string\n }\n}\n\nexport interface AudioSessionConfig {\n category?:\n | 'Ambient'\n | 'SoloAmbient'\n | 'Playback'\n | 'Record'\n | 'PlayAndRecord'\n | 'MultiRoute'\n mode?:\n | 'Default'\n | 'VoiceChat'\n | 'VideoChat'\n | 'GameChat'\n | 'VideoRecording'\n | 'Measurement'\n | 'MoviePlayback'\n | 'SpokenAudio'\n categoryOptions?: (\n | 'MixWithOthers'\n | 'DuckOthers'\n | 'InterruptSpokenAudioAndMixWithOthers'\n | 'AllowBluetooth'\n | 'AllowBluetoothA2DP'\n | 'AllowAirPlay'\n | 'DefaultToSpeaker'\n )[]\n}\n\nexport interface IOSConfig {\n audioSession?: AudioSessionConfig\n}\n\n// Add new type for interruption reasons\nexport type RecordingInterruptionReason =\n | 'audioFocusLoss'\n | 'audioFocusGain'\n | 'phoneCall'\n | 'phoneCallEnded'\n | 'recordingStopped'\n\n// Add new interface for interruption events\nexport interface RecordingInterruptionEvent {\n reason: RecordingInterruptionReason\n isPaused: boolean\n}\n\nexport interface RecordingConfig {\n // Sample rate for recording (16000, 44100, or 48000 Hz)\n sampleRate?: SampleRate\n\n // Number of audio channels (1 for mono, 2 for stereo)\n channels?: 1 | 2\n\n // Encoding type for the recording (pcm_32bit, pcm_16bit, pcm_8bit)\n encoding?: EncodingType\n\n // Interval in milliseconds at which to emit recording data\n interval?: number\n\n // Continue recording when app is in background (default is true)\n keepAwake?: boolean\n\n // Show a notification during recording (default is false)\n showNotification?: boolean\n\n // Show waveform in the notification (Android only, when showNotification is true)\n showWaveformInNotification?: boolean\n\n // Configuration for the notification\n notification?: NotificationConfig\n\n // Enable audio processing (default is false)\n enableProcessing?: boolean\n\n // iOS-specific configuration\n ios?: IOSConfig\n\n // Number of data points to extract per second of audio (default is 1000)\n pointsPerSecond?: number\n\n // Algorithm to use for amplitude computation (default is \"rms\")\n algorithm?: AmplitudeAlgorithm\n\n // Feature options to extract (default is empty)\n features?: AudioFeaturesOptions\n\n // Callback function to handle audio stream\n onAudioStream?: (_: AudioDataEvent) => Promise<void>\n\n // Callback function to handle audio features extraction results\n onAudioAnalysis?: (_: AudioAnalysisEvent) => Promise<void>\n\n compression?: {\n enabled: boolean\n format: 'aac' | 'opus'\n bitrate?: number\n }\n\n // Whether to automatically resume recording after an interruption (default is false)\n autoResumeAfterInterruption?: boolean\n\n // Optional callback to handle recording interruptions\n onRecordingInterrupted?: (_: RecordingInterruptionEvent) => void\n\n // Optional output configuration\n outputDirectory?: string // If not provided, uses default app directory\n filename?: string // If not provided, uses UUID\n}\n\nexport interface NotificationConfig {\n // Title of the notification\n title?: string\n\n // Main text content of the notification\n text?: string\n\n // Icon to be displayed in the notification (resource name or URI)\n icon?: string\n\n // Android-specific notification configuration\n android?: {\n // Unique identifier for the notification channel\n channelId?: string\n\n // User-visible name of the notification channel\n channelName?: string\n\n // User-visible description of the notification channel\n channelDescription?: string\n\n // Unique identifier for this notification\n notificationId?: number\n\n // List of actions that can be performed from the notification\n actions?: NotificationAction[]\n\n // Configuration for the waveform visualization in the notification\n waveform?: WaveformConfig\n\n // Color of the notification LED (if device supports it)\n lightColor?: string\n\n // Priority of the notification (affects how it's displayed)\n priority?: 'min' | 'low' | 'default' | 'high' | 'max'\n\n // Accent color for the notification (used for the app icon and buttons)\n accentColor?: string\n }\n\n // iOS-specific notification configuration\n ios?: {\n // Identifier for the notification category (used for grouping similar notifications)\n categoryIdentifier?: string\n }\n}\n\nexport interface NotificationAction {\n // Display title for the action\n title: string\n\n // Unique identifier for the action\n identifier: string\n\n // Icon to be displayed for the action (Android only)\n icon?: string\n}\n\nexport interface WaveformConfig {\n color?: string // The color of the waveform (e.g., \"#FFFFFF\" for white)\n opacity?: number // Opacity of the waveform (0.0 - 1.0)\n strokeWidth?: number // Width of the waveform line (default: 1.5)\n style?: 'stroke' | 'fill' // Drawing style: \"stroke\" for outline, \"fill\" for solid\n mirror?: boolean // Whether to mirror the waveform (symmetrical display)\n height?: number // Height of the waveform view in dp (default: 64)\n}\n\nexport interface UseAudioRecorderState {\n startRecording: (_: RecordingConfig) => Promise<StartRecordingResult>\n stopRecording: () => Promise<AudioRecording | null>\n pauseRecording: () => Promise<void>\n resumeRecording: () => Promise<void>\n isRecording: boolean\n isPaused: boolean\n durationMs: number // Duration of the recording\n size: number // Size in bytes of the recorded audio\n compression?: CompressionInfo\n analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag\n onRecordingInterrupted?: (_: RecordingInterruptionEvent) => void\n}\n"]}
@@ -158,12 +158,11 @@ export function useAudioRecorder({ logger, audioWorkletUrl, featuresExtratorUrl,
158
158
  logger?.debug(`[handleAudioAnalysis] Updated analysis data: durationMs=${savedAnalysisData.durationMs}`, savedAnalysisData);
159
159
  // Call the onAudioAnalysis callback if it exists in the recording config
160
160
  if (recordingConfigRef.current?.onAudioAnalysis) {
161
- try {
162
- await recordingConfigRef.current.onAudioAnalysis(analysis);
163
- }
164
- catch (error) {
165
- logger?.error('Error in onAudioAnalysis callback:', error);
166
- }
161
+ recordingConfigRef.current
162
+ .onAudioAnalysis(analysis)
163
+ .catch((error) => {
164
+ logger?.warn(`Error processing audio analysis:`, error);
165
+ });
167
166
  }
168
167
  // Update the ref
169
168
  analysisRef.current = savedAnalysisData;
@@ -1 +1 @@
1
- {"version":3,"file":"useAudioRecorder.js","sourceRoot":"","sources":["../src/useAudioRecorder.tsx"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,OAAO,EAAqB,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC/D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAYlE,OAAO,qBAAqB,MAAM,yBAAyB,CAAA;AAC3D,OAAO,EACH,wBAAwB,EACxB,qBAAqB,EAErB,gCAAgC,GACnC,MAAM,UAAU,CAAA;AAiDjB,MAAM,eAAe,GAAkB;IACnC,eAAe,EAAE,EAAE;IACnB,QAAQ,EAAE,EAAE;IACZ,gBAAgB,EAAE,CAAC;IACnB,UAAU,EAAE,CAAC;IACb,UAAU,EAAE,KAAK;IACjB,OAAO,EAAE,CAAC;IACV,UAAU,EAAE,EAAE;IACd,kBAAkB,EAAE,KAAK;IACzB,cAAc,EAAE,EAAE;IAClB,cAAc,EAAE;QACZ,GAAG,EAAE,MAAM,CAAC,iBAAiB;QAC7B,GAAG,EAAE,MAAM,CAAC,iBAAiB;KAChC;CACJ,CAAA;AAED,SAAS,oBAAoB,CACzB,KAA2B,EAC3B,MAAsB;IAEtB,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,OAAO;YACR,OAAO;gBACH,GAAG,KAAK;gBACR,WAAW,EAAE,IAAI;gBACjB,QAAQ,EAAE,KAAK;gBACf,UAAU,EAAE,CAAC;gBACb,IAAI,EAAE,CAAC;gBACP,WAAW,EAAE,SAAS;gBACtB,YAAY,EAAE,eAAe;aAChC,CAAA;QACL,KAAK,MAAM;YACP,OAAO;gBACH,GAAG,KAAK;gBACR,WAAW,EAAE,KAAK;gBAClB,QAAQ,EAAE,KAAK;gBACf,UAAU,EAAE,CAAC;gBACb,IAAI,EAAE,CAAC;gBACP,WAAW,EAAE,SAAS;gBACtB,YAAY,EAAE,SAAS;aAC1B,CAAA;QACL,KAAK,OAAO;YACR,OAAO,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAA;QAC3D,KAAK,QAAQ;YACT,OAAO,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAA;QAC3D,KAAK,wBAAwB;YACzB,OAAO;gBACH,GAAG,KAAK;gBACR,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ;gBACjC,WAAW,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW;aAC1C,CAAA;QACL,KAAK,eAAe,CAAC,CAAC,CAAC;YACnB,MAAM,QAAQ,GAAG;gBACb,GAAG,KAAK;gBACR,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU;gBACrC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI;gBACzB,WAAW,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW;oBACnC,CAAC,CAAC;wBACI,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI;wBACrC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ;wBAC7C,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO;wBAC3C,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM;qBAC5C;oBACH,CAAC,CAAC,SAAS;aAClB,CAAA;YACD,OAAO,QAAQ,CAAA;QACnB,CAAC;QACD,KAAK,iBAAiB;YAClB,OAAO;gBACH,GAAG,KAAK;gBACR,YAAY,EAAE,MAAM,CAAC,OAAO;aAC/B,CAAA;QACL;YACI,OAAO,KAAK,CAAA;IACpB,CAAC;AACL,CAAC;AAOD,MAAM,UAAU,gBAAgB,CAAC,EAC7B,MAAM,EACN,eAAe,EACf,mBAAmB,MACI,EAAE;IACzB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,UAAU,CAAC,oBAAoB,EAAE;QACvD,WAAW,EAAE,KAAK;QAClB,QAAQ,EAAE,KAAK;QACf,UAAU,EAAE,CAAC;QACb,IAAI,EAAE,CAAC;QACP,WAAW,EAAE,SAAS;QACtB,YAAY,EAAE,SAAS;KAC1B,CAAC,CAAA;IAEF,MAAM,cAAc,GAAG,MAAM,CAA8B,IAAI,CAAC,CAAA;IAEhE,MAAM,mBAAmB,GAAG,MAAM,CAA2B,IAAI,CAAC,CAAA;IAClE,wEAAwE;IACxE,MAAM,WAAW,GAAG,MAAM,CAAgB,EAAE,GAAG,eAAe,EAAE,CAAC,CAAA;IACjE,8DAA8D;IAC9D,MAAM,eAAe,GAAG,MAAM,CAAgB;QAC1C,GAAG,eAAe;KACrB,CAAC,CAAA;IAEF,2CAA2C;IAC3C,MAAM,eAAe,GACjB,QAAQ,CAAC,EAAE,KAAK,KAAK;QACjB,CAAC,CAAC,qBAAqB,CAAC;YAClB,eAAe;YACf,mBAAmB;YACnB,MAAM;SACT,CAAC;QACJ,CAAC,CAAC,qBAAqB,CAAA;IAE/B,MAAM,gBAAgB,GAAG,MAAM,CAE7B,IAAI,CAAC,CAAA;IAEP,MAAM,QAAQ,GAAG,MAAM,CAAC;QACpB,WAAW,EAAE,KAAK;QAClB,QAAQ,EAAE,KAAK;QACf,UAAU,EAAE,CAAC;QACb,IAAI,EAAE,CAAC;QACP,WAAW,EAAE,SAAwC;KACxD,CAAC,CAAA;IAEF,MAAM,kBAAkB,GAAG,MAAM,CAAyB,IAAI,CAAC,CAAA;IAE/D,MAAM,mBAAmB,GAAG,WAAW,CACnC,KAAK,EAAE,EACH,QAAQ,EACR,qBAAqB,GACE,EAAE,EAAE;QAC3B,MAAM,iBAAiB,GAAG,WAAW,CAAC,OAAO,IAAI;YAC7C,GAAG,eAAe;SACrB,CAAA;QAED,MAAM,WAAW,GAAG,qBAAqB,CAAA;QAEzC,MAAM,EAAE,KAAK,CACT,8DAA8D,WAAW,wBAAwB,QAAQ,CAAC,UAAU,CAAC,MAAM,4BAA4B,iBAAiB,CAAC,UAAU,CAAC,MAAM,EAAE,EAC5L,QAAQ,CACX,CAAA;QAED,sBAAsB;QACtB,MAAM,kBAAkB,GAAG;YACvB,GAAG,iBAAiB,CAAC,UAAU;YAC/B,GAAG,QAAQ,CAAC,UAAU;SACzB,CAAA;QAED,MAAM,sBAAsB,GAAG;YAC3B,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,UAAU,IAAI,EAAE,CAAC;YAC9C,GAAG,QAAQ,CAAC,UAAU;SACzB,CAAA;QAED,6BAA6B;QAC7B,MAAM,eAAe,GACjB,QAAQ,CAAC,eAAe,IAAI,iBAAiB,CAAC,eAAe,CAAA;QACjE,MAAM,aAAa,GACf,CAAC,eAAe,GAAG,qBAAqB,CAAC,GAAG,IAAI,CAAA;QAEpD,MAAM,EAAE,KAAK,CACT,+EAA+E,eAAe,0BAA0B,qBAAqB,6BAA6B,kBAAkB,CAAC,MAAM,qBAAqB,aAAa,EAAE,CAC1O,CAAA;QAED,oEAAoE;QACpE,IAAI,kBAAkB,CAAC,MAAM,GAAG,aAAa,EAAE,CAAC;YAC5C,kBAAkB,CAAC,MAAM,CACrB,CAAC,EACD,kBAAkB,CAAC,MAAM,GAAG,aAAa,CAC5C,CAAA;QACL,CAAC;QAED,4BAA4B;QAC5B,eAAe,CAAC,OAAO,GAAG;YACtB,GAAG,eAAe,CAAC,OAAO;YAC1B,UAAU,EAAE,sBAAsB;SACrC,CAAA;QACD,eAAe,CAAC,OAAO,CAAC,UAAU;YAC9B,sBAAsB,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,eAAe,CAAC,CAAA;QAC5D,iBAAiB,CAAC,UAAU,GAAG,kBAAkB,CAAA;QACjD,iBAAiB,CAAC,QAAQ;YACtB,QAAQ,CAAC,QAAQ,IAAI,iBAAiB,CAAC,QAAQ,CAAA;QACnD,iBAAiB,CAAC,UAAU;YACxB,kBAAkB,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,eAAe,CAAC,CAAA;QAExD,yBAAyB;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACnB,iBAAiB,CAAC,cAAc,CAAC,GAAG,EACpC,QAAQ,CAAC,cAAc,CAAC,GAAG,CAC9B,CAAA;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACnB,iBAAiB,CAAC,cAAc,CAAC,GAAG,EACpC,QAAQ,CAAC,cAAc,CAAC,GAAG,CAC9B,CAAA;QAED,iBAAiB,CAAC,cAAc,GAAG;YAC/B,GAAG,EAAE,MAAM;YACX,GAAG,EAAE,MAAM;SACd,CAAA;QACD,eAAe,CAAC,OAAO,CAAC,cAAc,GAAG;YACrC,GAAG,EAAE,MAAM;YACX,GAAG,EAAE,MAAM;SACd,CAAA;QAED,MAAM,EAAE,KAAK,CACT,2DAA2D,iBAAiB,CAAC,UAAU,EAAE,EACzF,iBAAiB,CACpB,CAAA;QAED,yEAAyE;QACzE,IAAI,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,CAAC;YAC9C,IAAI,CAAC;gBACD,MAAM,kBAAkB,CAAC,OAAO,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAA;YAC9D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,MAAM,EAAE,KAAK,CAAC,oCAAoC,EAAE,KAAK,CAAC,CAAA;YAC9D,CAAC;QACL,CAAC;QAED,iBAAiB;QACjB,WAAW,CAAC,OAAO,GAAG,iBAAiB,CAAA;QAEvC,mEAAmE;QACnE,QAAQ,CAAC;YACL,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,EAAE,GAAG,iBAAiB,EAAE;SACpC,CAAC,CAAA;IACN,CAAC,EACD,CAAC,QAAQ,CAAC,CACb,CAAA;IAED,MAAM,gBAAgB,GAAG,WAAW,CAChC,KAAK,EAAE,SAA4B,EAAE,EAAE;QACnC,MAAM,EACF,OAAO,EACP,SAAS,EACT,SAAS,EACT,eAAe,EACf,QAAQ,EACR,UAAU,EACV,OAAO,EACP,QAAQ,EACR,MAAM,EACN,WAAW,GACd,GAAG,SAAS,CAAA;QACb,MAAM,EAAE,KAAK,CAAC,0CAA0C,EAAE;YACtD,OAAO;YACP,SAAS;YACT,SAAS;YACT,QAAQ;YACR,QAAQ;YACR,eAAe;YACf,UAAU;YACV,aAAa,EAAE,OAAO,EAAE,MAAM;YAC9B,WAAW;SACd,CAAC,CAAA;QACF,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;YAClB,6BAA6B;YAC7B,OAAM;QACV,CAAC;QACD,IAAI,CAAC;YACD,+DAA+D;YAC/D,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;gBACxB,wDAAwD;gBACxD,IAAI,CAAC,OAAO,EAAE,CAAC;oBACX,MAAM,EAAE,KAAK,CAAC,+BAA+B,CAAC,CAAA;oBAC9C,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;gBACpD,CAAC;gBACD,gBAAgB,CAAC,OAAO,EAAE,CAAC;oBACvB,IAAI,EAAE,OAAO;oBACb,QAAQ;oBACR,OAAO;oBACP,aAAa,EAAE,SAAS;oBACxB,SAAS;oBACT,WAAW,EACP,WAAW,IAAI,cAAc,CAAC,OAAO,EAAE,WAAW;wBAC9C,CAAC,CAAC;4BACI,IAAI,EAAE,WAAW,CAAC,IAAI;4BACtB,IAAI,EAAE,WAAW,CAAC,SAAS;4BAC3B,QAAQ,EACJ,cAAc,CAAC,OAAO,CAAC,WAAW;gCAC9B,EAAE,QAAQ;4BAClB,OAAO,EACH,cAAc,CAAC,OAAO,CAAC,WAAW;gCAC9B,EAAE,OAAO;4BACjB,MAAM,EAAE,cAAc,CAAC,OAAO,CAAC,WAAW;gCACtC,EAAE,MAAM;yBACf;wBACH,CAAC,CAAC,SAAS;iBACtB,CAAC,CAAA;YACN,CAAC;iBAAM,IAAI,MAAM,EAAE,CAAC;gBAChB,kBAAkB;gBAClB,MAAM,QAAQ,GAAmB;oBAC7B,IAAI,EAAE,MAAM;oBACZ,QAAQ;oBACR,OAAO;oBACP,aAAa,EAAE,SAAS;oBACxB,SAAS;oBACT,WAAW,EACP,WAAW,IAAI,cAAc,CAAC,OAAO,EAAE,WAAW;wBAC9C,CAAC,CAAC;4BACI,IAAI,EAAE,WAAW,CAAC,IAAI;4BACtB,IAAI,EAAE,WAAW,CAAC,SAAS;4BAC3B,QAAQ,EACJ,cAAc,CAAC,OAAO,CAAC,WAAW;gCAC9B,EAAE,QAAQ;4BAClB,OAAO,EACH,cAAc,CAAC,OAAO,CAAC,WAAW;gCAC9B,EAAE,OAAO;4BACjB,MAAM,EAAE,cAAc,CAAC,OAAO,CAAC,WAAW;gCACtC,EAAE,MAAM;yBACf;wBACH,CAAC,CAAC,SAAS;iBACtB,CAAA;gBACD,gBAAgB,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,CAAA;gBACpC,MAAM,EAAE,KAAK,CACT,qDAAqD,EACrD,QAAQ,CACX,CAAA;YACL,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,EAAE,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAA;QACzD,CAAC;IACL,CAAC,EACD,EAAE,CACL,CAAA;IAED,MAAM,WAAW,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACvC,IAAI,CAAC;YACD,MAAM,MAAM,GAAsB,eAAe,CAAC,MAAM,EAAE,CAAA;YAC1D,MAAM,EAAE,KAAK,CACT,mBAAmB,MAAM,CAAC,QAAQ,iBAAiB,MAAM,CAAC,WAAW,gBAAgB,MAAM,CAAC,UAAU,UAAU,MAAM,CAAC,IAAI,EAAE,EAC7H,MAAM,CAAC,WAAW,CACrB,CAAA;YAED,2CAA2C;YAC3C,IACI,MAAM,CAAC,WAAW,KAAK,QAAQ,CAAC,OAAO,CAAC,WAAW;gBACnD,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAC/C,CAAC;gBACC,QAAQ,CAAC,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAA;gBACjD,QAAQ,CAAC,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAA;gBAC3C,QAAQ,CAAC;oBACL,IAAI,EAAE,wBAAwB;oBAC9B,OAAO,EAAE;wBACL,WAAW,EAAE,MAAM,CAAC,WAAW;wBAC/B,QAAQ,EAAE,MAAM,CAAC,QAAQ;qBAC5B;iBACJ,CAAC,CAAA;YACN,CAAC;YAED,IACI,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC,OAAO,CAAC,UAAU;gBACjD,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,OAAO,CAAC,IAAI,EACvC,CAAC;gBACC,QAAQ,CAAC,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAA;gBAC/C,QAAQ,CAAC,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAA;gBACnC,QAAQ,CAAC,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAA;gBACjD,QAAQ,CAAC;oBACL,IAAI,EAAE,eAAe;oBACrB,OAAO,EAAE;wBACL,UAAU,EAAE,MAAM,CAAC,UAAU;wBAC7B,IAAI,EAAE,MAAM,CAAC,IAAI;wBACjB,WAAW,EAAE,MAAM,CAAC,WAAW;qBAClC;iBACJ,CAAC,CAAA;YACN,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,EAAE,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAA;QACjD,CAAC;IACL,CAAC,EAAE,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAA,CAAC,4CAA4C;IAE1E,gCAAgC;IAChC,SAAS,CAAC,GAAG,EAAE;QACX,QAAQ,CAAC,OAAO,GAAG;YACf,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,WAAW,EAAE,KAAK,CAAC,WAAW;SACjC,CAAA;IACL,CAAC,EAAE;QACC,KAAK,CAAC,WAAW;QACjB,KAAK,CAAC,QAAQ;QACd,KAAK,CAAC,UAAU;QAChB,KAAK,CAAC,IAAI;QACV,KAAK,CAAC,WAAW;KACpB,CAAC,CAAA;IAEF,MAAM,cAAc,GAAG,WAAW,CAC9B,KAAK,EAAE,gBAAiC,EAAE,EAAE;QACxC,kBAAkB,CAAC,OAAO,GAAG,gBAAgB,CAAA;QAC7C,MAAM,EAAE,KAAK,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAA;QAEjD,WAAW,CAAC,OAAO,GAAG,EAAE,GAAG,eAAe,EAAE,CAAA,CAAC,sBAAsB;QACnE,eAAe,CAAC,OAAO,GAAG,EAAE,GAAG,eAAe,EAAE,CAAA;QAChD,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,GAAG,gBAAgB,CAAA;QACtD,MAAM,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAA;QAEpC,MAAM,qBAAqB,GAAG,KAAK,CAAA,CAAC,gEAAgE;QACpG,IAAI,OAAO,aAAa,KAAK,UAAU,EAAE,CAAC;YACtC,gBAAgB,CAAC,OAAO,GAAG,aAAa,CAAA;QAC5C,CAAC;aAAM,CAAC;YACJ,MAAM,EAAE,IAAI,CAAC,iCAAiC,EAAE,aAAa,CAAC,CAAA;YAC9D,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAA;QACnC,CAAC;QACD,MAAM,WAAW,GACb,MAAM,eAAe,CAAC,cAAc,CAAC,OAAO,CAAC,CAAA;QACjD,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;QAE3B,cAAc,CAAC,OAAO,GAAG,WAAW,CAAA;QAEpC,IAAI,gBAAgB,EAAE,CAAC;YACnB,MAAM,EAAE,KAAK,CAAC,kCAAkC,CAAC,CAAA;YACjD,MAAM,QAAQ,GAAG,wBAAwB,CACrC,KAAK,EAAE,YAAY,EAAE,EAAE;gBACnB,IAAI,CAAC;oBACD,MAAM,mBAAmB,CAAC;wBACtB,QAAQ,EAAE,YAAY;wBACtB,qBAAqB,EAAE,qBAAqB;qBAC/C,CAAC,CAAA;gBACN,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACb,MAAM,EAAE,IAAI,CACR,kCAAkC,EAClC,KAAK,CACR,CAAA;gBACL,CAAC;YACL,CAAC,CACJ,CAAA;YAED,mBAAmB,CAAC,OAAO,GAAG,QAAQ,CAAA;QAC1C,CAAC;QAED,OAAO,WAAW,CAAA;IACtB,CAAC,EACD,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAClC,CAAA;IAED,MAAM,aAAa,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACzC,MAAM,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAA;QAElC,MAAM,UAAU,GAAmB,MAAM,eAAe,CAAC,aAAa,EAAE,CAAA;QACxE,UAAU,CAAC,YAAY,GAAG,eAAe,CAAC,OAAO,CAAA;QAEjD,IAAI,mBAAmB,CAAC,OAAO,EAAE,CAAC;YAC9B,mBAAmB,CAAC,OAAO,CAAC,MAAM,EAAE,CAAA;YACpC,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAA;QACtC,CAAC;QACD,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAA;QAC/B,MAAM,EAAE,KAAK,CAAC,mBAAmB,EAAE,UAAU,CAAC,CAAA;QAC9C,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;QAC1B,OAAO,UAAU,CAAA;IACrB,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,MAAM,cAAc,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC1C,MAAM,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAA;QAChC,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,cAAc,EAAE,CAAA;QAC1D,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;QAC3B,OAAO,WAAW,CAAA;IACtB,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,MAAM,eAAe,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC3C,MAAM,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAA;QACjC,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,eAAe,EAAE,CAAA;QAC5D,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;QAC5B,OAAO,YAAY,CAAA;IACvB,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,UAAsC,CAAA;QAE1C,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACtC,yCAAyC;YACzC,WAAW,EAAE,CAAA;YAEb,iBAAiB;YACjB,UAAU,GAAG,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,CAAA;QAC/C,CAAC;QAED,OAAO,GAAG,EAAE;YACR,IAAI,UAAU,EAAE,CAAC;gBACb,aAAa,CAAC,UAAU,CAAC,CAAA;gBACzB,UAAU,GAAG,SAAS,CAAA;YAC1B,CAAC;QACL,CAAC,CAAA;IACL,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEpD,SAAS,CAAC,GAAG,EAAE;QACX,MAAM,EAAE,KAAK,CAAC,kCAAkC,CAAC,CAAA;QACjD,MAAM,cAAc,GAAG,qBAAqB,CAAC,gBAAgB,CAAC,CAAA;QAE9D,MAAM,EAAE,KAAK,CACT,0DAA0D,EAC1D;YACI,cAAc;SACjB,CACJ,CAAA;QAED,OAAO,GAAG,EAAE;YACR,MAAM,EAAE,KAAK,CAAC,+BAA+B,CAAC,CAAA;YAC9C,cAAc,CAAC,MAAM,EAAE,CAAA;QAC3B,CAAC,CAAA;IACL,CAAC,EAAE,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,CAAC,CAAA;IAE3C,SAAS,CAAC,GAAG,EAAE;QACX,qDAAqD;QACrD,MAAM,EAAE,KAAK,CAAC,4CAA4C,CAAC,CAAA;QAE3D,MAAM,YAAY,GAAG,gCAAgC,CAAC,CAAC,KAAK,EAAE,EAAE;YAC5D,MAAM,EAAE,KAAK,CAAC,wCAAwC,EAAE,KAAK,CAAC,CAAA;YAE9D,yCAAyC;YACzC,IAAI,kBAAkB,CAAC,OAAO,EAAE,sBAAsB,EAAE,CAAC;gBACrD,IAAI,CAAC;oBACD,kBAAkB,CAAC,OAAO,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAA;gBAC5D,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACb,MAAM,EAAE,KAAK,CACT,2CAA2C,EAC3C,KAAK,CACR,CAAA;gBACL,CAAC;YACL,CAAC;iBAAM,CAAC;gBACJ,MAAM,EAAE,IAAI,CAAC,+CAA+C,CAAC,CAAA;YACjE,CAAC;QACL,CAAC,CAAC,CAAA;QAEF,OAAO,GAAG,EAAE;YACR,MAAM,EAAE,KAAK,CAAC,0CAA0C,CAAC,CAAA;YACzD,YAAY,CAAC,MAAM,EAAE,CAAA;QACzB,CAAC,CAAA;IACL,CAAC,EAAE,EAAE,CAAC,CAAA,CAAC,wDAAwD;IAE/D,OAAO;QACH,cAAc;QACd,aAAa;QACb,cAAc;QACd,eAAe;QACf,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,YAAY,EAAE,KAAK,CAAC,YAAY;KACnC,CAAA;AACL,CAAC","sourcesContent":["// src/useAudioRecorder.ts\nimport { EventSubscription, Platform } from 'expo-modules-core'\nimport { useCallback, useEffect, useReducer, useRef } from 'react'\n\nimport { AudioAnalysis } from './AudioAnalysis/AudioAnalysis.types'\nimport {\n AudioDataEvent,\n AudioRecording,\n AudioStreamStatus,\n CompressionInfo,\n ConsoleLike,\n RecordingConfig,\n StartRecordingResult,\n} from './ExpoAudioStream.types'\nimport ExpoAudioStreamModule from './ExpoAudioStreamModule'\nimport {\n addAudioAnalysisListener,\n addAudioEventListener,\n AudioEventPayload,\n addRecordingInterruptionListener,\n} from './events'\n\nexport interface UseAudioRecorderProps {\n logger?: ConsoleLike\n audioWorkletUrl?: string\n featuresExtratorUrl?: string\n}\n\nexport interface UseAudioRecorderState {\n startRecording: (_: RecordingConfig) => Promise<StartRecordingResult>\n stopRecording: () => Promise<AudioRecording>\n pauseRecording: () => Promise<void>\n resumeRecording: () => Promise<void>\n isRecording: boolean\n isPaused: boolean\n durationMs: number\n size: number\n compression?: CompressionInfo\n analysisData?: AudioAnalysis\n}\n\ninterface RecorderReducerState {\n isRecording: boolean\n isPaused: boolean\n durationMs: number\n size: number\n compression?: CompressionInfo\n analysisData?: AudioAnalysis\n}\n\ntype RecorderAction =\n | { type: 'START' | 'STOP' | 'PAUSE' | 'RESUME' }\n | {\n type: 'UPDATE_RECORDING_STATE'\n payload: {\n isRecording: boolean\n isPaused: boolean\n }\n }\n | {\n type: 'UPDATE_STATUS'\n payload: {\n durationMs: number\n size: number\n compression?: CompressionInfo\n }\n }\n | { type: 'UPDATE_ANALYSIS'; payload: AudioAnalysis }\n\nconst defaultAnalysis: AudioAnalysis = {\n pointsPerSecond: 10,\n bitDepth: 32,\n numberOfChannels: 1,\n durationMs: 0,\n sampleRate: 44100,\n samples: 0,\n dataPoints: [],\n amplitudeAlgorithm: 'rms',\n speakerChanges: [],\n amplitudeRange: {\n min: Number.POSITIVE_INFINITY,\n max: Number.NEGATIVE_INFINITY,\n },\n}\n\nfunction audioRecorderReducer(\n state: RecorderReducerState,\n action: RecorderAction\n): RecorderReducerState {\n switch (action.type) {\n case 'START':\n return {\n ...state,\n isRecording: true,\n isPaused: false,\n durationMs: 0,\n size: 0,\n compression: undefined,\n analysisData: defaultAnalysis,\n }\n case 'STOP':\n return {\n ...state,\n isRecording: false,\n isPaused: false,\n durationMs: 0,\n size: 0,\n compression: undefined,\n analysisData: undefined,\n }\n case 'PAUSE':\n return { ...state, isPaused: true, isRecording: false }\n case 'RESUME':\n return { ...state, isPaused: false, isRecording: true }\n case 'UPDATE_RECORDING_STATE':\n return {\n ...state,\n isPaused: action.payload.isPaused,\n isRecording: action.payload.isRecording,\n }\n case 'UPDATE_STATUS': {\n const newState = {\n ...state,\n durationMs: action.payload.durationMs,\n size: action.payload.size,\n compression: action.payload.compression\n ? {\n size: action.payload.compression.size,\n mimeType: action.payload.compression.mimeType,\n bitrate: action.payload.compression.bitrate,\n format: action.payload.compression.format,\n }\n : undefined,\n }\n return newState\n }\n case 'UPDATE_ANALYSIS':\n return {\n ...state,\n analysisData: action.payload,\n }\n default:\n return state\n }\n}\n\ninterface HandleAudioAnalysisProps {\n analysis: AudioAnalysis\n visualizationDuration: number\n}\n\nexport function useAudioRecorder({\n logger,\n audioWorkletUrl,\n featuresExtratorUrl,\n}: UseAudioRecorderProps = {}): UseAudioRecorderState {\n const [state, dispatch] = useReducer(audioRecorderReducer, {\n isRecording: false,\n isPaused: false,\n durationMs: 0,\n size: 0,\n compression: undefined,\n analysisData: undefined,\n })\n\n const startResultRef = useRef<StartRecordingResult | null>(null)\n\n const analysisListenerRef = useRef<EventSubscription | null>(null)\n // analysisRef is the current analysis data (last 10 seconds by default)\n const analysisRef = useRef<AudioAnalysis>({ ...defaultAnalysis })\n // fullAnalysisRef is the full analysis data (all data points)\n const fullAnalysisRef = useRef<AudioAnalysis>({\n ...defaultAnalysis,\n })\n\n // Instantiate the module for web with URLs\n const ExpoAudioStream =\n Platform.OS === 'web'\n ? ExpoAudioStreamModule({\n audioWorkletUrl,\n featuresExtratorUrl,\n logger,\n })\n : ExpoAudioStreamModule\n\n const onAudioStreamRef = useRef<\n ((_: AudioDataEvent) => Promise<void>) | null\n >(null)\n\n const stateRef = useRef({\n isRecording: false,\n isPaused: false,\n durationMs: 0,\n size: 0,\n compression: undefined as CompressionInfo | undefined,\n })\n\n const recordingConfigRef = useRef<RecordingConfig | null>(null)\n\n const handleAudioAnalysis = useCallback(\n async ({\n analysis,\n visualizationDuration,\n }: HandleAudioAnalysisProps) => {\n const savedAnalysisData = analysisRef.current || {\n ...defaultAnalysis,\n }\n\n const maxDuration = visualizationDuration\n\n logger?.debug(\n `[handleAudioAnalysis] Received audio analysis: maxDuration=${maxDuration} analysis.dataPoints=${analysis.dataPoints.length} analysisData.dataPoints=${savedAnalysisData.dataPoints.length}`,\n analysis\n )\n\n // Combine data points\n const combinedDataPoints = [\n ...savedAnalysisData.dataPoints,\n ...analysis.dataPoints,\n ]\n\n const fullCombinedDataPoints = [\n ...(fullAnalysisRef.current?.dataPoints ?? []),\n ...analysis.dataPoints,\n ]\n\n // Calculate the new duration\n const pointsPerSecond =\n analysis.pointsPerSecond || savedAnalysisData.pointsPerSecond\n const maxDataPoints =\n (pointsPerSecond * visualizationDuration) / 1000\n\n logger?.debug(\n `[handleAudioAnalysis] Combined data points before trimming: pointsPerSecond=${pointsPerSecond} visualizationDuration=${visualizationDuration} combinedDataPointsLength=${combinedDataPoints.length} vs maxDataPoints=${maxDataPoints}`\n )\n\n // Trim data points to keep within the maximum number of data points\n if (combinedDataPoints.length > maxDataPoints) {\n combinedDataPoints.splice(\n 0,\n combinedDataPoints.length - maxDataPoints\n )\n }\n\n // Keep the full data points\n fullAnalysisRef.current = {\n ...fullAnalysisRef.current,\n dataPoints: fullCombinedDataPoints,\n }\n fullAnalysisRef.current.durationMs =\n fullCombinedDataPoints.length * (1000 / pointsPerSecond)\n savedAnalysisData.dataPoints = combinedDataPoints\n savedAnalysisData.bitDepth =\n analysis.bitDepth || savedAnalysisData.bitDepth\n savedAnalysisData.durationMs =\n combinedDataPoints.length * (1000 / pointsPerSecond)\n\n // Update amplitude range\n const newMin = Math.min(\n savedAnalysisData.amplitudeRange.min,\n analysis.amplitudeRange.min\n )\n const newMax = Math.max(\n savedAnalysisData.amplitudeRange.max,\n analysis.amplitudeRange.max\n )\n\n savedAnalysisData.amplitudeRange = {\n min: newMin,\n max: newMax,\n }\n fullAnalysisRef.current.amplitudeRange = {\n min: newMin,\n max: newMax,\n }\n\n logger?.debug(\n `[handleAudioAnalysis] Updated analysis data: durationMs=${savedAnalysisData.durationMs}`,\n savedAnalysisData\n )\n\n // Call the onAudioAnalysis callback if it exists in the recording config\n if (recordingConfigRef.current?.onAudioAnalysis) {\n try {\n await recordingConfigRef.current.onAudioAnalysis(analysis)\n } catch (error) {\n logger?.error('Error in onAudioAnalysis callback:', error)\n }\n }\n\n // Update the ref\n analysisRef.current = savedAnalysisData\n\n // Dispatch the updated analysis data to state to trigger re-render\n dispatch({\n type: 'UPDATE_ANALYSIS',\n payload: { ...savedAnalysisData },\n })\n },\n [dispatch]\n )\n\n const handleAudioEvent = useCallback(\n async (eventData: AudioEventPayload) => {\n const {\n fileUri,\n deltaSize,\n totalSize,\n lastEmittedSize,\n position,\n streamUuid,\n encoded,\n mimeType,\n buffer,\n compression,\n } = eventData\n logger?.debug(`[handleAudioEvent] Received audio event:`, {\n fileUri,\n deltaSize,\n totalSize,\n position,\n mimeType,\n lastEmittedSize,\n streamUuid,\n encodedLength: encoded?.length,\n compression,\n })\n if (deltaSize === 0) {\n // Ignore packet with no data\n return\n }\n try {\n // Coming from native ( ios / android ) otherwise buffer is set\n if (Platform.OS !== 'web') {\n // Read the audio file as a base64 string for comparison\n if (!encoded) {\n logger?.error(`Encoded audio data is missing`)\n throw new Error('Encoded audio data is missing')\n }\n onAudioStreamRef.current?.({\n data: encoded,\n position,\n fileUri,\n eventDataSize: deltaSize,\n totalSize,\n compression:\n compression && startResultRef.current?.compression\n ? {\n data: compression.data,\n size: compression.totalSize,\n mimeType:\n startResultRef.current.compression\n ?.mimeType,\n bitrate:\n startResultRef.current.compression\n ?.bitrate,\n format: startResultRef.current.compression\n ?.format,\n }\n : undefined,\n })\n } else if (buffer) {\n // Coming from web\n const webEvent: AudioDataEvent = {\n data: buffer,\n position,\n fileUri,\n eventDataSize: deltaSize,\n totalSize,\n compression:\n compression && startResultRef.current?.compression\n ? {\n data: compression.data,\n size: compression.totalSize,\n mimeType:\n startResultRef.current.compression\n ?.mimeType,\n bitrate:\n startResultRef.current.compression\n ?.bitrate,\n format: startResultRef.current.compression\n ?.format,\n }\n : undefined,\n }\n onAudioStreamRef.current?.(webEvent)\n logger?.debug(\n `[handleAudioEvent] Audio data sent to onAudioStream`,\n webEvent\n )\n }\n } catch (error) {\n logger?.error(`Error processing audio event:`, error)\n }\n },\n []\n )\n\n const checkStatus = useCallback(async () => {\n try {\n const status: AudioStreamStatus = ExpoAudioStream.status()\n logger?.debug(\n `Status: paused: ${status.isPaused} isRecording: ${status.isRecording} durationMs: ${status.durationMs} size: ${status.size}`,\n status.compression\n )\n\n // Only dispatch if values actually changed\n if (\n status.isRecording !== stateRef.current.isRecording ||\n status.isPaused !== stateRef.current.isPaused\n ) {\n stateRef.current.isRecording = status.isRecording\n stateRef.current.isPaused = status.isPaused\n dispatch({\n type: 'UPDATE_RECORDING_STATE',\n payload: {\n isRecording: status.isRecording,\n isPaused: status.isPaused,\n },\n })\n }\n\n if (\n status.durationMs !== stateRef.current.durationMs ||\n status.size !== stateRef.current.size\n ) {\n stateRef.current.durationMs = status.durationMs\n stateRef.current.size = status.size\n stateRef.current.compression = status.compression\n dispatch({\n type: 'UPDATE_STATUS',\n payload: {\n durationMs: status.durationMs,\n size: status.size,\n compression: status.compression,\n },\n })\n }\n } catch (error) {\n logger?.error(`Error getting status:`, error)\n }\n }, [ExpoAudioStream, logger]) // Only depend on ExpoAudioStream and logger\n\n // Update ref when state changes\n useEffect(() => {\n stateRef.current = {\n isRecording: state.isRecording,\n isPaused: state.isPaused,\n durationMs: state.durationMs,\n size: state.size,\n compression: state.compression,\n }\n }, [\n state.isRecording,\n state.isPaused,\n state.durationMs,\n state.size,\n state.compression,\n ])\n\n const startRecording = useCallback(\n async (recordingOptions: RecordingConfig) => {\n recordingConfigRef.current = recordingOptions\n logger?.debug(`start recoding`, recordingOptions)\n\n analysisRef.current = { ...defaultAnalysis } // Reset analysis data\n fullAnalysisRef.current = { ...defaultAnalysis }\n const { onAudioStream, ...options } = recordingOptions\n const { enableProcessing } = options\n\n const maxRecentDataDuration = 10000 // TODO compute maxRecentDataDuration based on screen dimensions\n if (typeof onAudioStream === 'function') {\n onAudioStreamRef.current = onAudioStream\n } else {\n logger?.warn(`onAudioStream is not a function`, onAudioStream)\n onAudioStreamRef.current = null\n }\n const startResult: StartRecordingResult =\n await ExpoAudioStream.startRecording(options)\n dispatch({ type: 'START' })\n\n startResultRef.current = startResult\n\n if (enableProcessing) {\n logger?.debug(`Enabling audio analysis listener`)\n const listener = addAudioAnalysisListener(\n async (analysisData) => {\n try {\n await handleAudioAnalysis({\n analysis: analysisData,\n visualizationDuration: maxRecentDataDuration,\n })\n } catch (error) {\n logger?.warn(\n `Error processing audio analysis:`,\n error\n )\n }\n }\n )\n\n analysisListenerRef.current = listener\n }\n\n return startResult\n },\n [handleAudioAnalysis, dispatch]\n )\n\n const stopRecording = useCallback(async () => {\n logger?.debug(`stoping recording`)\n\n const stopResult: AudioRecording = await ExpoAudioStream.stopRecording()\n stopResult.analysisData = fullAnalysisRef.current\n\n if (analysisListenerRef.current) {\n analysisListenerRef.current.remove()\n analysisListenerRef.current = null\n }\n onAudioStreamRef.current = null\n logger?.debug(`recording stopped`, stopResult)\n dispatch({ type: 'STOP' })\n return stopResult\n }, [dispatch])\n\n const pauseRecording = useCallback(async () => {\n logger?.debug(`pause recording`)\n const pauseResult = await ExpoAudioStream.pauseRecording()\n dispatch({ type: 'PAUSE' })\n return pauseResult\n }, [dispatch])\n\n const resumeRecording = useCallback(async () => {\n logger?.debug(`resume recording`)\n const resumeResult = await ExpoAudioStream.resumeRecording()\n dispatch({ type: 'RESUME' })\n return resumeResult\n }, [dispatch])\n\n useEffect(() => {\n let intervalId: NodeJS.Timeout | undefined\n\n if (state.isRecording || state.isPaused) {\n // Immediately check status when starting\n checkStatus()\n\n // Start interval\n intervalId = setInterval(checkStatus, 1000)\n }\n\n return () => {\n if (intervalId) {\n clearInterval(intervalId)\n intervalId = undefined\n }\n }\n }, [checkStatus, state.isRecording, state.isPaused])\n\n useEffect(() => {\n logger?.debug(`Registering audio event listener`)\n const subscribeAudio = addAudioEventListener(handleAudioEvent)\n\n logger?.debug(\n `Subscribed to audio event listener and analysis listener`,\n {\n subscribeAudio,\n }\n )\n\n return () => {\n logger?.debug(`Removing audio event listener`)\n subscribeAudio.remove()\n }\n }, [handleAudioEvent, handleAudioAnalysis])\n\n useEffect(() => {\n // Add event subscription for recording interruptions\n logger?.debug('Setting up recording interruption listener')\n\n const subscription = addRecordingInterruptionListener((event) => {\n logger?.debug('Received recording interruption event:', event)\n\n // Check if we have a callback configured\n if (recordingConfigRef.current?.onRecordingInterrupted) {\n try {\n recordingConfigRef.current.onRecordingInterrupted(event)\n } catch (error) {\n logger?.error(\n 'Error in recording interruption callback:',\n error\n )\n }\n } else {\n logger?.warn('No recording interruption callback configured')\n }\n })\n\n return () => {\n logger?.debug('Removing recording interruption listener')\n subscription.remove()\n }\n }, []) // Empty dependency array since we want this to run once\n\n return {\n startRecording,\n stopRecording,\n pauseRecording,\n resumeRecording,\n isPaused: state.isPaused,\n isRecording: state.isRecording,\n durationMs: state.durationMs,\n size: state.size,\n compression: state.compression,\n analysisData: state.analysisData,\n }\n}\n"]}
1
+ {"version":3,"file":"useAudioRecorder.js","sourceRoot":"","sources":["../src/useAudioRecorder.tsx"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,OAAO,EAAqB,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC/D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAYlE,OAAO,qBAAqB,MAAM,yBAAyB,CAAA;AAC3D,OAAO,EACH,wBAAwB,EACxB,qBAAqB,EAErB,gCAAgC,GACnC,MAAM,UAAU,CAAA;AAiDjB,MAAM,eAAe,GAAkB;IACnC,eAAe,EAAE,EAAE;IACnB,QAAQ,EAAE,EAAE;IACZ,gBAAgB,EAAE,CAAC;IACnB,UAAU,EAAE,CAAC;IACb,UAAU,EAAE,KAAK;IACjB,OAAO,EAAE,CAAC;IACV,UAAU,EAAE,EAAE;IACd,kBAAkB,EAAE,KAAK;IACzB,cAAc,EAAE,EAAE;IAClB,cAAc,EAAE;QACZ,GAAG,EAAE,MAAM,CAAC,iBAAiB;QAC7B,GAAG,EAAE,MAAM,CAAC,iBAAiB;KAChC;CACJ,CAAA;AAED,SAAS,oBAAoB,CACzB,KAA2B,EAC3B,MAAsB;IAEtB,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,OAAO;YACR,OAAO;gBACH,GAAG,KAAK;gBACR,WAAW,EAAE,IAAI;gBACjB,QAAQ,EAAE,KAAK;gBACf,UAAU,EAAE,CAAC;gBACb,IAAI,EAAE,CAAC;gBACP,WAAW,EAAE,SAAS;gBACtB,YAAY,EAAE,eAAe;aAChC,CAAA;QACL,KAAK,MAAM;YACP,OAAO;gBACH,GAAG,KAAK;gBACR,WAAW,EAAE,KAAK;gBAClB,QAAQ,EAAE,KAAK;gBACf,UAAU,EAAE,CAAC;gBACb,IAAI,EAAE,CAAC;gBACP,WAAW,EAAE,SAAS;gBACtB,YAAY,EAAE,SAAS;aAC1B,CAAA;QACL,KAAK,OAAO;YACR,OAAO,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAA;QAC3D,KAAK,QAAQ;YACT,OAAO,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAA;QAC3D,KAAK,wBAAwB;YACzB,OAAO;gBACH,GAAG,KAAK;gBACR,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ;gBACjC,WAAW,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW;aAC1C,CAAA;QACL,KAAK,eAAe,CAAC,CAAC,CAAC;YACnB,MAAM,QAAQ,GAAG;gBACb,GAAG,KAAK;gBACR,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU;gBACrC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI;gBACzB,WAAW,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW;oBACnC,CAAC,CAAC;wBACI,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI;wBACrC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ;wBAC7C,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO;wBAC3C,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM;qBAC5C;oBACH,CAAC,CAAC,SAAS;aAClB,CAAA;YACD,OAAO,QAAQ,CAAA;QACnB,CAAC;QACD,KAAK,iBAAiB;YAClB,OAAO;gBACH,GAAG,KAAK;gBACR,YAAY,EAAE,MAAM,CAAC,OAAO;aAC/B,CAAA;QACL;YACI,OAAO,KAAK,CAAA;IACpB,CAAC;AACL,CAAC;AAOD,MAAM,UAAU,gBAAgB,CAAC,EAC7B,MAAM,EACN,eAAe,EACf,mBAAmB,MACI,EAAE;IACzB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,UAAU,CAAC,oBAAoB,EAAE;QACvD,WAAW,EAAE,KAAK;QAClB,QAAQ,EAAE,KAAK;QACf,UAAU,EAAE,CAAC;QACb,IAAI,EAAE,CAAC;QACP,WAAW,EAAE,SAAS;QACtB,YAAY,EAAE,SAAS;KAC1B,CAAC,CAAA;IAEF,MAAM,cAAc,GAAG,MAAM,CAA8B,IAAI,CAAC,CAAA;IAEhE,MAAM,mBAAmB,GAAG,MAAM,CAA2B,IAAI,CAAC,CAAA;IAClE,wEAAwE;IACxE,MAAM,WAAW,GAAG,MAAM,CAAgB,EAAE,GAAG,eAAe,EAAE,CAAC,CAAA;IACjE,8DAA8D;IAC9D,MAAM,eAAe,GAAG,MAAM,CAAgB;QAC1C,GAAG,eAAe;KACrB,CAAC,CAAA;IAEF,2CAA2C;IAC3C,MAAM,eAAe,GACjB,QAAQ,CAAC,EAAE,KAAK,KAAK;QACjB,CAAC,CAAC,qBAAqB,CAAC;YAClB,eAAe;YACf,mBAAmB;YACnB,MAAM;SACT,CAAC;QACJ,CAAC,CAAC,qBAAqB,CAAA;IAE/B,MAAM,gBAAgB,GAAG,MAAM,CAE7B,IAAI,CAAC,CAAA;IAEP,MAAM,QAAQ,GAAG,MAAM,CAAC;QACpB,WAAW,EAAE,KAAK;QAClB,QAAQ,EAAE,KAAK;QACf,UAAU,EAAE,CAAC;QACb,IAAI,EAAE,CAAC;QACP,WAAW,EAAE,SAAwC;KACxD,CAAC,CAAA;IAEF,MAAM,kBAAkB,GAAG,MAAM,CAAyB,IAAI,CAAC,CAAA;IAE/D,MAAM,mBAAmB,GAAG,WAAW,CACnC,KAAK,EAAE,EACH,QAAQ,EACR,qBAAqB,GACE,EAAE,EAAE;QAC3B,MAAM,iBAAiB,GAAG,WAAW,CAAC,OAAO,IAAI;YAC7C,GAAG,eAAe;SACrB,CAAA;QAED,MAAM,WAAW,GAAG,qBAAqB,CAAA;QAEzC,MAAM,EAAE,KAAK,CACT,8DAA8D,WAAW,wBAAwB,QAAQ,CAAC,UAAU,CAAC,MAAM,4BAA4B,iBAAiB,CAAC,UAAU,CAAC,MAAM,EAAE,EAC5L,QAAQ,CACX,CAAA;QAED,sBAAsB;QACtB,MAAM,kBAAkB,GAAG;YACvB,GAAG,iBAAiB,CAAC,UAAU;YAC/B,GAAG,QAAQ,CAAC,UAAU;SACzB,CAAA;QAED,MAAM,sBAAsB,GAAG;YAC3B,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,UAAU,IAAI,EAAE,CAAC;YAC9C,GAAG,QAAQ,CAAC,UAAU;SACzB,CAAA;QAED,6BAA6B;QAC7B,MAAM,eAAe,GACjB,QAAQ,CAAC,eAAe,IAAI,iBAAiB,CAAC,eAAe,CAAA;QACjE,MAAM,aAAa,GACf,CAAC,eAAe,GAAG,qBAAqB,CAAC,GAAG,IAAI,CAAA;QAEpD,MAAM,EAAE,KAAK,CACT,+EAA+E,eAAe,0BAA0B,qBAAqB,6BAA6B,kBAAkB,CAAC,MAAM,qBAAqB,aAAa,EAAE,CAC1O,CAAA;QAED,oEAAoE;QACpE,IAAI,kBAAkB,CAAC,MAAM,GAAG,aAAa,EAAE,CAAC;YAC5C,kBAAkB,CAAC,MAAM,CACrB,CAAC,EACD,kBAAkB,CAAC,MAAM,GAAG,aAAa,CAC5C,CAAA;QACL,CAAC;QAED,4BAA4B;QAC5B,eAAe,CAAC,OAAO,GAAG;YACtB,GAAG,eAAe,CAAC,OAAO;YAC1B,UAAU,EAAE,sBAAsB;SACrC,CAAA;QACD,eAAe,CAAC,OAAO,CAAC,UAAU;YAC9B,sBAAsB,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,eAAe,CAAC,CAAA;QAC5D,iBAAiB,CAAC,UAAU,GAAG,kBAAkB,CAAA;QACjD,iBAAiB,CAAC,QAAQ;YACtB,QAAQ,CAAC,QAAQ,IAAI,iBAAiB,CAAC,QAAQ,CAAA;QACnD,iBAAiB,CAAC,UAAU;YACxB,kBAAkB,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,eAAe,CAAC,CAAA;QAExD,yBAAyB;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACnB,iBAAiB,CAAC,cAAc,CAAC,GAAG,EACpC,QAAQ,CAAC,cAAc,CAAC,GAAG,CAC9B,CAAA;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACnB,iBAAiB,CAAC,cAAc,CAAC,GAAG,EACpC,QAAQ,CAAC,cAAc,CAAC,GAAG,CAC9B,CAAA;QAED,iBAAiB,CAAC,cAAc,GAAG;YAC/B,GAAG,EAAE,MAAM;YACX,GAAG,EAAE,MAAM;SACd,CAAA;QACD,eAAe,CAAC,OAAO,CAAC,cAAc,GAAG;YACrC,GAAG,EAAE,MAAM;YACX,GAAG,EAAE,MAAM;SACd,CAAA;QAED,MAAM,EAAE,KAAK,CACT,2DAA2D,iBAAiB,CAAC,UAAU,EAAE,EACzF,iBAAiB,CACpB,CAAA;QAED,yEAAyE;QACzE,IAAI,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,CAAC;YAC9C,kBAAkB,CAAC,OAAO;iBACrB,eAAe,CAAC,QAAQ,CAAC;iBACzB,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBACb,MAAM,EAAE,IAAI,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAA;YAC3D,CAAC,CAAC,CAAA;QACV,CAAC;QAED,iBAAiB;QACjB,WAAW,CAAC,OAAO,GAAG,iBAAiB,CAAA;QAEvC,mEAAmE;QACnE,QAAQ,CAAC;YACL,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,EAAE,GAAG,iBAAiB,EAAE;SACpC,CAAC,CAAA;IACN,CAAC,EACD,CAAC,QAAQ,CAAC,CACb,CAAA;IAED,MAAM,gBAAgB,GAAG,WAAW,CAChC,KAAK,EAAE,SAA4B,EAAE,EAAE;QACnC,MAAM,EACF,OAAO,EACP,SAAS,EACT,SAAS,EACT,eAAe,EACf,QAAQ,EACR,UAAU,EACV,OAAO,EACP,QAAQ,EACR,MAAM,EACN,WAAW,GACd,GAAG,SAAS,CAAA;QACb,MAAM,EAAE,KAAK,CAAC,0CAA0C,EAAE;YACtD,OAAO;YACP,SAAS;YACT,SAAS;YACT,QAAQ;YACR,QAAQ;YACR,eAAe;YACf,UAAU;YACV,aAAa,EAAE,OAAO,EAAE,MAAM;YAC9B,WAAW;SACd,CAAC,CAAA;QACF,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;YAClB,6BAA6B;YAC7B,OAAM;QACV,CAAC;QACD,IAAI,CAAC;YACD,+DAA+D;YAC/D,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;gBACxB,wDAAwD;gBACxD,IAAI,CAAC,OAAO,EAAE,CAAC;oBACX,MAAM,EAAE,KAAK,CAAC,+BAA+B,CAAC,CAAA;oBAC9C,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;gBACpD,CAAC;gBACD,gBAAgB,CAAC,OAAO,EAAE,CAAC;oBACvB,IAAI,EAAE,OAAO;oBACb,QAAQ;oBACR,OAAO;oBACP,aAAa,EAAE,SAAS;oBACxB,SAAS;oBACT,WAAW,EACP,WAAW,IAAI,cAAc,CAAC,OAAO,EAAE,WAAW;wBAC9C,CAAC,CAAC;4BACI,IAAI,EAAE,WAAW,CAAC,IAAI;4BACtB,IAAI,EAAE,WAAW,CAAC,SAAS;4BAC3B,QAAQ,EACJ,cAAc,CAAC,OAAO,CAAC,WAAW;gCAC9B,EAAE,QAAQ;4BAClB,OAAO,EACH,cAAc,CAAC,OAAO,CAAC,WAAW;gCAC9B,EAAE,OAAO;4BACjB,MAAM,EAAE,cAAc,CAAC,OAAO,CAAC,WAAW;gCACtC,EAAE,MAAM;yBACf;wBACH,CAAC,CAAC,SAAS;iBACtB,CAAC,CAAA;YACN,CAAC;iBAAM,IAAI,MAAM,EAAE,CAAC;gBAChB,kBAAkB;gBAClB,MAAM,QAAQ,GAAmB;oBAC7B,IAAI,EAAE,MAAM;oBACZ,QAAQ;oBACR,OAAO;oBACP,aAAa,EAAE,SAAS;oBACxB,SAAS;oBACT,WAAW,EACP,WAAW,IAAI,cAAc,CAAC,OAAO,EAAE,WAAW;wBAC9C,CAAC,CAAC;4BACI,IAAI,EAAE,WAAW,CAAC,IAAI;4BACtB,IAAI,EAAE,WAAW,CAAC,SAAS;4BAC3B,QAAQ,EACJ,cAAc,CAAC,OAAO,CAAC,WAAW;gCAC9B,EAAE,QAAQ;4BAClB,OAAO,EACH,cAAc,CAAC,OAAO,CAAC,WAAW;gCAC9B,EAAE,OAAO;4BACjB,MAAM,EAAE,cAAc,CAAC,OAAO,CAAC,WAAW;gCACtC,EAAE,MAAM;yBACf;wBACH,CAAC,CAAC,SAAS;iBACtB,CAAA;gBACD,gBAAgB,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,CAAA;gBACpC,MAAM,EAAE,KAAK,CACT,qDAAqD,EACrD,QAAQ,CACX,CAAA;YACL,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,EAAE,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAA;QACzD,CAAC;IACL,CAAC,EACD,EAAE,CACL,CAAA;IAED,MAAM,WAAW,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACvC,IAAI,CAAC;YACD,MAAM,MAAM,GAAsB,eAAe,CAAC,MAAM,EAAE,CAAA;YAC1D,MAAM,EAAE,KAAK,CACT,mBAAmB,MAAM,CAAC,QAAQ,iBAAiB,MAAM,CAAC,WAAW,gBAAgB,MAAM,CAAC,UAAU,UAAU,MAAM,CAAC,IAAI,EAAE,EAC7H,MAAM,CAAC,WAAW,CACrB,CAAA;YAED,2CAA2C;YAC3C,IACI,MAAM,CAAC,WAAW,KAAK,QAAQ,CAAC,OAAO,CAAC,WAAW;gBACnD,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAC/C,CAAC;gBACC,QAAQ,CAAC,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAA;gBACjD,QAAQ,CAAC,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAA;gBAC3C,QAAQ,CAAC;oBACL,IAAI,EAAE,wBAAwB;oBAC9B,OAAO,EAAE;wBACL,WAAW,EAAE,MAAM,CAAC,WAAW;wBAC/B,QAAQ,EAAE,MAAM,CAAC,QAAQ;qBAC5B;iBACJ,CAAC,CAAA;YACN,CAAC;YAED,IACI,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC,OAAO,CAAC,UAAU;gBACjD,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,OAAO,CAAC,IAAI,EACvC,CAAC;gBACC,QAAQ,CAAC,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAA;gBAC/C,QAAQ,CAAC,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAA;gBACnC,QAAQ,CAAC,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAA;gBACjD,QAAQ,CAAC;oBACL,IAAI,EAAE,eAAe;oBACrB,OAAO,EAAE;wBACL,UAAU,EAAE,MAAM,CAAC,UAAU;wBAC7B,IAAI,EAAE,MAAM,CAAC,IAAI;wBACjB,WAAW,EAAE,MAAM,CAAC,WAAW;qBAClC;iBACJ,CAAC,CAAA;YACN,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,EAAE,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAA;QACjD,CAAC;IACL,CAAC,EAAE,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAA,CAAC,4CAA4C;IAE1E,gCAAgC;IAChC,SAAS,CAAC,GAAG,EAAE;QACX,QAAQ,CAAC,OAAO,GAAG;YACf,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,WAAW,EAAE,KAAK,CAAC,WAAW;SACjC,CAAA;IACL,CAAC,EAAE;QACC,KAAK,CAAC,WAAW;QACjB,KAAK,CAAC,QAAQ;QACd,KAAK,CAAC,UAAU;QAChB,KAAK,CAAC,IAAI;QACV,KAAK,CAAC,WAAW;KACpB,CAAC,CAAA;IAEF,MAAM,cAAc,GAAG,WAAW,CAC9B,KAAK,EAAE,gBAAiC,EAAE,EAAE;QACxC,kBAAkB,CAAC,OAAO,GAAG,gBAAgB,CAAA;QAC7C,MAAM,EAAE,KAAK,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAA;QAEjD,WAAW,CAAC,OAAO,GAAG,EAAE,GAAG,eAAe,EAAE,CAAA,CAAC,sBAAsB;QACnE,eAAe,CAAC,OAAO,GAAG,EAAE,GAAG,eAAe,EAAE,CAAA;QAChD,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,GAAG,gBAAgB,CAAA;QACtD,MAAM,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAA;QAEpC,MAAM,qBAAqB,GAAG,KAAK,CAAA,CAAC,gEAAgE;QACpG,IAAI,OAAO,aAAa,KAAK,UAAU,EAAE,CAAC;YACtC,gBAAgB,CAAC,OAAO,GAAG,aAAa,CAAA;QAC5C,CAAC;aAAM,CAAC;YACJ,MAAM,EAAE,IAAI,CAAC,iCAAiC,EAAE,aAAa,CAAC,CAAA;YAC9D,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAA;QACnC,CAAC;QACD,MAAM,WAAW,GACb,MAAM,eAAe,CAAC,cAAc,CAAC,OAAO,CAAC,CAAA;QACjD,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;QAE3B,cAAc,CAAC,OAAO,GAAG,WAAW,CAAA;QAEpC,IAAI,gBAAgB,EAAE,CAAC;YACnB,MAAM,EAAE,KAAK,CAAC,kCAAkC,CAAC,CAAA;YACjD,MAAM,QAAQ,GAAG,wBAAwB,CACrC,KAAK,EAAE,YAAY,EAAE,EAAE;gBACnB,IAAI,CAAC;oBACD,MAAM,mBAAmB,CAAC;wBACtB,QAAQ,EAAE,YAAY;wBACtB,qBAAqB,EAAE,qBAAqB;qBAC/C,CAAC,CAAA;gBACN,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACb,MAAM,EAAE,IAAI,CACR,kCAAkC,EAClC,KAAK,CACR,CAAA;gBACL,CAAC;YACL,CAAC,CACJ,CAAA;YAED,mBAAmB,CAAC,OAAO,GAAG,QAAQ,CAAA;QAC1C,CAAC;QAED,OAAO,WAAW,CAAA;IACtB,CAAC,EACD,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAClC,CAAA;IAED,MAAM,aAAa,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACzC,MAAM,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAA;QAElC,MAAM,UAAU,GAAmB,MAAM,eAAe,CAAC,aAAa,EAAE,CAAA;QACxE,UAAU,CAAC,YAAY,GAAG,eAAe,CAAC,OAAO,CAAA;QAEjD,IAAI,mBAAmB,CAAC,OAAO,EAAE,CAAC;YAC9B,mBAAmB,CAAC,OAAO,CAAC,MAAM,EAAE,CAAA;YACpC,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAA;QACtC,CAAC;QACD,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAA;QAC/B,MAAM,EAAE,KAAK,CAAC,mBAAmB,EAAE,UAAU,CAAC,CAAA;QAC9C,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;QAC1B,OAAO,UAAU,CAAA;IACrB,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,MAAM,cAAc,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC1C,MAAM,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAA;QAChC,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,cAAc,EAAE,CAAA;QAC1D,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;QAC3B,OAAO,WAAW,CAAA;IACtB,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,MAAM,eAAe,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC3C,MAAM,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAA;QACjC,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,eAAe,EAAE,CAAA;QAC5D,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;QAC5B,OAAO,YAAY,CAAA;IACvB,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,UAAsC,CAAA;QAE1C,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACtC,yCAAyC;YACzC,WAAW,EAAE,CAAA;YAEb,iBAAiB;YACjB,UAAU,GAAG,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,CAAA;QAC/C,CAAC;QAED,OAAO,GAAG,EAAE;YACR,IAAI,UAAU,EAAE,CAAC;gBACb,aAAa,CAAC,UAAU,CAAC,CAAA;gBACzB,UAAU,GAAG,SAAS,CAAA;YAC1B,CAAC;QACL,CAAC,CAAA;IACL,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEpD,SAAS,CAAC,GAAG,EAAE;QACX,MAAM,EAAE,KAAK,CAAC,kCAAkC,CAAC,CAAA;QACjD,MAAM,cAAc,GAAG,qBAAqB,CAAC,gBAAgB,CAAC,CAAA;QAE9D,MAAM,EAAE,KAAK,CACT,0DAA0D,EAC1D;YACI,cAAc;SACjB,CACJ,CAAA;QAED,OAAO,GAAG,EAAE;YACR,MAAM,EAAE,KAAK,CAAC,+BAA+B,CAAC,CAAA;YAC9C,cAAc,CAAC,MAAM,EAAE,CAAA;QAC3B,CAAC,CAAA;IACL,CAAC,EAAE,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,CAAC,CAAA;IAE3C,SAAS,CAAC,GAAG,EAAE;QACX,qDAAqD;QACrD,MAAM,EAAE,KAAK,CAAC,4CAA4C,CAAC,CAAA;QAE3D,MAAM,YAAY,GAAG,gCAAgC,CAAC,CAAC,KAAK,EAAE,EAAE;YAC5D,MAAM,EAAE,KAAK,CAAC,wCAAwC,EAAE,KAAK,CAAC,CAAA;YAE9D,yCAAyC;YACzC,IAAI,kBAAkB,CAAC,OAAO,EAAE,sBAAsB,EAAE,CAAC;gBACrD,IAAI,CAAC;oBACD,kBAAkB,CAAC,OAAO,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAA;gBAC5D,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACb,MAAM,EAAE,KAAK,CACT,2CAA2C,EAC3C,KAAK,CACR,CAAA;gBACL,CAAC;YACL,CAAC;iBAAM,CAAC;gBACJ,MAAM,EAAE,IAAI,CAAC,+CAA+C,CAAC,CAAA;YACjE,CAAC;QACL,CAAC,CAAC,CAAA;QAEF,OAAO,GAAG,EAAE;YACR,MAAM,EAAE,KAAK,CAAC,0CAA0C,CAAC,CAAA;YACzD,YAAY,CAAC,MAAM,EAAE,CAAA;QACzB,CAAC,CAAA;IACL,CAAC,EAAE,EAAE,CAAC,CAAA,CAAC,wDAAwD;IAE/D,OAAO;QACH,cAAc;QACd,aAAa;QACb,cAAc;QACd,eAAe;QACf,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,YAAY,EAAE,KAAK,CAAC,YAAY;KACnC,CAAA;AACL,CAAC","sourcesContent":["// src/useAudioRecorder.ts\nimport { EventSubscription, Platform } from 'expo-modules-core'\nimport { useCallback, useEffect, useReducer, useRef } from 'react'\n\nimport { AudioAnalysis } from './AudioAnalysis/AudioAnalysis.types'\nimport {\n AudioDataEvent,\n AudioRecording,\n AudioStreamStatus,\n CompressionInfo,\n ConsoleLike,\n RecordingConfig,\n StartRecordingResult,\n} from './ExpoAudioStream.types'\nimport ExpoAudioStreamModule from './ExpoAudioStreamModule'\nimport {\n addAudioAnalysisListener,\n addAudioEventListener,\n AudioEventPayload,\n addRecordingInterruptionListener,\n} from './events'\n\nexport interface UseAudioRecorderProps {\n logger?: ConsoleLike\n audioWorkletUrl?: string\n featuresExtratorUrl?: string\n}\n\nexport interface UseAudioRecorderState {\n startRecording: (_: RecordingConfig) => Promise<StartRecordingResult>\n stopRecording: () => Promise<AudioRecording>\n pauseRecording: () => Promise<void>\n resumeRecording: () => Promise<void>\n isRecording: boolean\n isPaused: boolean\n durationMs: number\n size: number\n compression?: CompressionInfo\n analysisData?: AudioAnalysis\n}\n\ninterface RecorderReducerState {\n isRecording: boolean\n isPaused: boolean\n durationMs: number\n size: number\n compression?: CompressionInfo\n analysisData?: AudioAnalysis\n}\n\ntype RecorderAction =\n | { type: 'START' | 'STOP' | 'PAUSE' | 'RESUME' }\n | {\n type: 'UPDATE_RECORDING_STATE'\n payload: {\n isRecording: boolean\n isPaused: boolean\n }\n }\n | {\n type: 'UPDATE_STATUS'\n payload: {\n durationMs: number\n size: number\n compression?: CompressionInfo\n }\n }\n | { type: 'UPDATE_ANALYSIS'; payload: AudioAnalysis }\n\nconst defaultAnalysis: AudioAnalysis = {\n pointsPerSecond: 10,\n bitDepth: 32,\n numberOfChannels: 1,\n durationMs: 0,\n sampleRate: 44100,\n samples: 0,\n dataPoints: [],\n amplitudeAlgorithm: 'rms',\n speakerChanges: [],\n amplitudeRange: {\n min: Number.POSITIVE_INFINITY,\n max: Number.NEGATIVE_INFINITY,\n },\n}\n\nfunction audioRecorderReducer(\n state: RecorderReducerState,\n action: RecorderAction\n): RecorderReducerState {\n switch (action.type) {\n case 'START':\n return {\n ...state,\n isRecording: true,\n isPaused: false,\n durationMs: 0,\n size: 0,\n compression: undefined,\n analysisData: defaultAnalysis,\n }\n case 'STOP':\n return {\n ...state,\n isRecording: false,\n isPaused: false,\n durationMs: 0,\n size: 0,\n compression: undefined,\n analysisData: undefined,\n }\n case 'PAUSE':\n return { ...state, isPaused: true, isRecording: false }\n case 'RESUME':\n return { ...state, isPaused: false, isRecording: true }\n case 'UPDATE_RECORDING_STATE':\n return {\n ...state,\n isPaused: action.payload.isPaused,\n isRecording: action.payload.isRecording,\n }\n case 'UPDATE_STATUS': {\n const newState = {\n ...state,\n durationMs: action.payload.durationMs,\n size: action.payload.size,\n compression: action.payload.compression\n ? {\n size: action.payload.compression.size,\n mimeType: action.payload.compression.mimeType,\n bitrate: action.payload.compression.bitrate,\n format: action.payload.compression.format,\n }\n : undefined,\n }\n return newState\n }\n case 'UPDATE_ANALYSIS':\n return {\n ...state,\n analysisData: action.payload,\n }\n default:\n return state\n }\n}\n\ninterface HandleAudioAnalysisProps {\n analysis: AudioAnalysis\n visualizationDuration: number\n}\n\nexport function useAudioRecorder({\n logger,\n audioWorkletUrl,\n featuresExtratorUrl,\n}: UseAudioRecorderProps = {}): UseAudioRecorderState {\n const [state, dispatch] = useReducer(audioRecorderReducer, {\n isRecording: false,\n isPaused: false,\n durationMs: 0,\n size: 0,\n compression: undefined,\n analysisData: undefined,\n })\n\n const startResultRef = useRef<StartRecordingResult | null>(null)\n\n const analysisListenerRef = useRef<EventSubscription | null>(null)\n // analysisRef is the current analysis data (last 10 seconds by default)\n const analysisRef = useRef<AudioAnalysis>({ ...defaultAnalysis })\n // fullAnalysisRef is the full analysis data (all data points)\n const fullAnalysisRef = useRef<AudioAnalysis>({\n ...defaultAnalysis,\n })\n\n // Instantiate the module for web with URLs\n const ExpoAudioStream =\n Platform.OS === 'web'\n ? ExpoAudioStreamModule({\n audioWorkletUrl,\n featuresExtratorUrl,\n logger,\n })\n : ExpoAudioStreamModule\n\n const onAudioStreamRef = useRef<\n ((_: AudioDataEvent) => Promise<void>) | null\n >(null)\n\n const stateRef = useRef({\n isRecording: false,\n isPaused: false,\n durationMs: 0,\n size: 0,\n compression: undefined as CompressionInfo | undefined,\n })\n\n const recordingConfigRef = useRef<RecordingConfig | null>(null)\n\n const handleAudioAnalysis = useCallback(\n async ({\n analysis,\n visualizationDuration,\n }: HandleAudioAnalysisProps) => {\n const savedAnalysisData = analysisRef.current || {\n ...defaultAnalysis,\n }\n\n const maxDuration = visualizationDuration\n\n logger?.debug(\n `[handleAudioAnalysis] Received audio analysis: maxDuration=${maxDuration} analysis.dataPoints=${analysis.dataPoints.length} analysisData.dataPoints=${savedAnalysisData.dataPoints.length}`,\n analysis\n )\n\n // Combine data points\n const combinedDataPoints = [\n ...savedAnalysisData.dataPoints,\n ...analysis.dataPoints,\n ]\n\n const fullCombinedDataPoints = [\n ...(fullAnalysisRef.current?.dataPoints ?? []),\n ...analysis.dataPoints,\n ]\n\n // Calculate the new duration\n const pointsPerSecond =\n analysis.pointsPerSecond || savedAnalysisData.pointsPerSecond\n const maxDataPoints =\n (pointsPerSecond * visualizationDuration) / 1000\n\n logger?.debug(\n `[handleAudioAnalysis] Combined data points before trimming: pointsPerSecond=${pointsPerSecond} visualizationDuration=${visualizationDuration} combinedDataPointsLength=${combinedDataPoints.length} vs maxDataPoints=${maxDataPoints}`\n )\n\n // Trim data points to keep within the maximum number of data points\n if (combinedDataPoints.length > maxDataPoints) {\n combinedDataPoints.splice(\n 0,\n combinedDataPoints.length - maxDataPoints\n )\n }\n\n // Keep the full data points\n fullAnalysisRef.current = {\n ...fullAnalysisRef.current,\n dataPoints: fullCombinedDataPoints,\n }\n fullAnalysisRef.current.durationMs =\n fullCombinedDataPoints.length * (1000 / pointsPerSecond)\n savedAnalysisData.dataPoints = combinedDataPoints\n savedAnalysisData.bitDepth =\n analysis.bitDepth || savedAnalysisData.bitDepth\n savedAnalysisData.durationMs =\n combinedDataPoints.length * (1000 / pointsPerSecond)\n\n // Update amplitude range\n const newMin = Math.min(\n savedAnalysisData.amplitudeRange.min,\n analysis.amplitudeRange.min\n )\n const newMax = Math.max(\n savedAnalysisData.amplitudeRange.max,\n analysis.amplitudeRange.max\n )\n\n savedAnalysisData.amplitudeRange = {\n min: newMin,\n max: newMax,\n }\n fullAnalysisRef.current.amplitudeRange = {\n min: newMin,\n max: newMax,\n }\n\n logger?.debug(\n `[handleAudioAnalysis] Updated analysis data: durationMs=${savedAnalysisData.durationMs}`,\n savedAnalysisData\n )\n\n // Call the onAudioAnalysis callback if it exists in the recording config\n if (recordingConfigRef.current?.onAudioAnalysis) {\n recordingConfigRef.current\n .onAudioAnalysis(analysis)\n .catch((error) => {\n logger?.warn(`Error processing audio analysis:`, error)\n })\n }\n\n // Update the ref\n analysisRef.current = savedAnalysisData\n\n // Dispatch the updated analysis data to state to trigger re-render\n dispatch({\n type: 'UPDATE_ANALYSIS',\n payload: { ...savedAnalysisData },\n })\n },\n [dispatch]\n )\n\n const handleAudioEvent = useCallback(\n async (eventData: AudioEventPayload) => {\n const {\n fileUri,\n deltaSize,\n totalSize,\n lastEmittedSize,\n position,\n streamUuid,\n encoded,\n mimeType,\n buffer,\n compression,\n } = eventData\n logger?.debug(`[handleAudioEvent] Received audio event:`, {\n fileUri,\n deltaSize,\n totalSize,\n position,\n mimeType,\n lastEmittedSize,\n streamUuid,\n encodedLength: encoded?.length,\n compression,\n })\n if (deltaSize === 0) {\n // Ignore packet with no data\n return\n }\n try {\n // Coming from native ( ios / android ) otherwise buffer is set\n if (Platform.OS !== 'web') {\n // Read the audio file as a base64 string for comparison\n if (!encoded) {\n logger?.error(`Encoded audio data is missing`)\n throw new Error('Encoded audio data is missing')\n }\n onAudioStreamRef.current?.({\n data: encoded,\n position,\n fileUri,\n eventDataSize: deltaSize,\n totalSize,\n compression:\n compression && startResultRef.current?.compression\n ? {\n data: compression.data,\n size: compression.totalSize,\n mimeType:\n startResultRef.current.compression\n ?.mimeType,\n bitrate:\n startResultRef.current.compression\n ?.bitrate,\n format: startResultRef.current.compression\n ?.format,\n }\n : undefined,\n })\n } else if (buffer) {\n // Coming from web\n const webEvent: AudioDataEvent = {\n data: buffer,\n position,\n fileUri,\n eventDataSize: deltaSize,\n totalSize,\n compression:\n compression && startResultRef.current?.compression\n ? {\n data: compression.data,\n size: compression.totalSize,\n mimeType:\n startResultRef.current.compression\n ?.mimeType,\n bitrate:\n startResultRef.current.compression\n ?.bitrate,\n format: startResultRef.current.compression\n ?.format,\n }\n : undefined,\n }\n onAudioStreamRef.current?.(webEvent)\n logger?.debug(\n `[handleAudioEvent] Audio data sent to onAudioStream`,\n webEvent\n )\n }\n } catch (error) {\n logger?.error(`Error processing audio event:`, error)\n }\n },\n []\n )\n\n const checkStatus = useCallback(async () => {\n try {\n const status: AudioStreamStatus = ExpoAudioStream.status()\n logger?.debug(\n `Status: paused: ${status.isPaused} isRecording: ${status.isRecording} durationMs: ${status.durationMs} size: ${status.size}`,\n status.compression\n )\n\n // Only dispatch if values actually changed\n if (\n status.isRecording !== stateRef.current.isRecording ||\n status.isPaused !== stateRef.current.isPaused\n ) {\n stateRef.current.isRecording = status.isRecording\n stateRef.current.isPaused = status.isPaused\n dispatch({\n type: 'UPDATE_RECORDING_STATE',\n payload: {\n isRecording: status.isRecording,\n isPaused: status.isPaused,\n },\n })\n }\n\n if (\n status.durationMs !== stateRef.current.durationMs ||\n status.size !== stateRef.current.size\n ) {\n stateRef.current.durationMs = status.durationMs\n stateRef.current.size = status.size\n stateRef.current.compression = status.compression\n dispatch({\n type: 'UPDATE_STATUS',\n payload: {\n durationMs: status.durationMs,\n size: status.size,\n compression: status.compression,\n },\n })\n }\n } catch (error) {\n logger?.error(`Error getting status:`, error)\n }\n }, [ExpoAudioStream, logger]) // Only depend on ExpoAudioStream and logger\n\n // Update ref when state changes\n useEffect(() => {\n stateRef.current = {\n isRecording: state.isRecording,\n isPaused: state.isPaused,\n durationMs: state.durationMs,\n size: state.size,\n compression: state.compression,\n }\n }, [\n state.isRecording,\n state.isPaused,\n state.durationMs,\n state.size,\n state.compression,\n ])\n\n const startRecording = useCallback(\n async (recordingOptions: RecordingConfig) => {\n recordingConfigRef.current = recordingOptions\n logger?.debug(`start recoding`, recordingOptions)\n\n analysisRef.current = { ...defaultAnalysis } // Reset analysis data\n fullAnalysisRef.current = { ...defaultAnalysis }\n const { onAudioStream, ...options } = recordingOptions\n const { enableProcessing } = options\n\n const maxRecentDataDuration = 10000 // TODO compute maxRecentDataDuration based on screen dimensions\n if (typeof onAudioStream === 'function') {\n onAudioStreamRef.current = onAudioStream\n } else {\n logger?.warn(`onAudioStream is not a function`, onAudioStream)\n onAudioStreamRef.current = null\n }\n const startResult: StartRecordingResult =\n await ExpoAudioStream.startRecording(options)\n dispatch({ type: 'START' })\n\n startResultRef.current = startResult\n\n if (enableProcessing) {\n logger?.debug(`Enabling audio analysis listener`)\n const listener = addAudioAnalysisListener(\n async (analysisData) => {\n try {\n await handleAudioAnalysis({\n analysis: analysisData,\n visualizationDuration: maxRecentDataDuration,\n })\n } catch (error) {\n logger?.warn(\n `Error processing audio analysis:`,\n error\n )\n }\n }\n )\n\n analysisListenerRef.current = listener\n }\n\n return startResult\n },\n [handleAudioAnalysis, dispatch]\n )\n\n const stopRecording = useCallback(async () => {\n logger?.debug(`stoping recording`)\n\n const stopResult: AudioRecording = await ExpoAudioStream.stopRecording()\n stopResult.analysisData = fullAnalysisRef.current\n\n if (analysisListenerRef.current) {\n analysisListenerRef.current.remove()\n analysisListenerRef.current = null\n }\n onAudioStreamRef.current = null\n logger?.debug(`recording stopped`, stopResult)\n dispatch({ type: 'STOP' })\n return stopResult\n }, [dispatch])\n\n const pauseRecording = useCallback(async () => {\n logger?.debug(`pause recording`)\n const pauseResult = await ExpoAudioStream.pauseRecording()\n dispatch({ type: 'PAUSE' })\n return pauseResult\n }, [dispatch])\n\n const resumeRecording = useCallback(async () => {\n logger?.debug(`resume recording`)\n const resumeResult = await ExpoAudioStream.resumeRecording()\n dispatch({ type: 'RESUME' })\n return resumeResult\n }, [dispatch])\n\n useEffect(() => {\n let intervalId: NodeJS.Timeout | undefined\n\n if (state.isRecording || state.isPaused) {\n // Immediately check status when starting\n checkStatus()\n\n // Start interval\n intervalId = setInterval(checkStatus, 1000)\n }\n\n return () => {\n if (intervalId) {\n clearInterval(intervalId)\n intervalId = undefined\n }\n }\n }, [checkStatus, state.isRecording, state.isPaused])\n\n useEffect(() => {\n logger?.debug(`Registering audio event listener`)\n const subscribeAudio = addAudioEventListener(handleAudioEvent)\n\n logger?.debug(\n `Subscribed to audio event listener and analysis listener`,\n {\n subscribeAudio,\n }\n )\n\n return () => {\n logger?.debug(`Removing audio event listener`)\n subscribeAudio.remove()\n }\n }, [handleAudioEvent, handleAudioAnalysis])\n\n useEffect(() => {\n // Add event subscription for recording interruptions\n logger?.debug('Setting up recording interruption listener')\n\n const subscription = addRecordingInterruptionListener((event) => {\n logger?.debug('Received recording interruption event:', event)\n\n // Check if we have a callback configured\n if (recordingConfigRef.current?.onRecordingInterrupted) {\n try {\n recordingConfigRef.current.onRecordingInterrupted(event)\n } catch (error) {\n logger?.error(\n 'Error in recording interruption callback:',\n error\n )\n }\n } else {\n logger?.warn('No recording interruption callback configured')\n }\n })\n\n return () => {\n logger?.debug('Removing recording interruption listener')\n subscription.remove()\n }\n }, []) // Empty dependency array since we want this to run once\n\n return {\n startRecording,\n stopRecording,\n pauseRecording,\n resumeRecording,\n isPaused: state.isPaused,\n isRecording: state.isRecording,\n durationMs: state.durationMs,\n size: state.size,\n compression: state.compression,\n analysisData: state.analysisData,\n }\n}\n"]}
@@ -11,7 +11,6 @@ import Accelerate
11
11
  import UIKit
12
12
  import MediaPlayer
13
13
  import UserNotifications
14
- import CallKit
15
14
 
16
15
  // Helper to convert to little-endian byte array
17
16
  extension UInt32 {
@@ -566,17 +565,26 @@ class AudioStreamManager: NSObject {
566
565
  return status
567
566
  }
568
567
 
568
+ /// Detects if a phone call is active without using CallKit.
569
+ /// We avoid CallKit because its usage prevents apps from being available in China's App Store.
570
+ /// This is a workaround that uses AVAudioSession to detect phone calls instead.
571
+ private func isPhoneCallActive() -> Bool {
572
+ let audioSession = AVAudioSession.sharedInstance()
573
+ return audioSession.isOtherAudioPlaying &&
574
+ audioSession.secondaryAudioShouldBeSilencedHint &&
575
+ audioSession.currentRoute.outputs.contains { $0.portType == .builtInReceiver }
576
+ }
577
+
569
578
  /// Starts a new audio recording with the specified settings and interval.
570
579
  /// - Parameters:
571
580
  /// - settings: The recording settings to use.
572
581
  /// - intervalMilliseconds: The interval in milliseconds for emitting audio data.
573
582
  /// - Returns: A StartRecordingResult object if recording starts successfully, or nil otherwise.
574
583
  func startRecording(settings: RecordingSettings, intervalMilliseconds: Int) -> StartRecordingResult? {
575
- // Check for active call first
576
- let callCenter = CXCallObserver()
577
- if callCenter.calls.contains(where: { $0.hasEnded == false }) {
578
- Logger.debug("Cannot start recording during an active call")
579
- delegate?.audioStreamManager(self, didFailWithError: "Cannot start recording during an active call")
584
+ // Check for active call using the new method
585
+ if isPhoneCallActive() {
586
+ Logger.debug("Cannot start recording during an active phone call")
587
+ delegate?.audioStreamManager(self, didFailWithError: "Cannot start recording during an active phone call")
580
588
  return nil
581
589
  }
582
590
 
@@ -717,11 +725,12 @@ class AudioStreamManager: NSObject {
717
725
  if settings.enableCompressedOutput {
718
726
  do {
719
727
  let compressedSettings: [String: Any] = [
720
- AVFormatIDKey: kAudioFormatMPEG4AAC,
728
+ AVFormatIDKey: settings.compressedFormat == "aac" ? kAudioFormatMPEG4AAC : kAudioFormatOpus,
721
729
  AVSampleRateKey: Float64(settings.sampleRate),
722
730
  AVNumberOfChannelsKey: settings.numberOfChannels,
723
- AVEncoderBitRateKey: settings.compressedBitRate ?? 24000,
724
- AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
731
+ AVEncoderBitRateKey: settings.compressedBitRate,
732
+ AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue,
733
+ AVEncoderBitDepthHintKey: settings.bitDepth
725
734
  ]
726
735
 
727
736
  Logger.debug("Initializing compressed recording with settings: \(compressedSettings)")
@@ -735,21 +744,23 @@ class AudioStreamManager: NSObject {
735
744
  do {
736
745
  compressedRecorder = try AVAudioRecorder(url: url, settings: compressedSettings)
737
746
  if let recorder = compressedRecorder {
738
- recorder.delegate = self // Add this line to get recording callbacks
747
+ recorder.delegate = self
739
748
 
740
749
  if !recorder.prepareToRecord() {
741
750
  Logger.debug("Failed to prepare recorder")
742
- throw NSError(domain: "AudioStreamManager", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to prepare recorder"])
751
+ throw NSError(domain: "AudioStreamManager", code: -1,
752
+ userInfo: [NSLocalizedDescriptionKey: "Failed to prepare recorder"])
743
753
  }
744
754
 
745
755
  if !recorder.record() {
746
756
  Logger.debug("Failed to start recorder")
747
- throw NSError(domain: "AudioStreamManager", code: -2, userInfo: [NSLocalizedDescriptionKey: "Failed to start recorder"])
757
+ throw NSError(domain: "AudioStreamManager", code: -2,
758
+ userInfo: [NSLocalizedDescriptionKey: "Failed to start recorder"])
748
759
  }
749
760
 
750
761
  Logger.debug("Compressed recording started successfully")
751
- compressedFormat = "aac"
752
- compressedBitRate = settings.compressedBitRate ?? 24000
762
+ compressedFormat = settings.compressedFormat
763
+ compressedBitRate = settings.compressedBitRate
753
764
  }
754
765
  } catch {
755
766
  Logger.debug("Failed to initialize compressed recorder: \(error)")
@@ -919,11 +930,10 @@ class AudioStreamManager: NSObject {
919
930
 
920
931
  /// Resumes the current audio recording.
921
932
  func resumeRecording() {
922
- // Check for active call first
923
- let callCenter = CXCallObserver()
924
- if callCenter.calls.contains(where: { $0.hasEnded == false }) {
925
- Logger.debug("Cannot resume recording during an active call")
926
- delegate?.audioStreamManager(self, didFailWithError: "Cannot resume recording during an active call")
933
+ // Check for active call using the new method
934
+ if isPhoneCallActive() {
935
+ Logger.debug("Cannot resume recording during an active phone call")
936
+ delegate?.audioStreamManager(self, didFailWithError: "Cannot resume recording during an active phone call")
927
937
  return
928
938
  }
929
939
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@siteed/expo-audio-stream",
3
- "version": "1.15.0",
3
+ "version": "1.16.0",
4
4
  "description": "stream audio crossplatform",
5
5
  "license": "MIT",
6
6
  "main": "build/index.js",
@@ -37,13 +37,14 @@ const withRecordingPermission = (config, props) => {
37
37
  config.modResults['NSUserNotificationAlertStyle'] = 'alert';
38
38
  }
39
39
  const existingBackgroundModes = config.modResults.UIBackgroundModes || [];
40
- // Only add background modes if explicitly enabled
41
- if (options.iosBackgroundModes?.useAudio &&
42
- enableBackgroundAudio &&
40
+ // Only add background modes if explicitly enabled and set to true
41
+ if (options.iosBackgroundModes?.useAudio === true &&
42
+ enableBackgroundAudio === true &&
43
43
  !existingBackgroundModes.includes('audio')) {
44
44
  existingBackgroundModes.push('audio');
45
45
  }
46
- if (options.iosBackgroundModes?.useVoIP && enablePhoneStateHandling) {
46
+ if (options.iosBackgroundModes?.useVoIP === true &&
47
+ enablePhoneStateHandling === true) {
47
48
  if (!existingBackgroundModes.includes('voip')) {
48
49
  existingBackgroundModes.push('voip');
49
50
  }
@@ -55,22 +56,22 @@ const withRecordingPermission = (config, props) => {
55
56
  config.modResults.UIRequiredDeviceCapabilities =
56
57
  existingCapabilities;
57
58
  }
58
- // Add additional background modes if enabled
59
- if (options.iosBackgroundModes?.useProcessing) {
59
+ // Add additional background modes only if explicitly set to true
60
+ if (options.iosBackgroundModes?.useProcessing === true) {
60
61
  if (!existingBackgroundModes.includes('processing')) {
61
62
  existingBackgroundModes.push('processing');
62
63
  }
63
64
  // Add processing info if enabled
64
65
  config.modResults.BGTaskSchedulerPermittedIdentifiers = [
65
- 'com.siteed.audiostream.processing'
66
+ 'com.siteed.audiostream.processing',
66
67
  ];
67
68
  }
68
- if (options.iosBackgroundModes?.useLocation) {
69
+ if (options.iosBackgroundModes?.useLocation === true) {
69
70
  if (!existingBackgroundModes.includes('location')) {
70
71
  existingBackgroundModes.push('location');
71
72
  }
72
73
  }
73
- if (options.iosBackgroundModes?.useExternalAccessory) {
74
+ if (options.iosBackgroundModes?.useExternalAccessory === true) {
74
75
  if (!existingBackgroundModes.includes('external-accessory')) {
75
76
  existingBackgroundModes.push('external-accessory');
76
77
  }
@@ -84,7 +85,7 @@ const withRecordingPermission = (config, props) => {
84
85
  if (options.iosConfig?.allowBackgroundAudioControls) {
85
86
  config.modResults.UIBackgroundModes = [
86
87
  ...existingBackgroundModes,
87
- 'remote-notification'
88
+ 'remote-notification',
88
89
  ];
89
90
  config.modResults.MPNowPlayingInfoPropertyPlaybackRate = true;
90
91
  }
@@ -17,7 +17,7 @@ function debugLog(message: string, ...args: unknown[]): void {
17
17
  }
18
18
 
19
19
  interface AudioStreamPluginOptions {
20
- enablePhoneStateHandling?: boolean // Controls READ_PHONE_STATE permission
20
+ enablePhoneStateHandling?: boolean // Controls READ_PHONE_STATE permission
21
21
  enableNotifications?: boolean
22
22
  enableBackgroundAudio?: boolean
23
23
  iosBackgroundModes?: {
@@ -38,7 +38,7 @@ const withRecordingPermission: ConfigPlugin<AudioStreamPluginOptions> = (
38
38
  props: AudioStreamPluginOptions | void
39
39
  ) => {
40
40
  const options: AudioStreamPluginOptions = {
41
- enablePhoneStateHandling: true, // Default to true for backward compatibility
41
+ enablePhoneStateHandling: true, // Default to true for backward compatibility
42
42
  enableNotifications: true,
43
43
  enableBackgroundAudio: true,
44
44
  iosBackgroundModes: {
@@ -75,16 +75,19 @@ const withRecordingPermission: ConfigPlugin<AudioStreamPluginOptions> = (
75
75
  const existingBackgroundModes =
76
76
  config.modResults.UIBackgroundModes || []
77
77
 
78
- // Only add background modes if explicitly enabled
78
+ // Only add background modes if explicitly enabled and set to true
79
79
  if (
80
- options.iosBackgroundModes?.useAudio &&
81
- enableBackgroundAudio &&
80
+ options.iosBackgroundModes?.useAudio === true &&
81
+ enableBackgroundAudio === true &&
82
82
  !existingBackgroundModes.includes('audio')
83
83
  ) {
84
84
  existingBackgroundModes.push('audio')
85
85
  }
86
86
 
87
- if (options.iosBackgroundModes?.useVoIP && enablePhoneStateHandling) {
87
+ if (
88
+ options.iosBackgroundModes?.useVoIP === true &&
89
+ enablePhoneStateHandling === true
90
+ ) {
88
91
  if (!existingBackgroundModes.includes('voip')) {
89
92
  existingBackgroundModes.push('voip')
90
93
  }
@@ -97,24 +100,24 @@ const withRecordingPermission: ConfigPlugin<AudioStreamPluginOptions> = (
97
100
  existingCapabilities
98
101
  }
99
102
 
100
- // Add additional background modes if enabled
101
- if (options.iosBackgroundModes?.useProcessing) {
103
+ // Add additional background modes only if explicitly set to true
104
+ if (options.iosBackgroundModes?.useProcessing === true) {
102
105
  if (!existingBackgroundModes.includes('processing')) {
103
106
  existingBackgroundModes.push('processing')
104
107
  }
105
108
  // Add processing info if enabled
106
109
  config.modResults.BGTaskSchedulerPermittedIdentifiers = [
107
- 'com.siteed.audiostream.processing'
110
+ 'com.siteed.audiostream.processing',
108
111
  ]
109
112
  }
110
113
 
111
- if (options.iosBackgroundModes?.useLocation) {
114
+ if (options.iosBackgroundModes?.useLocation === true) {
112
115
  if (!existingBackgroundModes.includes('location')) {
113
116
  existingBackgroundModes.push('location')
114
117
  }
115
118
  }
116
119
 
117
- if (options.iosBackgroundModes?.useExternalAccessory) {
120
+ if (options.iosBackgroundModes?.useExternalAccessory === true) {
118
121
  if (!existingBackgroundModes.includes('external-accessory')) {
119
122
  existingBackgroundModes.push('external-accessory')
120
123
  }
@@ -122,7 +125,7 @@ const withRecordingPermission: ConfigPlugin<AudioStreamPluginOptions> = (
122
125
 
123
126
  // Configure background processing info if enabled
124
127
  if (options.iosConfig?.backgroundProcessingTitle) {
125
- config.modResults.BGProcessingTaskTitle =
128
+ config.modResults.BGProcessingTaskTitle =
126
129
  options.iosConfig.backgroundProcessingTitle
127
130
  }
128
131
 
@@ -130,7 +133,7 @@ const withRecordingPermission: ConfigPlugin<AudioStreamPluginOptions> = (
130
133
  if (options.iosConfig?.allowBackgroundAudioControls) {
131
134
  config.modResults.UIBackgroundModes = [
132
135
  ...existingBackgroundModes,
133
- 'remote-notification'
136
+ 'remote-notification',
134
137
  ]
135
138
  config.modResults.MPNowPlayingInfoPropertyPlaybackRate = true
136
139
  }
@@ -182,7 +182,7 @@ export interface RecordingConfig {
182
182
 
183
183
  compression?: {
184
184
  enabled: boolean
185
- format: 'aac' | 'opus' | 'mp3'
185
+ format: 'aac' | 'opus'
186
186
  bitrate?: number
187
187
  }
188
188
 
@@ -281,11 +281,11 @@ export function useAudioRecorder({
281
281
 
282
282
  // Call the onAudioAnalysis callback if it exists in the recording config
283
283
  if (recordingConfigRef.current?.onAudioAnalysis) {
284
- try {
285
- await recordingConfigRef.current.onAudioAnalysis(analysis)
286
- } catch (error) {
287
- logger?.error('Error in onAudioAnalysis callback:', error)
288
- }
284
+ recordingConfigRef.current
285
+ .onAudioAnalysis(analysis)
286
+ .catch((error) => {
287
+ logger?.warn(`Error processing audio analysis:`, error)
288
+ })
289
289
  }
290
290
 
291
291
  // Update the ref