@siteed/expo-audio-stream 2.0.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/README.md +46 -27
  2. package/build/index.d.ts +11 -12
  3. package/build/index.js +44 -10
  4. package/package.json +49 -110
  5. package/src/index.ts +18 -33
  6. package/CHANGELOG.md +0 -195
  7. package/android/build.gradle +0 -105
  8. package/android/src/main/AndroidManifest.xml +0 -27
  9. package/android/src/main/java/net/siteed/audiostream/AudioAnalysisData.kt +0 -166
  10. package/android/src/main/java/net/siteed/audiostream/AudioDataEncoder.kt +0 -9
  11. package/android/src/main/java/net/siteed/audiostream/AudioFileHandler.kt +0 -131
  12. package/android/src/main/java/net/siteed/audiostream/AudioFormatUtils.kt +0 -103
  13. package/android/src/main/java/net/siteed/audiostream/AudioNotificationsManager.kt +0 -435
  14. package/android/src/main/java/net/siteed/audiostream/AudioProcessor.kt +0 -1936
  15. package/android/src/main/java/net/siteed/audiostream/AudioRecorderManager.kt +0 -1437
  16. package/android/src/main/java/net/siteed/audiostream/AudioRecordingService.kt +0 -138
  17. package/android/src/main/java/net/siteed/audiostream/Constants.kt +0 -20
  18. package/android/src/main/java/net/siteed/audiostream/EventSender.kt +0 -7
  19. package/android/src/main/java/net/siteed/audiostream/ExpoAudioStreamModule.kt +0 -509
  20. package/android/src/main/java/net/siteed/audiostream/FFT.kt +0 -99
  21. package/android/src/main/java/net/siteed/audiostream/Features.kt +0 -98
  22. package/android/src/main/java/net/siteed/audiostream/NotificationConfig.kt +0 -70
  23. package/android/src/main/java/net/siteed/audiostream/PermissionUtils.kt +0 -59
  24. package/android/src/main/java/net/siteed/audiostream/RecordingActionReceiver.kt +0 -59
  25. package/android/src/main/java/net/siteed/audiostream/RecordingConfig.kt +0 -205
  26. package/android/src/main/java/net/siteed/audiostream/WaveformConfig.kt +0 -19
  27. package/android/src/main/java/net/siteed/audiostream/WaveformRenderer.kt +0 -159
  28. package/android/src/main/res/drawable/ic_default_action_icon.xml +0 -16
  29. package/android/src/main/res/drawable/ic_microphone.xml +0 -13
  30. package/android/src/main/res/drawable/ic_pause.xml +0 -10
  31. package/android/src/main/res/drawable/ic_play.xml +0 -10
  32. package/android/src/main/res/drawable/ic_stop.xml +0 -10
  33. package/android/src/main/res/layout/notification_recording.xml +0 -37
  34. package/android/src/main/test/java/net/siteed/audiostream/AudioProcessorTest.kt +0 -56
  35. package/app.plugin.js +0 -1
  36. package/build/AudioAnalysis/AudioAnalysis.types.d.ts +0 -144
  37. package/build/AudioAnalysis/AudioAnalysis.types.d.ts.map +0 -1
  38. package/build/AudioAnalysis/AudioAnalysis.types.js +0 -3
  39. package/build/AudioAnalysis/AudioAnalysis.types.js.map +0 -1
  40. package/build/AudioAnalysis/extractAudioAnalysis.d.ts +0 -78
  41. package/build/AudioAnalysis/extractAudioAnalysis.d.ts.map +0 -1
  42. package/build/AudioAnalysis/extractAudioAnalysis.js +0 -229
  43. package/build/AudioAnalysis/extractAudioAnalysis.js.map +0 -1
  44. package/build/AudioAnalysis/extractWaveform.d.ts +0 -8
  45. package/build/AudioAnalysis/extractWaveform.d.ts.map +0 -1
  46. package/build/AudioAnalysis/extractWaveform.js +0 -11
  47. package/build/AudioAnalysis/extractWaveform.js.map +0 -1
  48. package/build/AudioRecorder.provider.d.ts +0 -11
  49. package/build/AudioRecorder.provider.d.ts.map +0 -1
  50. package/build/AudioRecorder.provider.js +0 -37
  51. package/build/AudioRecorder.provider.js.map +0 -1
  52. package/build/ExpoAudioStream.native.d.ts +0 -3
  53. package/build/ExpoAudioStream.native.d.ts.map +0 -1
  54. package/build/ExpoAudioStream.native.js +0 -6
  55. package/build/ExpoAudioStream.native.js.map +0 -1
  56. package/build/ExpoAudioStream.types.d.ts +0 -206
  57. package/build/ExpoAudioStream.types.d.ts.map +0 -1
  58. package/build/ExpoAudioStream.types.js +0 -2
  59. package/build/ExpoAudioStream.types.js.map +0 -1
  60. package/build/ExpoAudioStream.web.d.ts +0 -59
  61. package/build/ExpoAudioStream.web.d.ts.map +0 -1
  62. package/build/ExpoAudioStream.web.js +0 -285
  63. package/build/ExpoAudioStream.web.js.map +0 -1
  64. package/build/ExpoAudioStreamModule.d.ts +0 -3
  65. package/build/ExpoAudioStreamModule.d.ts.map +0 -1
  66. package/build/ExpoAudioStreamModule.js +0 -239
  67. package/build/ExpoAudioStreamModule.js.map +0 -1
  68. package/build/WebRecorder.web.d.ts +0 -119
  69. package/build/WebRecorder.web.d.ts.map +0 -1
  70. package/build/WebRecorder.web.js +0 -436
  71. package/build/WebRecorder.web.js.map +0 -1
  72. package/build/constants.d.ts +0 -11
  73. package/build/constants.d.ts.map +0 -1
  74. package/build/constants.js +0 -14
  75. package/build/constants.js.map +0 -1
  76. package/build/events.d.ts +0 -26
  77. package/build/events.d.ts.map +0 -1
  78. package/build/events.js +0 -21
  79. package/build/events.js.map +0 -1
  80. package/build/index.d.ts.map +0 -1
  81. package/build/index.js.map +0 -1
  82. package/build/useAudioRecorder.d.ts +0 -21
  83. package/build/useAudioRecorder.d.ts.map +0 -1
  84. package/build/useAudioRecorder.js +0 -427
  85. package/build/useAudioRecorder.js.map +0 -1
  86. package/build/utils/BlobFix.d.ts +0 -9
  87. package/build/utils/BlobFix.d.ts.map +0 -1
  88. package/build/utils/BlobFix.js +0 -498
  89. package/build/utils/BlobFix.js.map +0 -1
  90. package/build/utils/audioProcessing.d.ts +0 -24
  91. package/build/utils/audioProcessing.d.ts.map +0 -1
  92. package/build/utils/audioProcessing.js +0 -133
  93. package/build/utils/audioProcessing.js.map +0 -1
  94. package/build/utils/concatenateBuffers.d.ts +0 -8
  95. package/build/utils/concatenateBuffers.d.ts.map +0 -1
  96. package/build/utils/concatenateBuffers.js +0 -21
  97. package/build/utils/concatenateBuffers.js.map +0 -1
  98. package/build/utils/convertPCMToFloat32.d.ts +0 -13
  99. package/build/utils/convertPCMToFloat32.d.ts.map +0 -1
  100. package/build/utils/convertPCMToFloat32.js +0 -120
  101. package/build/utils/convertPCMToFloat32.js.map +0 -1
  102. package/build/utils/encodingToBitDepth.d.ts +0 -5
  103. package/build/utils/encodingToBitDepth.d.ts.map +0 -1
  104. package/build/utils/encodingToBitDepth.js +0 -13
  105. package/build/utils/encodingToBitDepth.js.map +0 -1
  106. package/build/utils/getWavFileInfo.d.ts +0 -26
  107. package/build/utils/getWavFileInfo.d.ts.map +0 -1
  108. package/build/utils/getWavFileInfo.js +0 -92
  109. package/build/utils/getWavFileInfo.js.map +0 -1
  110. package/build/utils/writeWavHeader.d.ts +0 -49
  111. package/build/utils/writeWavHeader.d.ts.map +0 -1
  112. package/build/utils/writeWavHeader.js +0 -91
  113. package/build/utils/writeWavHeader.js.map +0 -1
  114. package/build/workers/InlineFeaturesExtractor.web.d.ts +0 -2
  115. package/build/workers/InlineFeaturesExtractor.web.d.ts.map +0 -1
  116. package/build/workers/InlineFeaturesExtractor.web.js +0 -828
  117. package/build/workers/InlineFeaturesExtractor.web.js.map +0 -1
  118. package/build/workers/inlineAudioWebWorker.web.d.ts +0 -2
  119. package/build/workers/inlineAudioWebWorker.web.d.ts.map +0 -1
  120. package/build/workers/inlineAudioWebWorker.web.js +0 -157
  121. package/build/workers/inlineAudioWebWorker.web.js.map +0 -1
  122. package/expo-module.config.json +0 -9
  123. package/ios/AudioAnalysisData.swift +0 -74
  124. package/ios/AudioNotificationManager.swift +0 -135
  125. package/ios/AudioProcessingHelpers.swift +0 -743
  126. package/ios/AudioProcessor.swift +0 -858
  127. package/ios/AudioStreamError.swift +0 -7
  128. package/ios/AudioStreamManager.swift +0 -1708
  129. package/ios/AudioStreamManagerDelegate.swift +0 -16
  130. package/ios/DataPoint.swift +0 -54
  131. package/ios/DecodingConfig.swift +0 -47
  132. package/ios/ExpoAudioStream.podspec +0 -27
  133. package/ios/ExpoAudioStreamModule.swift +0 -698
  134. package/ios/FFT.swift +0 -62
  135. package/ios/Features.swift +0 -95
  136. package/ios/Logger.swift +0 -7
  137. package/ios/NotificationExtension.swift +0 -15
  138. package/ios/RecordingResult.swift +0 -22
  139. package/ios/RecordingSettings.swift +0 -265
  140. package/ios/WaveformExtractor.swift +0 -105
  141. package/plugin/build/index.d.ts +0 -21
  142. package/plugin/build/index.js +0 -191
  143. package/plugin/src/index.ts +0 -278
  144. package/plugin/tsconfig.json +0 -10
  145. package/plugin/tsconfig.tsbuildinfo +0 -1
  146. package/src/AudioAnalysis/AudioAnalysis.types.ts +0 -165
  147. package/src/AudioAnalysis/extractAudioAnalysis.ts +0 -370
  148. package/src/AudioAnalysis/extractWaveform.ts +0 -22
  149. package/src/AudioRecorder.provider.tsx +0 -54
  150. package/src/ExpoAudioStream.native.ts +0 -6
  151. package/src/ExpoAudioStream.types.ts +0 -329
  152. package/src/ExpoAudioStream.web.ts +0 -359
  153. package/src/ExpoAudioStreamModule.ts +0 -286
  154. package/src/WebRecorder.web.ts +0 -580
  155. package/src/constants.ts +0 -18
  156. package/src/events.ts +0 -60
  157. package/src/useAudioRecorder.tsx +0 -620
  158. package/src/utils/BlobFix.ts +0 -559
  159. package/src/utils/audioProcessing.ts +0 -205
  160. package/src/utils/concatenateBuffers.ts +0 -24
  161. package/src/utils/convertPCMToFloat32.ts +0 -170
  162. package/src/utils/encodingToBitDepth.ts +0 -18
  163. package/src/utils/getWavFileInfo.ts +0 -132
  164. package/src/utils/writeWavHeader.ts +0 -114
  165. package/src/workers/InlineFeaturesExtractor.web.tsx +0 -827
  166. package/src/workers/inlineAudioWebWorker.web.tsx +0 -156
@@ -1 +0,0 @@
1
- {"version":3,"file":"ExpoAudioStreamModule.js","sourceRoot":"","sources":["../src/ExpoAudioStreamModule.ts"],"names":[],"mappings":"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","sourcesContent":["import crc32 from 'crc-32'\nimport { requireNativeModule } from 'expo-modules-core'\nimport { Platform } from 'react-native'\n\nimport {\n ExtractAudioDataOptions,\n ExtractedAudioData,\n BitDepth,\n} from './ExpoAudioStream.types'\nimport {\n ExpoAudioStreamWeb,\n ExpoAudioStreamWebProps,\n} from './ExpoAudioStream.web'\nimport { processAudioBuffer } from './utils/audioProcessing'\nimport { writeWavHeader } from './utils/writeWavHeader'\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet ExpoAudioStreamModule: any\n\nif (Platform.OS === 'web') {\n let instance: ExpoAudioStreamWeb | null = null\n\n ExpoAudioStreamModule = (webProps: ExpoAudioStreamWebProps) => {\n if (!instance) {\n instance = new ExpoAudioStreamWeb(webProps)\n }\n return instance\n }\n ExpoAudioStreamModule.requestPermissionsAsync = async () => {\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: true,\n })\n stream.getTracks().forEach((track) => track.stop())\n return {\n status: 'granted',\n expires: 'never',\n canAskAgain: true,\n granted: true,\n }\n } catch {\n return {\n status: 'denied',\n expires: 'never',\n canAskAgain: true,\n granted: false,\n }\n }\n }\n ExpoAudioStreamModule.getPermissionsAsync = async () => {\n let maybeStatus: string | null = null\n\n if (navigator?.permissions?.query) {\n try {\n const { state } = await navigator.permissions.query({\n name: 'microphone' as PermissionName,\n })\n maybeStatus = state\n } catch {\n maybeStatus = null\n }\n }\n\n switch (maybeStatus) {\n case 'granted':\n return {\n status: 'granted',\n expires: 'never',\n canAskAgain: true,\n granted: true,\n }\n case 'denied':\n return {\n status: 'denied',\n expires: 'never',\n canAskAgain: true,\n granted: false,\n }\n default:\n return await ExpoAudioStreamModule.requestPermissionsAsync()\n }\n }\n ExpoAudioStreamModule.extractAudioData = async (\n options: ExtractAudioDataOptions\n ): Promise<ExtractedAudioData> => {\n try {\n const {\n fileUri,\n position,\n length,\n startTimeMs,\n endTimeMs,\n decodingOptions,\n includeNormalizedData,\n includeBase64Data,\n includeWavHeader = false,\n logger,\n } = options\n\n logger?.debug('EXTRACT AUDIO - Step 1: Initial request', {\n fileUri,\n extractionParams: {\n position,\n length,\n startTimeMs,\n endTimeMs,\n },\n decodingOptions: {\n targetSampleRate:\n decodingOptions?.targetSampleRate ?? 16000,\n targetChannels: decodingOptions?.targetChannels ?? 1,\n targetBitDepth: decodingOptions?.targetBitDepth ?? 16,\n normalizeAudio: decodingOptions?.normalizeAudio ?? false,\n },\n outputOptions: {\n includeNormalizedData,\n includeBase64Data,\n includeWavHeader,\n },\n })\n\n // Process the audio using shared helper function\n const processedBuffer = await processAudioBuffer({\n fileUri,\n targetSampleRate: decodingOptions?.targetSampleRate ?? 16000,\n targetChannels: decodingOptions?.targetChannels ?? 1,\n normalizeAudio: decodingOptions?.normalizeAudio ?? false,\n position,\n length,\n startTimeMs,\n endTimeMs,\n logger,\n })\n\n logger?.debug('EXTRACT AUDIO - Step 2: Audio processing complete', {\n processedData: {\n samples: processedBuffer.samples,\n sampleRate: processedBuffer.sampleRate,\n channels: processedBuffer.channels,\n durationMs: processedBuffer.durationMs,\n },\n })\n\n const channelData = processedBuffer.channelData\n const bitDepth = (decodingOptions?.targetBitDepth ?? 16) as BitDepth\n const bytesPerSample = bitDepth / 8\n const numSamples = processedBuffer.samples\n\n logger?.debug('EXTRACT AUDIO - Step 3: PCM conversion setup', {\n channelData: {\n length: channelData.length,\n first: channelData[0],\n last: channelData[channelData.length - 1],\n },\n calculation: {\n bitDepth,\n bytesPerSample,\n numSamples,\n expectedBytes: numSamples * bytesPerSample,\n },\n })\n\n // Create PCM data with correct length based on original byte length\n const pcmData = new Uint8Array(numSamples * bytesPerSample)\n let offset = 0\n\n // Convert Float32 samples to PCM format\n for (let i = 0; i < numSamples; i++) {\n const sample = channelData[i]\n const value = Math.max(-1, Math.min(1, sample))\n // Convert to 16-bit signed integer\n let intValue = Math.round(value * 32767)\n\n // Handle negative values correctly\n if (intValue < 0) {\n intValue = 65536 + intValue\n }\n\n // Write as little-endian\n pcmData[offset++] = intValue & 255 // Low byte\n pcmData[offset++] = (intValue >> 8) & 255 // High byte\n }\n\n const durationMs = Math.round(\n (numSamples / processedBuffer.sampleRate) * 1000\n )\n\n logger?.debug('EXTRACT AUDIO - Step 4: Final output', {\n pcmData: {\n length: pcmData.length,\n first: pcmData[0],\n last: pcmData[pcmData.length - 1],\n },\n timing: {\n numSamples,\n sampleRate: processedBuffer.sampleRate,\n durationMs,\n shouldBe3000ms: endTimeMs\n ? endTimeMs - (startTimeMs ?? 0) === 3000\n : undefined,\n },\n })\n\n const result: ExtractedAudioData = {\n pcmData: new Uint8Array(pcmData.buffer),\n sampleRate: processedBuffer.sampleRate,\n channels: processedBuffer.channels,\n bitDepth,\n durationMs,\n format: `pcm_${bitDepth}bit` as const,\n samples: numSamples,\n }\n\n // Add WAV header if requested\n if (includeWavHeader) {\n logger?.debug('EXTRACT AUDIO - Step 4: Adding WAV header', {\n originalLength: pcmData.length,\n newLength: result.pcmData.length,\n firstBytes: Array.from(result.pcmData.slice(0, 44)), // WAV header is 44 bytes\n })\n const wavBuffer = writeWavHeader({\n buffer: pcmData.buffer.slice(0, pcmData.length),\n sampleRate: processedBuffer.sampleRate,\n numChannels: processedBuffer.channels,\n bitDepth,\n })\n result.pcmData = new Uint8Array(wavBuffer)\n result.hasWavHeader = true\n }\n\n if (includeNormalizedData) {\n // // Simple approach: Create normalized data directly from the PCM data\n // // Just convert to -1 to 1 range without any amplification\n // const normalizedData = new Float32Array(numSamples)\n\n // // Convert the PCM data to float values\n // for (let i = 0; i < numSamples; i++) {\n // // Get the 16-bit PCM value (little endian)\n // const lowByte = pcmData[i * 2]\n // const highByte = pcmData[i * 2 + 1]\n // const pcmValue = (highByte << 8) | lowByte\n\n // // Convert to signed 16-bit value\n // const signedValue =\n // pcmValue > 32767 ? pcmValue - 65536 : pcmValue\n\n // // Normalize to float between -1 and 1\n // normalizedData[i] = signedValue / 32768.0\n // }\n // Store the normalized data in the result\n result.normalizedData = channelData\n }\n\n if (includeBase64Data) {\n // Convert the PCM data to a base64 string\n const binary = Array.from(new Uint8Array(pcmData.buffer))\n .map((b) => String.fromCharCode(b))\n .join('')\n result.base64Data = btoa(binary)\n }\n\n if (options.computeChecksum) {\n result.checksum = crc32.buf(pcmData)\n }\n\n logger?.debug('EXTRACT AUDIO - Step 3: PCM conversion complete', {\n pcmStats: {\n length: pcmData.length,\n bytesPerSample,\n totalSamples: numSamples,\n firstBytes: Array.from(pcmData.slice(0, 16)),\n lastBytes: Array.from(pcmData.slice(-16)),\n },\n })\n\n return result\n } catch (error) {\n options.logger?.error('EXTRACT AUDIO - Error:', error)\n throw error\n }\n }\n} else {\n ExpoAudioStreamModule = requireNativeModule('ExpoAudioStream')\n}\n\nexport default ExpoAudioStreamModule\n"]}
@@ -1,119 +0,0 @@
1
- import { AudioAnalysis } from './AudioAnalysis/AudioAnalysis.types';
2
- import { ConsoleLike, RecordingConfig } from './ExpoAudioStream.types';
3
- import { EmitAudioAnalysisFunction, EmitAudioEventFunction } from './ExpoAudioStream.web';
4
- interface AudioFeaturesEvent {
5
- data: {
6
- command: string;
7
- result: AudioAnalysis;
8
- };
9
- }
10
- export declare class WebRecorder {
11
- private audioContext;
12
- private audioWorkletNode;
13
- private featureExtractorWorker?;
14
- private source;
15
- private emitAudioEventCallback;
16
- private emitAudioAnalysisCallback;
17
- private config;
18
- private position;
19
- private numberOfChannels;
20
- private bitDepth;
21
- private exportBitDepth;
22
- private audioAnalysisData;
23
- private packetCount;
24
- private logger?;
25
- private compressedMediaRecorder;
26
- private compressedChunks;
27
- private compressedSize;
28
- private pendingCompressedChunk;
29
- private readonly wavMimeType;
30
- private dataPointIdCounter;
31
- /**
32
- * Initializes a new WebRecorder instance for audio recording and processing
33
- * @param audioContext - The AudioContext to use for recording
34
- * @param source - The MediaStreamAudioSourceNode providing the audio input
35
- * @param recordingConfig - Configuration options for the recording
36
- * @param emitAudioEventCallback - Callback function for audio data events
37
- * @param emitAudioAnalysisCallback - Callback function for audio analysis events
38
- * @param logger - Optional logger for debugging information
39
- */
40
- constructor({ audioContext, source, recordingConfig, emitAudioEventCallback, emitAudioAnalysisCallback, logger, }: {
41
- audioContext: AudioContext;
42
- source: MediaStreamAudioSourceNode;
43
- recordingConfig: RecordingConfig;
44
- emitAudioEventCallback: EmitAudioEventFunction;
45
- emitAudioAnalysisCallback: EmitAudioAnalysisFunction;
46
- logger?: ConsoleLike;
47
- });
48
- /**
49
- * Initializes the audio worklet using an inline script
50
- * Creates and connects the audio processing pipeline
51
- */
52
- init(): Promise<void>;
53
- /**
54
- * Initializes the feature extractor worker for audio analysis
55
- * Creates an inline worker from a blob for audio feature extraction
56
- */
57
- initFeatureExtractorWorker(): void;
58
- /**
59
- * Processes audio analysis results from the feature extractor worker
60
- * Updates the audio analysis data and emits events
61
- * @param event - The event containing audio analysis results
62
- */
63
- handleFeatureExtractorMessage(event: AudioFeaturesEvent): void;
64
- /**
65
- * Resets the data point ID counter
66
- * Used when starting a new recording
67
- */
68
- resetDataPointCounter(): void;
69
- /**
70
- * Starts the audio recording process
71
- * Connects the audio nodes and begins capturing audio data
72
- */
73
- start(): void;
74
- /**
75
- * Stops the audio recording process and returns the recorded data
76
- * @returns Promise resolving to an object containing PCM data and optional compressed blob
77
- */
78
- stop(): Promise<{
79
- pcmData: Float32Array;
80
- compressedBlob?: Blob;
81
- }>;
82
- /**
83
- * Cleans up resources when recording is stopped
84
- * Closes audio context and disconnects nodes
85
- */
86
- private cleanup;
87
- /**
88
- * Pauses the audio recording process
89
- * Disconnects audio nodes and pauses the media recorder
90
- */
91
- pause(): void;
92
- /**
93
- * Stops all media stream tracks to release hardware resources
94
- * Ensures recording indicators (like microphone icon) are turned off
95
- */
96
- stopMediaStreamTracks(): void;
97
- /**
98
- * Determines the audio format capabilities of the current audio context
99
- * @param sampleRate - The sample rate to check
100
- * @returns Object containing format information (sample rate, bit depth, channels)
101
- */
102
- private checkAudioContextFormat;
103
- /**
104
- * Resumes a paused recording
105
- * Reconnects audio nodes and resumes the media recorder
106
- */
107
- resume(): void;
108
- /**
109
- * Initializes the compressed media recorder if compression is enabled
110
- * Sets up event handlers for compressed audio data
111
- */
112
- private initializeCompressedRecorder;
113
- /**
114
- * Processes features if enabled
115
- */
116
- processFeatures(chunk: Float32Array, sampleRate: number, chunkPosition: number, startPosition: number, endPosition: number, samples: number): void;
117
- }
118
- export {};
119
- //# sourceMappingURL=WebRecorder.web.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"WebRecorder.web.d.ts","sourceRoot":"","sources":["../src/WebRecorder.web.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAA;AACnE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EACH,yBAAyB,EACzB,sBAAsB,EACzB,MAAM,uBAAuB,CAAA;AAa9B,UAAU,kBAAkB;IACxB,IAAI,EAAE;QACF,OAAO,EAAE,MAAM,CAAA;QACf,MAAM,EAAE,aAAa,CAAA;KACxB,CAAA;CACJ;AASD,qBAAa,WAAW;IACpB,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,sBAAsB,CAAC,CAAQ;IACvC,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,sBAAsB,CAAwB;IACtD,OAAO,CAAC,yBAAyB,CAA2B;IAC5D,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,gBAAgB,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,iBAAiB,CAAe;IACxC,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,MAAM,CAAC,CAAa;IAC5B,OAAO,CAAC,uBAAuB,CAA6B;IAC5D,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,cAAc,CAAY;IAClC,OAAO,CAAC,sBAAsB,CAAoB;IAClD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,kBAAkB,CAAY;IAEtC;;;;;;;;OAQG;gBACS,EACR,YAAY,EACZ,MAAM,EACN,eAAe,EACf,sBAAsB,EACtB,yBAAyB,EACzB,MAAM,GACT,EAAE;QACC,YAAY,EAAE,YAAY,CAAA;QAC1B,MAAM,EAAE,0BAA0B,CAAA;QAClC,eAAe,EAAE,eAAe,CAAA;QAChC,sBAAsB,EAAE,sBAAsB,CAAA;QAC9C,yBAAyB,EAAE,yBAAyB,CAAA;QACpD,MAAM,CAAC,EAAE,WAAW,CAAA;KACvB;IAmDD;;;OAGG;IACG,IAAI;IAqHV;;;OAGG;IACH,0BAA0B;IAuB1B;;;;OAIG;IACH,6BAA6B,CAAC,KAAK,EAAE,kBAAkB;IA+FvD;;;OAGG;IACH,qBAAqB;IAYrB;;;OAGG;IACH,KAAK;IAaL;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,YAAY,CAAC;QAAC,cAAc,CAAC,EAAE,IAAI,CAAA;KAAE,CAAC;IAqBvE;;;OAGG;IACH,OAAO,CAAC,OAAO;IAaf;;;OAGG;IACH,KAAK;IAOL;;;OAGG;IACH,qBAAqB;IAMrB;;;;OAIG;IACH,OAAO,CAAC,uBAAuB;IAoB/B;;;OAGG;IACH,MAAM;IAON;;;OAGG;IACH,OAAO,CAAC,4BAA4B;IAkCpC;;OAEG;IACH,eAAe,CACX,KAAK,EAAE,YAAY,EACnB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM;CAsBtB"}
@@ -1,436 +0,0 @@
1
- // packages/expo-audio-stream/src/WebRecorder.web.ts
2
- import { encodingToBitDepth } from './utils/encodingToBitDepth';
3
- import { InlineFeaturesExtractor } from './workers/InlineFeaturesExtractor.web';
4
- import { InlineAudioWebWorker } from './workers/inlineAudioWebWorker.web';
5
- const DEFAULT_WEB_BITDEPTH = 32;
6
- const DEFAULT_SEGMENT_DURATION_MS = 100;
7
- const DEFAULT_WEB_INTERVAL = 500;
8
- const DEFAULT_WEB_NUMBER_OF_CHANNELS = 1;
9
- const TAG = 'WebRecorder';
10
- export class WebRecorder {
11
- audioContext;
12
- audioWorkletNode;
13
- featureExtractorWorker;
14
- source;
15
- emitAudioEventCallback;
16
- emitAudioAnalysisCallback;
17
- config;
18
- position = 0;
19
- numberOfChannels; // Number of audio channels
20
- bitDepth; // Bit depth of the audio
21
- exportBitDepth; // Bit depth of the audio
22
- audioAnalysisData; // Keep updating the full audio analysis data with latest events
23
- packetCount = 0;
24
- logger;
25
- compressedMediaRecorder = null;
26
- compressedChunks = [];
27
- compressedSize = 0;
28
- pendingCompressedChunk = null;
29
- wavMimeType = 'audio/wav';
30
- dataPointIdCounter = 0; // Add this property to track the counter
31
- /**
32
- * Initializes a new WebRecorder instance for audio recording and processing
33
- * @param audioContext - The AudioContext to use for recording
34
- * @param source - The MediaStreamAudioSourceNode providing the audio input
35
- * @param recordingConfig - Configuration options for the recording
36
- * @param emitAudioEventCallback - Callback function for audio data events
37
- * @param emitAudioAnalysisCallback - Callback function for audio analysis events
38
- * @param logger - Optional logger for debugging information
39
- */
40
- constructor({ audioContext, source, recordingConfig, emitAudioEventCallback, emitAudioAnalysisCallback, logger, }) {
41
- this.audioContext = audioContext;
42
- this.source = source;
43
- this.emitAudioEventCallback = emitAudioEventCallback;
44
- this.emitAudioAnalysisCallback = emitAudioAnalysisCallback;
45
- this.config = recordingConfig;
46
- this.logger = logger;
47
- const audioContextFormat = this.checkAudioContextFormat({
48
- sampleRate: this.audioContext.sampleRate,
49
- });
50
- this.logger?.debug('Initialized WebRecorder with config:', {
51
- sampleRate: audioContextFormat.sampleRate,
52
- bitDepth: audioContextFormat.bitDepth,
53
- numberOfChannels: audioContextFormat.numberOfChannels,
54
- });
55
- this.bitDepth = audioContextFormat.bitDepth;
56
- this.numberOfChannels =
57
- audioContextFormat.numberOfChannels ||
58
- DEFAULT_WEB_NUMBER_OF_CHANNELS; // Default to 1 if not available
59
- this.exportBitDepth =
60
- encodingToBitDepth({
61
- encoding: recordingConfig.encoding ?? 'pcm_32bit',
62
- }) ||
63
- audioContextFormat.bitDepth ||
64
- DEFAULT_WEB_BITDEPTH;
65
- this.audioAnalysisData = {
66
- amplitudeRange: { min: 0, max: 0 },
67
- rmsRange: { min: 0, max: 0 },
68
- dataPoints: [],
69
- durationMs: 0,
70
- samples: 0,
71
- bitDepth: this.bitDepth,
72
- numberOfChannels: this.numberOfChannels,
73
- sampleRate: this.config.sampleRate || this.audioContext.sampleRate,
74
- segmentDurationMs: this.config.segmentDurationMs ?? DEFAULT_SEGMENT_DURATION_MS, // Default to 100ms segments
75
- };
76
- if (recordingConfig.enableProcessing) {
77
- this.initFeatureExtractorWorker();
78
- }
79
- // Initialize compressed recording if enabled
80
- if (recordingConfig.compression?.enabled) {
81
- this.initializeCompressedRecorder();
82
- }
83
- }
84
- /**
85
- * Initializes the audio worklet using an inline script
86
- * Creates and connects the audio processing pipeline
87
- */
88
- async init() {
89
- try {
90
- // Create and use inline audio worklet
91
- const blob = new Blob([InlineAudioWebWorker], {
92
- type: 'application/javascript',
93
- });
94
- const url = URL.createObjectURL(blob);
95
- await this.audioContext.audioWorklet.addModule(url);
96
- this.audioWorkletNode = new AudioWorkletNode(this.audioContext, 'recorder-processor');
97
- this.audioWorkletNode.port.onmessage = async (event) => {
98
- const command = event.data.command;
99
- if (command !== 'newData')
100
- return;
101
- const pcmBufferFloat = event.data.recordedData;
102
- if (!pcmBufferFloat) {
103
- this.logger?.warn('Received empty audio buffer', event);
104
- return;
105
- }
106
- // Process data in smaller chunks and emit immediately
107
- const chunkSize = this.audioContext.sampleRate * 2; // Reduce to 2 seconds chunks
108
- const sampleRate = event.data.sampleRate ?? this.audioContext.sampleRate;
109
- const duration = pcmBufferFloat.length / sampleRate;
110
- // Calculate bytes per sample based on bit depth
111
- const bytesPerSample = this.bitDepth / 8;
112
- // Emit chunks without storing them
113
- for (let i = 0; i < pcmBufferFloat.length; i += chunkSize) {
114
- const chunk = pcmBufferFloat.slice(i, i + chunkSize);
115
- const chunkPosition = this.position + i / sampleRate;
116
- // Calculate byte positions and samples
117
- const startPosition = Math.floor(i * bytesPerSample);
118
- const endPosition = Math.floor((i + chunk.length) * bytesPerSample);
119
- const samples = chunk.length; // Number of samples in this chunk
120
- // Process features if enabled
121
- if (this.config.enableProcessing &&
122
- this.featureExtractorWorker) {
123
- this.featureExtractorWorker.postMessage({
124
- command: 'process',
125
- channelData: chunk,
126
- sampleRate,
127
- segmentDurationMs: this.config.segmentDurationMs ??
128
- DEFAULT_SEGMENT_DURATION_MS, // Default to 100ms
129
- bitDepth: this.bitDepth,
130
- fullAudioDurationMs: chunkPosition * 1000,
131
- numberOfChannels: this.numberOfChannels,
132
- features: this.config.features,
133
- intervalAnalysis: this.config.intervalAnalysis,
134
- startPosition,
135
- endPosition,
136
- samples,
137
- });
138
- }
139
- // Emit chunk immediately
140
- this.emitAudioEventCallback({
141
- data: chunk,
142
- position: chunkPosition,
143
- compression: this.pendingCompressedChunk
144
- ? {
145
- data: this.pendingCompressedChunk,
146
- size: this.pendingCompressedChunk.size,
147
- totalSize: this.compressedSize,
148
- mimeType: 'audio/webm',
149
- format: 'opus',
150
- bitrate: this.config.compression?.bitrate ??
151
- 128000,
152
- }
153
- : undefined,
154
- });
155
- }
156
- this.position += duration;
157
- this.pendingCompressedChunk = null;
158
- };
159
- this.logger?.debug(`WebRecorder initialized -- recordSampleRate=${this.audioContext.sampleRate}`, this.config);
160
- this.audioWorkletNode.port.postMessage({
161
- command: 'init',
162
- recordSampleRate: this.audioContext.sampleRate,
163
- exportSampleRate: this.config.sampleRate ?? this.audioContext.sampleRate,
164
- bitDepth: this.bitDepth,
165
- exportBitDepth: this.exportBitDepth,
166
- channels: this.numberOfChannels,
167
- interval: this.config.interval ?? DEFAULT_WEB_INTERVAL,
168
- // enableLogging: !!this.logger,
169
- });
170
- // Connect the source to the AudioWorkletNode and start recording
171
- this.source.connect(this.audioWorkletNode);
172
- this.audioWorkletNode.connect(this.audioContext.destination);
173
- }
174
- catch (error) {
175
- console.error(`[${TAG}] Failed to initialize WebRecorder`, error);
176
- }
177
- }
178
- /**
179
- * Initializes the feature extractor worker for audio analysis
180
- * Creates an inline worker from a blob for audio feature extraction
181
- */
182
- initFeatureExtractorWorker() {
183
- try {
184
- const blob = new Blob([InlineFeaturesExtractor], {
185
- type: 'application/javascript',
186
- });
187
- const url = URL.createObjectURL(blob);
188
- this.featureExtractorWorker = new Worker(url);
189
- this.featureExtractorWorker.onmessage =
190
- this.handleFeatureExtractorMessage.bind(this);
191
- this.featureExtractorWorker.onerror = (error) => {
192
- console.error(`[${TAG}] Feature extractor worker error:`, error);
193
- };
194
- this.logger?.log('Feature extractor worker initialized successfully');
195
- }
196
- catch (error) {
197
- console.error(`[${TAG}] Failed to initialize feature extractor worker`, error);
198
- }
199
- }
200
- /**
201
- * Processes audio analysis results from the feature extractor worker
202
- * Updates the audio analysis data and emits events
203
- * @param event - The event containing audio analysis results
204
- */
205
- handleFeatureExtractorMessage(event) {
206
- if (event.data.command === 'features') {
207
- const segmentResult = event.data.result;
208
- // Update the dataPointIdCounter based on the last ID received
209
- if (segmentResult.dataPoints &&
210
- segmentResult.dataPoints.length > 0) {
211
- const lastDataPoint = segmentResult.dataPoints[segmentResult.dataPoints.length - 1];
212
- if (lastDataPoint && typeof lastDataPoint.id === 'number') {
213
- this.dataPointIdCounter = Math.max(this.dataPointIdCounter, lastDataPoint.id + 1);
214
- }
215
- }
216
- console.debug('[WebRecorder] Raw segment result:', {
217
- dataPointsLength: segmentResult.dataPoints.length,
218
- durationMs: segmentResult.durationMs,
219
- sampleRate: segmentResult.sampleRate,
220
- amplitudeRange: segmentResult.amplitudeRange,
221
- });
222
- // Ensure consistent sample rate in the result
223
- segmentResult.sampleRate =
224
- this.config.sampleRate || this.audioContext.sampleRate;
225
- // Update the full audio analysis data with proper range merging
226
- this.audioAnalysisData.dataPoints.push(...segmentResult.dataPoints);
227
- this.audioAnalysisData.durationMs += segmentResult.durationMs;
228
- // Make sure the sample rate is consistent
229
- this.audioAnalysisData.sampleRate = segmentResult.sampleRate;
230
- // Properly merge amplitude ranges
231
- if (segmentResult.amplitudeRange) {
232
- if (!this.audioAnalysisData.amplitudeRange) {
233
- this.audioAnalysisData.amplitudeRange = {
234
- ...segmentResult.amplitudeRange,
235
- };
236
- }
237
- else {
238
- this.audioAnalysisData.amplitudeRange = {
239
- min: Math.min(this.audioAnalysisData.amplitudeRange.min, segmentResult.amplitudeRange.min),
240
- max: Math.max(this.audioAnalysisData.amplitudeRange.max, segmentResult.amplitudeRange.max),
241
- };
242
- }
243
- }
244
- // Properly merge RMS ranges
245
- if (segmentResult.rmsRange) {
246
- if (!this.audioAnalysisData.rmsRange) {
247
- this.audioAnalysisData.rmsRange = {
248
- ...segmentResult.rmsRange,
249
- };
250
- }
251
- else {
252
- this.audioAnalysisData.rmsRange = {
253
- min: Math.min(this.audioAnalysisData.rmsRange.min, segmentResult.rmsRange.min),
254
- max: Math.max(this.audioAnalysisData.rmsRange.max, segmentResult.rmsRange.max),
255
- };
256
- }
257
- }
258
- this.logger?.debug('features event segmentResult', segmentResult);
259
- this.logger?.debug(`features event audioAnalysisData duration=${this.audioAnalysisData.durationMs}`, this.audioAnalysisData);
260
- this.emitAudioAnalysisCallback(segmentResult);
261
- console.debug('[WebRecorder] Updated audioAnalysisData:', {
262
- dataPointsLength: this.audioAnalysisData.dataPoints.length,
263
- durationMs: this.audioAnalysisData.durationMs,
264
- sampleRate: this.audioAnalysisData.sampleRate,
265
- amplitudeRange: this.audioAnalysisData.amplitudeRange,
266
- });
267
- }
268
- }
269
- /**
270
- * Resets the data point ID counter
271
- * Used when starting a new recording
272
- */
273
- resetDataPointCounter() {
274
- this.dataPointIdCounter = 0;
275
- // Reset the counter in the worker
276
- if (this.featureExtractorWorker) {
277
- this.featureExtractorWorker.postMessage({
278
- command: 'resetCounter',
279
- startCounterFrom: 0,
280
- });
281
- }
282
- }
283
- /**
284
- * Starts the audio recording process
285
- * Connects the audio nodes and begins capturing audio data
286
- */
287
- start() {
288
- this.source.connect(this.audioWorkletNode);
289
- this.audioWorkletNode.connect(this.audioContext.destination);
290
- this.packetCount = 0;
291
- // Reset the counter when starting a new recording
292
- this.resetDataPointCounter();
293
- if (this.compressedMediaRecorder) {
294
- this.compressedMediaRecorder.start(this.config.interval ?? 1000);
295
- }
296
- }
297
- /**
298
- * Stops the audio recording process and returns the recorded data
299
- * @returns Promise resolving to an object containing PCM data and optional compressed blob
300
- */
301
- async stop() {
302
- try {
303
- if (this.compressedMediaRecorder) {
304
- this.compressedMediaRecorder.stop();
305
- return {
306
- pcmData: new Float32Array(), // Return empty array since we're streaming
307
- compressedBlob: new Blob(this.compressedChunks, {
308
- type: 'audio/webm;codecs=opus',
309
- }),
310
- };
311
- }
312
- return { pcmData: new Float32Array() };
313
- }
314
- finally {
315
- this.cleanup();
316
- // Reset the chunks array
317
- this.compressedChunks = [];
318
- this.compressedSize = 0;
319
- this.pendingCompressedChunk = null;
320
- }
321
- }
322
- /**
323
- * Cleans up resources when recording is stopped
324
- * Closes audio context and disconnects nodes
325
- */
326
- cleanup() {
327
- if (this.audioContext) {
328
- this.audioContext.close();
329
- }
330
- if (this.audioWorkletNode) {
331
- this.audioWorkletNode.disconnect();
332
- }
333
- if (this.source) {
334
- this.source.disconnect();
335
- }
336
- this.stopMediaStreamTracks();
337
- }
338
- /**
339
- * Pauses the audio recording process
340
- * Disconnects audio nodes and pauses the media recorder
341
- */
342
- pause() {
343
- this.source.disconnect(this.audioWorkletNode); // Disconnect the source from the AudioWorkletNode
344
- this.audioWorkletNode.disconnect(this.audioContext.destination); // Disconnect the AudioWorkletNode from the destination
345
- this.audioWorkletNode.port.postMessage({ command: 'pause' });
346
- this.compressedMediaRecorder?.pause();
347
- }
348
- /**
349
- * Stops all media stream tracks to release hardware resources
350
- * Ensures recording indicators (like microphone icon) are turned off
351
- */
352
- stopMediaStreamTracks() {
353
- // Stop all audio tracks to stop the recording icon
354
- const tracks = this.source.mediaStream.getTracks();
355
- tracks.forEach((track) => track.stop());
356
- }
357
- /**
358
- * Determines the audio format capabilities of the current audio context
359
- * @param sampleRate - The sample rate to check
360
- * @returns Object containing format information (sample rate, bit depth, channels)
361
- */
362
- checkAudioContextFormat({ sampleRate }) {
363
- // Create a silent AudioBuffer
364
- const frameCount = sampleRate * 1.0; // 1 second buffer
365
- const audioBuffer = this.audioContext.createBuffer(1, frameCount, sampleRate);
366
- // Check the format
367
- const channelData = audioBuffer.getChannelData(0);
368
- const bitDepth = channelData.BYTES_PER_ELEMENT * 8; // 4 bytes per element means 32-bit
369
- return {
370
- sampleRate: audioBuffer.sampleRate,
371
- bitDepth,
372
- numberOfChannels: audioBuffer.numberOfChannels,
373
- };
374
- }
375
- /**
376
- * Resumes a paused recording
377
- * Reconnects audio nodes and resumes the media recorder
378
- */
379
- resume() {
380
- this.source.connect(this.audioWorkletNode);
381
- this.audioWorkletNode.connect(this.audioContext.destination);
382
- this.audioWorkletNode.port.postMessage({ command: 'resume' });
383
- this.compressedMediaRecorder?.resume();
384
- }
385
- /**
386
- * Initializes the compressed media recorder if compression is enabled
387
- * Sets up event handlers for compressed audio data
388
- */
389
- initializeCompressedRecorder() {
390
- try {
391
- const mimeType = 'audio/webm;codecs=opus';
392
- if (!MediaRecorder.isTypeSupported(mimeType)) {
393
- this.logger?.warn('Opus compression not supported in this browser');
394
- return;
395
- }
396
- this.compressedMediaRecorder = new MediaRecorder(this.source.mediaStream, {
397
- mimeType,
398
- audioBitsPerSecond: this.config.compression?.bitrate ?? 128000,
399
- });
400
- this.compressedMediaRecorder.ondataavailable = (event) => {
401
- if (event.data.size > 0) {
402
- this.compressedChunks.push(event.data);
403
- this.compressedSize += event.data.size;
404
- this.pendingCompressedChunk = event.data;
405
- }
406
- };
407
- }
408
- catch (error) {
409
- this.logger?.error('Failed to initialize compressed recorder:', error);
410
- }
411
- }
412
- /**
413
- * Processes features if enabled
414
- */
415
- processFeatures(chunk, sampleRate, chunkPosition, startPosition, endPosition, samples) {
416
- if (this.config.enableProcessing && this.featureExtractorWorker) {
417
- this.featureExtractorWorker.postMessage({
418
- command: 'process',
419
- channelData: chunk,
420
- sampleRate,
421
- segmentDurationMs: this.config.segmentDurationMs ??
422
- DEFAULT_SEGMENT_DURATION_MS, // Default to 100ms
423
- bitDepth: this.bitDepth,
424
- fullAudioDurationMs: chunkPosition * 1000,
425
- numberOfChannels: this.numberOfChannels,
426
- features: this.config.features,
427
- intervalAnalysis: this.config.intervalAnalysis,
428
- startPosition,
429
- endPosition,
430
- samples,
431
- startCounterFrom: this.dataPointIdCounter, // Pass the current counter value
432
- });
433
- }
434
- }
435
- }
436
- //# sourceMappingURL=WebRecorder.web.js.map