@siteed/expo-audio-stream 2.1.0 → 2.2.1-beta.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 (189) hide show
  1. package/README.md +23 -260
  2. package/build/index.d.ts +11 -15
  3. package/build/index.js +54 -14
  4. package/build/src/index.d.ts +11 -0
  5. package/build/src/index.js +54 -0
  6. package/package.json +49 -110
  7. package/src/index.ts +18 -32
  8. package/CHANGELOG.md +0 -206
  9. package/android/build.gradle +0 -105
  10. package/android/src/main/AndroidManifest.xml +0 -27
  11. package/android/src/main/java/net/siteed/audiostream/AudioAnalysisData.kt +0 -166
  12. package/android/src/main/java/net/siteed/audiostream/AudioDataEncoder.kt +0 -9
  13. package/android/src/main/java/net/siteed/audiostream/AudioFileHandler.kt +0 -131
  14. package/android/src/main/java/net/siteed/audiostream/AudioFormatUtils.kt +0 -103
  15. package/android/src/main/java/net/siteed/audiostream/AudioNotificationsManager.kt +0 -435
  16. package/android/src/main/java/net/siteed/audiostream/AudioProcessor.kt +0 -2235
  17. package/android/src/main/java/net/siteed/audiostream/AudioRecorderManager.kt +0 -1437
  18. package/android/src/main/java/net/siteed/audiostream/AudioRecordingService.kt +0 -152
  19. package/android/src/main/java/net/siteed/audiostream/AudioTrimmer.kt +0 -1099
  20. package/android/src/main/java/net/siteed/audiostream/Constants.kt +0 -21
  21. package/android/src/main/java/net/siteed/audiostream/EventSender.kt +0 -7
  22. package/android/src/main/java/net/siteed/audiostream/ExpoAudioStreamModule.kt +0 -739
  23. package/android/src/main/java/net/siteed/audiostream/FFT.kt +0 -99
  24. package/android/src/main/java/net/siteed/audiostream/Features.kt +0 -98
  25. package/android/src/main/java/net/siteed/audiostream/NotificationConfig.kt +0 -70
  26. package/android/src/main/java/net/siteed/audiostream/PermissionUtils.kt +0 -59
  27. package/android/src/main/java/net/siteed/audiostream/RecordingActionReceiver.kt +0 -59
  28. package/android/src/main/java/net/siteed/audiostream/RecordingConfig.kt +0 -205
  29. package/android/src/main/java/net/siteed/audiostream/WaveformConfig.kt +0 -19
  30. package/android/src/main/java/net/siteed/audiostream/WaveformRenderer.kt +0 -159
  31. package/android/src/main/res/drawable/ic_default_action_icon.xml +0 -16
  32. package/android/src/main/res/drawable/ic_microphone.xml +0 -13
  33. package/android/src/main/res/drawable/ic_pause.xml +0 -10
  34. package/android/src/main/res/drawable/ic_play.xml +0 -10
  35. package/android/src/main/res/drawable/ic_stop.xml +0 -10
  36. package/android/src/main/res/layout/notification_recording.xml +0 -37
  37. package/android/src/main/test/java/net/siteed/audiostream/AudioProcessorTest.kt +0 -56
  38. package/app.plugin.js +0 -1
  39. package/build/AudioAnalysis/AudioAnalysis.types.d.ts +0 -179
  40. package/build/AudioAnalysis/AudioAnalysis.types.d.ts.map +0 -1
  41. package/build/AudioAnalysis/AudioAnalysis.types.js +0 -3
  42. package/build/AudioAnalysis/AudioAnalysis.types.js.map +0 -1
  43. package/build/AudioAnalysis/extractAudioAnalysis.d.ts +0 -68
  44. package/build/AudioAnalysis/extractAudioAnalysis.d.ts.map +0 -1
  45. package/build/AudioAnalysis/extractAudioAnalysis.js +0 -203
  46. package/build/AudioAnalysis/extractAudioAnalysis.js.map +0 -1
  47. package/build/AudioAnalysis/extractAudioData.d.ts +0 -3
  48. package/build/AudioAnalysis/extractAudioData.d.ts.map +0 -1
  49. package/build/AudioAnalysis/extractAudioData.js +0 -5
  50. package/build/AudioAnalysis/extractAudioData.js.map +0 -1
  51. package/build/AudioAnalysis/extractMelSpectrogram.d.ts +0 -14
  52. package/build/AudioAnalysis/extractMelSpectrogram.d.ts.map +0 -1
  53. package/build/AudioAnalysis/extractMelSpectrogram.js +0 -85
  54. package/build/AudioAnalysis/extractMelSpectrogram.js.map +0 -1
  55. package/build/AudioAnalysis/extractPreview.d.ts +0 -11
  56. package/build/AudioAnalysis/extractPreview.d.ts.map +0 -1
  57. package/build/AudioAnalysis/extractPreview.js +0 -25
  58. package/build/AudioAnalysis/extractPreview.js.map +0 -1
  59. package/build/AudioAnalysis/extractWaveform.d.ts +0 -8
  60. package/build/AudioAnalysis/extractWaveform.d.ts.map +0 -1
  61. package/build/AudioAnalysis/extractWaveform.js +0 -11
  62. package/build/AudioAnalysis/extractWaveform.js.map +0 -1
  63. package/build/AudioRecorder.provider.d.ts +0 -11
  64. package/build/AudioRecorder.provider.d.ts.map +0 -1
  65. package/build/AudioRecorder.provider.js +0 -37
  66. package/build/AudioRecorder.provider.js.map +0 -1
  67. package/build/ExpoAudioStream.native.d.ts +0 -3
  68. package/build/ExpoAudioStream.native.d.ts.map +0 -1
  69. package/build/ExpoAudioStream.native.js +0 -6
  70. package/build/ExpoAudioStream.native.js.map +0 -1
  71. package/build/ExpoAudioStream.types.d.ts +0 -532
  72. package/build/ExpoAudioStream.types.d.ts.map +0 -1
  73. package/build/ExpoAudioStream.types.js +0 -2
  74. package/build/ExpoAudioStream.types.js.map +0 -1
  75. package/build/ExpoAudioStream.web.d.ts +0 -59
  76. package/build/ExpoAudioStream.web.d.ts.map +0 -1
  77. package/build/ExpoAudioStream.web.js +0 -285
  78. package/build/ExpoAudioStream.web.js.map +0 -1
  79. package/build/ExpoAudioStreamModule.d.ts +0 -3
  80. package/build/ExpoAudioStreamModule.d.ts.map +0 -1
  81. package/build/ExpoAudioStreamModule.js +0 -693
  82. package/build/ExpoAudioStreamModule.js.map +0 -1
  83. package/build/WebRecorder.web.d.ts +0 -119
  84. package/build/WebRecorder.web.d.ts.map +0 -1
  85. package/build/WebRecorder.web.js +0 -436
  86. package/build/WebRecorder.web.js.map +0 -1
  87. package/build/constants.d.ts +0 -11
  88. package/build/constants.d.ts.map +0 -1
  89. package/build/constants.js +0 -14
  90. package/build/constants.js.map +0 -1
  91. package/build/events.d.ts +0 -26
  92. package/build/events.d.ts.map +0 -1
  93. package/build/events.js +0 -21
  94. package/build/events.js.map +0 -1
  95. package/build/index.d.ts.map +0 -1
  96. package/build/index.js.map +0 -1
  97. package/build/trimAudio.d.ts +0 -25
  98. package/build/trimAudio.d.ts.map +0 -1
  99. package/build/trimAudio.js +0 -67
  100. package/build/trimAudio.js.map +0 -1
  101. package/build/useAudioRecorder.d.ts +0 -21
  102. package/build/useAudioRecorder.d.ts.map +0 -1
  103. package/build/useAudioRecorder.js +0 -427
  104. package/build/useAudioRecorder.js.map +0 -1
  105. package/build/utils/BlobFix.d.ts +0 -9
  106. package/build/utils/BlobFix.d.ts.map +0 -1
  107. package/build/utils/BlobFix.js +0 -498
  108. package/build/utils/BlobFix.js.map +0 -1
  109. package/build/utils/audioProcessing.d.ts +0 -24
  110. package/build/utils/audioProcessing.d.ts.map +0 -1
  111. package/build/utils/audioProcessing.js +0 -133
  112. package/build/utils/audioProcessing.js.map +0 -1
  113. package/build/utils/concatenateBuffers.d.ts +0 -8
  114. package/build/utils/concatenateBuffers.d.ts.map +0 -1
  115. package/build/utils/concatenateBuffers.js +0 -21
  116. package/build/utils/concatenateBuffers.js.map +0 -1
  117. package/build/utils/convertPCMToFloat32.d.ts +0 -13
  118. package/build/utils/convertPCMToFloat32.d.ts.map +0 -1
  119. package/build/utils/convertPCMToFloat32.js +0 -120
  120. package/build/utils/convertPCMToFloat32.js.map +0 -1
  121. package/build/utils/encodingToBitDepth.d.ts +0 -5
  122. package/build/utils/encodingToBitDepth.d.ts.map +0 -1
  123. package/build/utils/encodingToBitDepth.js +0 -13
  124. package/build/utils/encodingToBitDepth.js.map +0 -1
  125. package/build/utils/getWavFileInfo.d.ts +0 -26
  126. package/build/utils/getWavFileInfo.d.ts.map +0 -1
  127. package/build/utils/getWavFileInfo.js +0 -92
  128. package/build/utils/getWavFileInfo.js.map +0 -1
  129. package/build/utils/writeWavHeader.d.ts +0 -49
  130. package/build/utils/writeWavHeader.d.ts.map +0 -1
  131. package/build/utils/writeWavHeader.js +0 -91
  132. package/build/utils/writeWavHeader.js.map +0 -1
  133. package/build/workers/InlineFeaturesExtractor.web.d.ts +0 -2
  134. package/build/workers/InlineFeaturesExtractor.web.d.ts.map +0 -1
  135. package/build/workers/InlineFeaturesExtractor.web.js +0 -828
  136. package/build/workers/InlineFeaturesExtractor.web.js.map +0 -1
  137. package/build/workers/inlineAudioWebWorker.web.d.ts +0 -2
  138. package/build/workers/inlineAudioWebWorker.web.d.ts.map +0 -1
  139. package/build/workers/inlineAudioWebWorker.web.js +0 -157
  140. package/build/workers/inlineAudioWebWorker.web.js.map +0 -1
  141. package/expo-module.config.json +0 -9
  142. package/ios/AudioAnalysisData.swift +0 -74
  143. package/ios/AudioNotificationManager.swift +0 -135
  144. package/ios/AudioProcessingHelpers.swift +0 -743
  145. package/ios/AudioProcessor.swift +0 -1313
  146. package/ios/AudioStreamError.swift +0 -7
  147. package/ios/AudioStreamManager.swift +0 -1708
  148. package/ios/AudioStreamManagerDelegate.swift +0 -16
  149. package/ios/DataPoint.swift +0 -54
  150. package/ios/DecodingConfig.swift +0 -47
  151. package/ios/ExpoAudioStream.podspec +0 -27
  152. package/ios/ExpoAudioStreamModule.swift +0 -805
  153. package/ios/FFT.swift +0 -62
  154. package/ios/Features.swift +0 -95
  155. package/ios/Logger.swift +0 -7
  156. package/ios/NotificationExtension.swift +0 -15
  157. package/ios/RecordingResult.swift +0 -22
  158. package/ios/RecordingSettings.swift +0 -265
  159. package/ios/WaveformExtractor.swift +0 -105
  160. package/plugin/build/index.d.ts +0 -21
  161. package/plugin/build/index.js +0 -191
  162. package/plugin/src/index.ts +0 -278
  163. package/plugin/tsconfig.json +0 -10
  164. package/plugin/tsconfig.tsbuildinfo +0 -1
  165. package/src/AudioAnalysis/AudioAnalysis.types.ts +0 -202
  166. package/src/AudioAnalysis/extractAudioAnalysis.ts +0 -333
  167. package/src/AudioAnalysis/extractAudioData.ts +0 -6
  168. package/src/AudioAnalysis/extractMelSpectrogram.ts +0 -144
  169. package/src/AudioAnalysis/extractPreview.ts +0 -34
  170. package/src/AudioAnalysis/extractWaveform.ts +0 -22
  171. package/src/AudioRecorder.provider.tsx +0 -54
  172. package/src/ExpoAudioStream.native.ts +0 -6
  173. package/src/ExpoAudioStream.types.ts +0 -641
  174. package/src/ExpoAudioStream.web.ts +0 -359
  175. package/src/ExpoAudioStreamModule.ts +0 -967
  176. package/src/WebRecorder.web.ts +0 -580
  177. package/src/constants.ts +0 -18
  178. package/src/events.ts +0 -60
  179. package/src/trimAudio.ts +0 -90
  180. package/src/useAudioRecorder.tsx +0 -620
  181. package/src/utils/BlobFix.ts +0 -559
  182. package/src/utils/audioProcessing.ts +0 -205
  183. package/src/utils/concatenateBuffers.ts +0 -24
  184. package/src/utils/convertPCMToFloat32.ts +0 -170
  185. package/src/utils/encodingToBitDepth.ts +0 -18
  186. package/src/utils/getWavFileInfo.ts +0 -132
  187. package/src/utils/writeWavHeader.ts +0 -114
  188. package/src/workers/InlineFeaturesExtractor.web.tsx +0 -827
  189. package/src/workers/inlineAudioWebWorker.web.tsx +0 -156
@@ -1,191 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const config_plugins_1 = require("@expo/config-plugins");
4
- const MICROPHONE_USAGE = 'Allow $(PRODUCT_NAME) to access your microphone';
5
- const NOTIFICATION_USAGE = 'Show recording notifications and controls';
6
- const LOG_PREFIX = '[@siteed/expo-audio-stream]';
7
- function debugLog(message, ...args) {
8
- if (process.env.EXPO_DEBUG) {
9
- console.log(`${LOG_PREFIX} ${message}`, ...args);
10
- }
11
- }
12
- const withRecordingPermission = (config, props) => {
13
- const options = {
14
- enablePhoneStateHandling: true, // Default to true for backward compatibility
15
- enableNotifications: true,
16
- enableBackgroundAudio: true,
17
- iosBackgroundModes: {
18
- useVoIP: false,
19
- useAudio: false,
20
- useProcessing: false,
21
- useLocation: false,
22
- useExternalAccessory: false,
23
- },
24
- iosConfig: {
25
- microphoneUsageDescription: MICROPHONE_USAGE,
26
- notificationUsageDescription: NOTIFICATION_USAGE,
27
- },
28
- ...(props || {}),
29
- };
30
- const { enablePhoneStateHandling, enableNotifications, enableBackgroundAudio, } = options;
31
- debugLog('📱 Configuring Recording Permissions Plugin...', options);
32
- // iOS Configuration
33
- config = (0, config_plugins_1.withInfoPlist)(config, (config) => {
34
- // Always set the microphone usage description from options first
35
- config.modResults['NSMicrophoneUsageDescription'] =
36
- options.iosConfig?.microphoneUsageDescription ||
37
- config.modResults['NSMicrophoneUsageDescription'] ||
38
- MICROPHONE_USAGE;
39
- if (enableNotifications) {
40
- config.modResults['NSUserNotificationsUsageDescription'] =
41
- options.iosConfig?.notificationUsageDescription ||
42
- config.modResults['NSUserNotificationsUsageDescription'] ||
43
- NOTIFICATION_USAGE;
44
- config.modResults['NSUserNotificationAlertStyle'] = 'alert';
45
- }
46
- const existingBackgroundModes = config.modResults.UIBackgroundModes || [];
47
- // Only add background modes if explicitly enabled and set to true
48
- if (options.iosBackgroundModes?.useAudio === true &&
49
- enableBackgroundAudio === true &&
50
- !existingBackgroundModes.includes('audio')) {
51
- // Don't automatically add 'audio' background mode as it's only for playback
52
- // existingBackgroundModes.push('audio')
53
- // Instead, ensure processing mode is used for background recording
54
- if (options.iosBackgroundModes?.useProcessing !== true) {
55
- console.warn(`${LOG_PREFIX} Warning: Background audio recording requires 'processing' background mode. Please enable 'useProcessing' in iosBackgroundModes.`);
56
- }
57
- }
58
- if (options.iosBackgroundModes?.useVoIP === true &&
59
- enablePhoneStateHandling === true) {
60
- if (!existingBackgroundModes.includes('voip')) {
61
- existingBackgroundModes.push('voip');
62
- }
63
- const existingCapabilities = (config.modResults
64
- .UIRequiredDeviceCapabilities || []);
65
- if (!existingCapabilities.includes('telephony')) {
66
- existingCapabilities.push('telephony');
67
- }
68
- config.modResults.UIRequiredDeviceCapabilities =
69
- existingCapabilities;
70
- }
71
- // Add additional background modes only if explicitly set to true
72
- if (options.iosBackgroundModes?.useProcessing === true) {
73
- if (!existingBackgroundModes.includes('processing')) {
74
- existingBackgroundModes.push('processing');
75
- }
76
- // Add processing info if enabled
77
- config.modResults.BGTaskSchedulerPermittedIdentifiers = [
78
- 'com.siteed.audiostream.processing',
79
- ];
80
- }
81
- if (options.iosBackgroundModes?.useLocation === true) {
82
- if (!existingBackgroundModes.includes('location')) {
83
- existingBackgroundModes.push('location');
84
- }
85
- }
86
- if (options.iosBackgroundModes?.useExternalAccessory === true) {
87
- if (!existingBackgroundModes.includes('external-accessory')) {
88
- existingBackgroundModes.push('external-accessory');
89
- }
90
- }
91
- // Configure background processing info if enabled
92
- if (options.iosConfig?.backgroundProcessingTitle) {
93
- config.modResults.BGProcessingTaskTitle =
94
- options.iosConfig.backgroundProcessingTitle;
95
- }
96
- // Configure audio session behavior
97
- if (options.iosConfig?.allowBackgroundAudioControls) {
98
- config.modResults.UIBackgroundModes = [
99
- ...existingBackgroundModes,
100
- 'remote-notification',
101
- ];
102
- config.modResults.MPNowPlayingInfoPropertyPlaybackRate = true;
103
- }
104
- config.modResults.UIBackgroundModes = existingBackgroundModes;
105
- return config;
106
- });
107
- // Android Configuration
108
- config = (0, config_plugins_1.withAndroidManifest)(config, (config) => {
109
- const basePermissions = [
110
- 'android.permission.RECORD_AUDIO',
111
- 'android.permission.WAKE_LOCK',
112
- ];
113
- const optionalPermissions = [
114
- enableNotifications && 'android.permission.POST_NOTIFICATIONS',
115
- enablePhoneStateHandling && 'android.permission.READ_PHONE_STATE',
116
- enableBackgroundAudio && 'android.permission.FOREGROUND_SERVICE',
117
- enableBackgroundAudio &&
118
- 'android.permission.FOREGROUND_SERVICE_MICROPHONE',
119
- ].filter(Boolean);
120
- const permissionsToAdd = [...basePermissions, ...optionalPermissions];
121
- debugLog('📋 Existing Android permissions:', config.modResults.manifest['uses-permission']?.map((p) => p.$?.['android:name']) || []);
122
- debugLog('➕ Adding Android permissions:', permissionsToAdd);
123
- const { addPermission } = config_plugins_1.AndroidConfig.Permissions;
124
- // Add each permission only if it doesn't exist
125
- permissionsToAdd.forEach((permission) => {
126
- const existingPermission = config.modResults.manifest['uses-permission']?.find((p) => p.$?.['android:name'] === permission);
127
- if (!existingPermission) {
128
- addPermission(config.modResults, permission);
129
- }
130
- });
131
- // Get the main application node
132
- const mainApplication = config.modResults.manifest.application?.[0];
133
- if (mainApplication) {
134
- debugLog('📱 Configuring Android application components...');
135
- // Add RecordingActionReceiver
136
- if (!mainApplication.receiver) {
137
- mainApplication.receiver = [];
138
- }
139
- const receiverConfig = {
140
- $: {
141
- 'android:name': '.RecordingActionReceiver',
142
- 'android:exported': 'false',
143
- },
144
- 'intent-filter': [
145
- {
146
- action: [
147
- { $: { 'android:name': 'PAUSE_RECORDING' } },
148
- { $: { 'android:name': 'RESUME_RECORDING' } },
149
- { $: { 'android:name': 'STOP_RECORDING' } },
150
- ],
151
- },
152
- ],
153
- };
154
- const receiverIndex = mainApplication.receiver.findIndex((receiver) => receiver.$?.['android:name'] === '.RecordingActionReceiver');
155
- if (receiverIndex >= 0) {
156
- mainApplication.receiver[receiverIndex] = receiverConfig;
157
- }
158
- else {
159
- mainApplication.receiver.push(receiverConfig);
160
- }
161
- debugLog('✅ RecordingActionReceiver configured');
162
- // Add AudioRecordingService
163
- if (!mainApplication.service) {
164
- mainApplication.service = [];
165
- }
166
- const serviceConfig = {
167
- $: {
168
- 'android:name': '.AudioRecordingService',
169
- 'android:enabled': 'true',
170
- 'android:exported': 'false',
171
- 'android:foregroundServiceType': 'microphone',
172
- },
173
- };
174
- const serviceIndex = mainApplication.service.findIndex((service) => service.$?.['android:name'] === '.AudioRecordingService');
175
- if (serviceIndex >= 0) {
176
- mainApplication.service[serviceIndex] = serviceConfig;
177
- }
178
- else {
179
- mainApplication.service.push(serviceConfig);
180
- }
181
- debugLog('✅ AudioRecordingService configured');
182
- }
183
- else {
184
- console.error(`${LOG_PREFIX} ❌ Main application node not found in Android Manifest`);
185
- }
186
- return config;
187
- });
188
- debugLog('✨ Recording Permissions Plugin configuration completed');
189
- return config;
190
- };
191
- exports.default = withRecordingPermission;
@@ -1,278 +0,0 @@
1
- import {
2
- ConfigPlugin,
3
- withAndroidManifest,
4
- withInfoPlist,
5
- AndroidConfig,
6
- } from '@expo/config-plugins'
7
- import { ExpoConfig } from '@expo/config-types'
8
-
9
- const MICROPHONE_USAGE = 'Allow $(PRODUCT_NAME) to access your microphone'
10
- const NOTIFICATION_USAGE = 'Show recording notifications and controls'
11
- const LOG_PREFIX = '[@siteed/expo-audio-stream]'
12
-
13
- function debugLog(message: string, ...args: unknown[]): void {
14
- if (process.env.EXPO_DEBUG) {
15
- console.log(`${LOG_PREFIX} ${message}`, ...args)
16
- }
17
- }
18
-
19
- interface AudioStreamPluginOptions {
20
- enablePhoneStateHandling?: boolean // Controls READ_PHONE_STATE permission
21
- enableNotifications?: boolean
22
- enableBackgroundAudio?: boolean
23
- iosBackgroundModes?: {
24
- useVoIP?: boolean
25
- useAudio?: boolean
26
- useProcessing?: boolean
27
- useLocation?: boolean
28
- useExternalAccessory?: boolean
29
- }
30
- iosConfig?: {
31
- allowBackgroundAudioControls?: boolean
32
- backgroundProcessingTitle?: string
33
- microphoneUsageDescription?: string
34
- notificationUsageDescription?: string
35
- }
36
- }
37
-
38
- const withRecordingPermission: ConfigPlugin<AudioStreamPluginOptions> = (
39
- config: ExpoConfig,
40
- props: AudioStreamPluginOptions | void
41
- ) => {
42
- const options: AudioStreamPluginOptions = {
43
- enablePhoneStateHandling: true, // Default to true for backward compatibility
44
- enableNotifications: true,
45
- enableBackgroundAudio: true,
46
- iosBackgroundModes: {
47
- useVoIP: false,
48
- useAudio: false,
49
- useProcessing: false,
50
- useLocation: false,
51
- useExternalAccessory: false,
52
- },
53
- iosConfig: {
54
- microphoneUsageDescription: MICROPHONE_USAGE,
55
- notificationUsageDescription: NOTIFICATION_USAGE,
56
- },
57
- ...(props || {}),
58
- }
59
-
60
- const {
61
- enablePhoneStateHandling,
62
- enableNotifications,
63
- enableBackgroundAudio,
64
- } = options
65
-
66
- debugLog('📱 Configuring Recording Permissions Plugin...', options)
67
-
68
- // iOS Configuration
69
- config = withInfoPlist(config as any, (config) => {
70
- // Always set the microphone usage description from options first
71
- config.modResults['NSMicrophoneUsageDescription'] =
72
- options.iosConfig?.microphoneUsageDescription ||
73
- config.modResults['NSMicrophoneUsageDescription'] ||
74
- MICROPHONE_USAGE
75
-
76
- if (enableNotifications) {
77
- config.modResults['NSUserNotificationsUsageDescription'] =
78
- options.iosConfig?.notificationUsageDescription ||
79
- config.modResults['NSUserNotificationsUsageDescription'] ||
80
- NOTIFICATION_USAGE
81
- config.modResults['NSUserNotificationAlertStyle'] = 'alert'
82
- }
83
-
84
- const existingBackgroundModes =
85
- config.modResults.UIBackgroundModes || []
86
-
87
- // Only add background modes if explicitly enabled and set to true
88
- if (
89
- options.iosBackgroundModes?.useAudio === true &&
90
- enableBackgroundAudio === true &&
91
- !existingBackgroundModes.includes('audio')
92
- ) {
93
- // Don't automatically add 'audio' background mode as it's only for playback
94
- // existingBackgroundModes.push('audio')
95
-
96
- // Instead, ensure processing mode is used for background recording
97
- if (options.iosBackgroundModes?.useProcessing !== true) {
98
- console.warn(
99
- `${LOG_PREFIX} Warning: Background audio recording requires 'processing' background mode. Please enable 'useProcessing' in iosBackgroundModes.`
100
- )
101
- }
102
- }
103
-
104
- if (
105
- options.iosBackgroundModes?.useVoIP === true &&
106
- enablePhoneStateHandling === true
107
- ) {
108
- if (!existingBackgroundModes.includes('voip')) {
109
- existingBackgroundModes.push('voip')
110
- }
111
- const existingCapabilities = (config.modResults
112
- .UIRequiredDeviceCapabilities || []) as string[]
113
- if (!existingCapabilities.includes('telephony')) {
114
- existingCapabilities.push('telephony')
115
- }
116
- config.modResults.UIRequiredDeviceCapabilities =
117
- existingCapabilities
118
- }
119
-
120
- // Add additional background modes only if explicitly set to true
121
- if (options.iosBackgroundModes?.useProcessing === true) {
122
- if (!existingBackgroundModes.includes('processing')) {
123
- existingBackgroundModes.push('processing')
124
- }
125
- // Add processing info if enabled
126
- config.modResults.BGTaskSchedulerPermittedIdentifiers = [
127
- 'com.siteed.audiostream.processing',
128
- ]
129
- }
130
-
131
- if (options.iosBackgroundModes?.useLocation === true) {
132
- if (!existingBackgroundModes.includes('location')) {
133
- existingBackgroundModes.push('location')
134
- }
135
- }
136
-
137
- if (options.iosBackgroundModes?.useExternalAccessory === true) {
138
- if (!existingBackgroundModes.includes('external-accessory')) {
139
- existingBackgroundModes.push('external-accessory')
140
- }
141
- }
142
-
143
- // Configure background processing info if enabled
144
- if (options.iosConfig?.backgroundProcessingTitle) {
145
- config.modResults.BGProcessingTaskTitle =
146
- options.iosConfig.backgroundProcessingTitle
147
- }
148
-
149
- // Configure audio session behavior
150
- if (options.iosConfig?.allowBackgroundAudioControls) {
151
- config.modResults.UIBackgroundModes = [
152
- ...existingBackgroundModes,
153
- 'remote-notification',
154
- ]
155
- config.modResults.MPNowPlayingInfoPropertyPlaybackRate = true
156
- }
157
-
158
- config.modResults.UIBackgroundModes = existingBackgroundModes
159
- return config
160
- })
161
-
162
- // Android Configuration
163
- config = withAndroidManifest(config as any, (config) => {
164
- const basePermissions = [
165
- 'android.permission.RECORD_AUDIO',
166
- 'android.permission.WAKE_LOCK',
167
- ]
168
-
169
- const optionalPermissions = [
170
- enableNotifications && 'android.permission.POST_NOTIFICATIONS',
171
- enablePhoneStateHandling && 'android.permission.READ_PHONE_STATE',
172
- enableBackgroundAudio && 'android.permission.FOREGROUND_SERVICE',
173
- enableBackgroundAudio &&
174
- 'android.permission.FOREGROUND_SERVICE_MICROPHONE',
175
- ].filter(Boolean) as string[]
176
-
177
- const permissionsToAdd = [...basePermissions, ...optionalPermissions]
178
-
179
- debugLog(
180
- '📋 Existing Android permissions:',
181
- config.modResults.manifest['uses-permission']?.map(
182
- (p) => p.$?.['android:name']
183
- ) || []
184
- )
185
-
186
- debugLog('➕ Adding Android permissions:', permissionsToAdd)
187
-
188
- const { addPermission } = AndroidConfig.Permissions
189
-
190
- // Add each permission only if it doesn't exist
191
- permissionsToAdd.forEach((permission) => {
192
- const existingPermission = config.modResults.manifest[
193
- 'uses-permission'
194
- ]?.find((p) => p.$?.['android:name'] === permission)
195
- if (!existingPermission) {
196
- addPermission(config.modResults, permission)
197
- }
198
- })
199
-
200
- // Get the main application node
201
- const mainApplication = config.modResults.manifest.application?.[0]
202
- if (mainApplication) {
203
- debugLog('📱 Configuring Android application components...')
204
-
205
- // Add RecordingActionReceiver
206
- if (!mainApplication.receiver) {
207
- mainApplication.receiver = []
208
- }
209
-
210
- const receiverConfig = {
211
- $: {
212
- 'android:name': '.RecordingActionReceiver',
213
- 'android:exported': 'false' as const,
214
- },
215
- 'intent-filter': [
216
- {
217
- action: [
218
- { $: { 'android:name': 'PAUSE_RECORDING' } },
219
- { $: { 'android:name': 'RESUME_RECORDING' } },
220
- { $: { 'android:name': 'STOP_RECORDING' } },
221
- ],
222
- },
223
- ],
224
- }
225
-
226
- const receiverIndex = mainApplication.receiver.findIndex(
227
- (receiver: any) =>
228
- receiver.$?.['android:name'] === '.RecordingActionReceiver'
229
- )
230
-
231
- if (receiverIndex >= 0) {
232
- mainApplication.receiver[receiverIndex] = receiverConfig
233
- } else {
234
- mainApplication.receiver.push(receiverConfig)
235
- }
236
-
237
- debugLog('✅ RecordingActionReceiver configured')
238
-
239
- // Add AudioRecordingService
240
- if (!mainApplication.service) {
241
- mainApplication.service = []
242
- }
243
-
244
- const serviceConfig = {
245
- $: {
246
- 'android:name': '.AudioRecordingService',
247
- 'android:enabled': 'true' as const,
248
- 'android:exported': 'false' as const,
249
- 'android:foregroundServiceType': 'microphone',
250
- },
251
- }
252
-
253
- const serviceIndex = mainApplication.service.findIndex(
254
- (service: any) =>
255
- service.$?.['android:name'] === '.AudioRecordingService'
256
- )
257
-
258
- if (serviceIndex >= 0) {
259
- mainApplication.service[serviceIndex] = serviceConfig
260
- } else {
261
- mainApplication.service.push(serviceConfig)
262
- }
263
-
264
- debugLog('✅ AudioRecordingService configured')
265
- } else {
266
- console.error(
267
- `${LOG_PREFIX} ❌ Main application node not found in Android Manifest`
268
- )
269
- }
270
-
271
- return config
272
- })
273
-
274
- debugLog('✨ Recording Permissions Plugin configuration completed')
275
- return config as any
276
- }
277
-
278
- export default withRecordingPermission
@@ -1,10 +0,0 @@
1
- {
2
- "extends": "expo-module-scripts/tsconfig.plugin",
3
- "compilerOptions": {
4
- "outDir": "build",
5
- "lib": ["es2023", "dom"],
6
- "rootDir": "src"
7
- },
8
- "include": ["./src"],
9
- "exclude": ["**/__mocks__/*", "**/__tests__/*"]
10
- }
@@ -1 +0,0 @@
1
- {"root":["./src/index.ts"],"version":"5.7.2"}
@@ -1,202 +0,0 @@
1
- // packages/expo-audio-stream/src/AudioAnalysis/AudioAnalysis.types.ts
2
-
3
- import { BitDepth, ConsoleLike } from '../ExpoAudioStream.types'
4
-
5
- /**
6
- * Represents the configuration for decoding audio data.
7
- */
8
- export interface DecodingConfig {
9
- /** Target sample rate for decoded audio (Android and Web) */
10
- targetSampleRate?: number
11
- /** Target number of channels (Android and Web) */
12
- targetChannels?: number
13
- /** Target bit depth (Android and Web) */
14
- targetBitDepth?: BitDepth
15
- /** Whether to normalize audio levels (Android and Web) */
16
- normalizeAudio?: boolean
17
- }
18
-
19
- /**
20
- * Represents speech-related features extracted from audio.
21
- */
22
- export interface SpeechFeatures {
23
- isActive: boolean // Whether speech is detected in this segment
24
- speakerId?: number // Optional speaker identification
25
- // Could add more speech-related features here like:
26
- // confidence: number
27
- // language?: string
28
- // sentiment?: number
29
- // etc.
30
- }
31
-
32
- /**
33
- * Represents various audio features extracted from an audio signal.
34
- */
35
- export interface AudioFeatures {
36
- energy?: number // The infinite integral of the squared signal, representing the overall energy of the audio.
37
- mfcc?: number[] // Mel-frequency cepstral coefficients, describing the short-term power spectrum of a sound.
38
- rms?: number // Root mean square value, indicating the amplitude of the audio signal.
39
- minAmplitude?: number // Minimum amplitude value in the audio signal.
40
- maxAmplitude?: number // Maximum amplitude value in the audio signal.
41
- zcr?: number // Zero-crossing rate, indicating the rate at which the signal changes sign.
42
- spectralCentroid?: number // The center of mass of the spectrum, indicating the brightness of the sound.
43
- spectralFlatness?: number // Measure of the flatness of the spectrum, indicating how noise-like the signal is.
44
- spectralRolloff?: number // The frequency below which a specified percentage (usually 85%) of the total spectral energy lies.
45
- spectralBandwidth?: number // The width of the spectrum, indicating the range of frequencies present.
46
- chromagram?: number[] // Chromagram, representing the 12 different pitch classes of the audio.
47
- tempo?: number // Estimated tempo of the audio signal, measured in beats per minute (BPM).
48
- hnr?: number // Harmonics-to-noise ratio, indicating the proportion of harmonics to noise in the audio signal.
49
- melSpectrogram?: number[] // Mel-scaled spectrogram representation of the audio.
50
- spectralContrast?: number[] // Spectral contrast features representing the difference between peaks and valleys.
51
- tonnetz?: number[] // Tonal network features representing harmonic relationships.
52
- pitch?: number // Pitch of the audio signal, measured in Hertz (Hz).
53
- crc32?: number // crc32 checksum of the audio signal, used to verify the integrity of the audio.
54
- }
55
-
56
- /**
57
- * Options to specify which audio features to extract.
58
- */
59
- export interface AudioFeaturesOptions {
60
- energy?: boolean
61
- mfcc?: boolean
62
- rms?: boolean
63
- zcr?: boolean
64
- spectralCentroid?: boolean
65
- spectralFlatness?: boolean
66
- spectralRolloff?: boolean
67
- spectralBandwidth?: boolean
68
- chromagram?: boolean
69
- tempo?: boolean
70
- hnr?: boolean
71
- melSpectrogram?: boolean
72
- spectralContrast?: boolean
73
- tonnetz?: boolean
74
- pitch?: boolean
75
- crc32?: boolean
76
- }
77
-
78
- /**
79
- * Represents a single data point in the audio analysis.
80
- */
81
- export interface DataPoint {
82
- id: number
83
- amplitude: number // Peak amplitude for the segment
84
- rms: number // Root mean square value
85
- dB: number // dBFS (decibels relative to full scale) computed from RMS value
86
- silent: boolean // Always computed
87
- features?: AudioFeatures
88
- speech?: SpeechFeatures
89
- startTime?: number
90
- endTime?: number
91
- // start / end position in bytes
92
- startPosition?: number
93
- endPosition?: number
94
- // number of audio samples for this point (samples size depends on bit depth)
95
- samples?: number
96
- }
97
-
98
- /**
99
- * Represents the complete data from the audio analysis.
100
- */
101
- export interface AudioAnalysis {
102
- segmentDurationMs: number // Duration of each segment in milliseconds
103
- durationMs: number // Duration of the audio in milliseconds
104
- bitDepth: number // Bit depth of the audio
105
- samples: number // Size of the audio in bytes
106
- numberOfChannels: number // Number of audio channels
107
- sampleRate: number // Sample rate of the audio
108
- dataPoints: DataPoint[] // Array of data points from the analysis.
109
- amplitudeRange: {
110
- min: number
111
- max: number
112
- }
113
- rmsRange: {
114
- min: number
115
- max: number
116
- }
117
- // TODO: speaker changes into a broader speech analysis section
118
- speechAnalysis?: {
119
- speakerChanges: {
120
- timestamp: number
121
- speakerId: number
122
- }[]
123
- // Could add more speech analysis data here like:
124
- // dominantSpeaker?: number
125
- // totalSpeechDuration?: number
126
- // speakerStats?: { [speakerId: number]: { duration: number, segments: number } }
127
- }
128
- }
129
-
130
- /**
131
- * Options for specifying a time range within an audio file.
132
- */
133
- export interface AudioRangeOptions {
134
- /** Start time in milliseconds */
135
- startTimeMs?: number
136
- /** End time in milliseconds */
137
- endTimeMs?: number
138
- }
139
-
140
- /**
141
- * Options for generating a quick preview of audio waveform.
142
- * This is optimized for UI rendering with a specified number of points.
143
- */
144
- export interface PreviewOptions extends AudioRangeOptions {
145
- /** URI of the audio file to analyze */
146
- fileUri: string
147
- /**
148
- * Total number of points to generate for the preview.
149
- * @default 100
150
- */
151
- numberOfPoints?: number
152
- /**
153
- * Optional logger for debugging.
154
- */
155
- logger?: ConsoleLike
156
- /**
157
- * Optional configuration for decoding the audio file.
158
- * Defaults to:
159
- * - targetSampleRate: undefined (keep original)
160
- * - targetChannels: undefined (keep original)
161
- * - targetBitDepth: 16
162
- * - normalizeAudio: false
163
- */
164
- decodingOptions?: DecodingConfig
165
- }
166
-
167
- /**
168
- * Options for mel-spectrogram extraction
169
- *
170
- * @experimental This feature is experimental and currently only available on Android.
171
- * The API may change in future versions.
172
- */
173
- export interface ExtractMelSpectrogramOptions {
174
- fileUri?: string // Path to audio file
175
- arrayBuffer?: ArrayBuffer // Raw audio buffer
176
- windowSizeMs: number // Window size in ms (e.g., 25)
177
- hopLengthMs: number // Hop length in ms (e.g., 10)
178
- nMels: number // Number of mel filters (e.g., 60)
179
- fMin?: number // Min frequency (default: 0)
180
- fMax?: number // Max frequency (default: sampleRate / 2)
181
- windowType?: 'hann' | 'hamming' // Window function (default: 'hann')
182
- normalize?: boolean // Mean normalization (default: false)
183
- logScale?: boolean // Log scaling of mel energies (default: true)
184
- decodingOptions?: DecodingConfig // Audio decoding settings
185
- startTimeMs?: number // Optional start time
186
- endTimeMs?: number // Optional end time
187
- logger?: ConsoleLike
188
- }
189
-
190
- /**
191
- * Return type for mel spectrogram extraction
192
- *
193
- * @experimental This feature is experimental and currently only available on Android.
194
- * The API may change in future versions.
195
- */
196
- export interface MelSpectrogram {
197
- spectrogram: number[][] // 2D array [time][mel]
198
- sampleRate: number // Audio sample rate
199
- nMels: number // Number of mel filters
200
- timeSteps: number // Number of time frames
201
- durationMs: number // Audio duration in ms
202
- }