@siteed/expo-audio-stream 2.1.0 → 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.
- package/README.md +40 -222
- package/build/index.d.ts +11 -15
- package/build/index.js +44 -14
- package/package.json +49 -110
- package/src/index.ts +18 -32
- package/CHANGELOG.md +0 -206
- package/android/build.gradle +0 -105
- package/android/src/main/AndroidManifest.xml +0 -27
- package/android/src/main/java/net/siteed/audiostream/AudioAnalysisData.kt +0 -166
- package/android/src/main/java/net/siteed/audiostream/AudioDataEncoder.kt +0 -9
- package/android/src/main/java/net/siteed/audiostream/AudioFileHandler.kt +0 -131
- package/android/src/main/java/net/siteed/audiostream/AudioFormatUtils.kt +0 -103
- package/android/src/main/java/net/siteed/audiostream/AudioNotificationsManager.kt +0 -435
- package/android/src/main/java/net/siteed/audiostream/AudioProcessor.kt +0 -2235
- package/android/src/main/java/net/siteed/audiostream/AudioRecorderManager.kt +0 -1437
- package/android/src/main/java/net/siteed/audiostream/AudioRecordingService.kt +0 -152
- package/android/src/main/java/net/siteed/audiostream/AudioTrimmer.kt +0 -1099
- package/android/src/main/java/net/siteed/audiostream/Constants.kt +0 -21
- package/android/src/main/java/net/siteed/audiostream/EventSender.kt +0 -7
- package/android/src/main/java/net/siteed/audiostream/ExpoAudioStreamModule.kt +0 -739
- package/android/src/main/java/net/siteed/audiostream/FFT.kt +0 -99
- package/android/src/main/java/net/siteed/audiostream/Features.kt +0 -98
- package/android/src/main/java/net/siteed/audiostream/NotificationConfig.kt +0 -70
- package/android/src/main/java/net/siteed/audiostream/PermissionUtils.kt +0 -59
- package/android/src/main/java/net/siteed/audiostream/RecordingActionReceiver.kt +0 -59
- package/android/src/main/java/net/siteed/audiostream/RecordingConfig.kt +0 -205
- package/android/src/main/java/net/siteed/audiostream/WaveformConfig.kt +0 -19
- package/android/src/main/java/net/siteed/audiostream/WaveformRenderer.kt +0 -159
- package/android/src/main/res/drawable/ic_default_action_icon.xml +0 -16
- package/android/src/main/res/drawable/ic_microphone.xml +0 -13
- package/android/src/main/res/drawable/ic_pause.xml +0 -10
- package/android/src/main/res/drawable/ic_play.xml +0 -10
- package/android/src/main/res/drawable/ic_stop.xml +0 -10
- package/android/src/main/res/layout/notification_recording.xml +0 -37
- package/android/src/main/test/java/net/siteed/audiostream/AudioProcessorTest.kt +0 -56
- package/app.plugin.js +0 -1
- package/build/AudioAnalysis/AudioAnalysis.types.d.ts +0 -179
- package/build/AudioAnalysis/AudioAnalysis.types.d.ts.map +0 -1
- package/build/AudioAnalysis/AudioAnalysis.types.js +0 -3
- package/build/AudioAnalysis/AudioAnalysis.types.js.map +0 -1
- package/build/AudioAnalysis/extractAudioAnalysis.d.ts +0 -68
- package/build/AudioAnalysis/extractAudioAnalysis.d.ts.map +0 -1
- package/build/AudioAnalysis/extractAudioAnalysis.js +0 -203
- package/build/AudioAnalysis/extractAudioAnalysis.js.map +0 -1
- package/build/AudioAnalysis/extractAudioData.d.ts +0 -3
- package/build/AudioAnalysis/extractAudioData.d.ts.map +0 -1
- package/build/AudioAnalysis/extractAudioData.js +0 -5
- package/build/AudioAnalysis/extractAudioData.js.map +0 -1
- package/build/AudioAnalysis/extractMelSpectrogram.d.ts +0 -14
- package/build/AudioAnalysis/extractMelSpectrogram.d.ts.map +0 -1
- package/build/AudioAnalysis/extractMelSpectrogram.js +0 -85
- package/build/AudioAnalysis/extractMelSpectrogram.js.map +0 -1
- package/build/AudioAnalysis/extractPreview.d.ts +0 -11
- package/build/AudioAnalysis/extractPreview.d.ts.map +0 -1
- package/build/AudioAnalysis/extractPreview.js +0 -25
- package/build/AudioAnalysis/extractPreview.js.map +0 -1
- package/build/AudioAnalysis/extractWaveform.d.ts +0 -8
- package/build/AudioAnalysis/extractWaveform.d.ts.map +0 -1
- package/build/AudioAnalysis/extractWaveform.js +0 -11
- package/build/AudioAnalysis/extractWaveform.js.map +0 -1
- package/build/AudioRecorder.provider.d.ts +0 -11
- package/build/AudioRecorder.provider.d.ts.map +0 -1
- package/build/AudioRecorder.provider.js +0 -37
- package/build/AudioRecorder.provider.js.map +0 -1
- package/build/ExpoAudioStream.native.d.ts +0 -3
- package/build/ExpoAudioStream.native.d.ts.map +0 -1
- package/build/ExpoAudioStream.native.js +0 -6
- package/build/ExpoAudioStream.native.js.map +0 -1
- package/build/ExpoAudioStream.types.d.ts +0 -532
- package/build/ExpoAudioStream.types.d.ts.map +0 -1
- package/build/ExpoAudioStream.types.js +0 -2
- package/build/ExpoAudioStream.types.js.map +0 -1
- package/build/ExpoAudioStream.web.d.ts +0 -59
- package/build/ExpoAudioStream.web.d.ts.map +0 -1
- package/build/ExpoAudioStream.web.js +0 -285
- package/build/ExpoAudioStream.web.js.map +0 -1
- package/build/ExpoAudioStreamModule.d.ts +0 -3
- package/build/ExpoAudioStreamModule.d.ts.map +0 -1
- package/build/ExpoAudioStreamModule.js +0 -693
- package/build/ExpoAudioStreamModule.js.map +0 -1
- package/build/WebRecorder.web.d.ts +0 -119
- package/build/WebRecorder.web.d.ts.map +0 -1
- package/build/WebRecorder.web.js +0 -436
- package/build/WebRecorder.web.js.map +0 -1
- package/build/constants.d.ts +0 -11
- package/build/constants.d.ts.map +0 -1
- package/build/constants.js +0 -14
- package/build/constants.js.map +0 -1
- package/build/events.d.ts +0 -26
- package/build/events.d.ts.map +0 -1
- package/build/events.js +0 -21
- package/build/events.js.map +0 -1
- package/build/index.d.ts.map +0 -1
- package/build/index.js.map +0 -1
- package/build/trimAudio.d.ts +0 -25
- package/build/trimAudio.d.ts.map +0 -1
- package/build/trimAudio.js +0 -67
- package/build/trimAudio.js.map +0 -1
- package/build/useAudioRecorder.d.ts +0 -21
- package/build/useAudioRecorder.d.ts.map +0 -1
- package/build/useAudioRecorder.js +0 -427
- package/build/useAudioRecorder.js.map +0 -1
- package/build/utils/BlobFix.d.ts +0 -9
- package/build/utils/BlobFix.d.ts.map +0 -1
- package/build/utils/BlobFix.js +0 -498
- package/build/utils/BlobFix.js.map +0 -1
- package/build/utils/audioProcessing.d.ts +0 -24
- package/build/utils/audioProcessing.d.ts.map +0 -1
- package/build/utils/audioProcessing.js +0 -133
- package/build/utils/audioProcessing.js.map +0 -1
- package/build/utils/concatenateBuffers.d.ts +0 -8
- package/build/utils/concatenateBuffers.d.ts.map +0 -1
- package/build/utils/concatenateBuffers.js +0 -21
- package/build/utils/concatenateBuffers.js.map +0 -1
- package/build/utils/convertPCMToFloat32.d.ts +0 -13
- package/build/utils/convertPCMToFloat32.d.ts.map +0 -1
- package/build/utils/convertPCMToFloat32.js +0 -120
- package/build/utils/convertPCMToFloat32.js.map +0 -1
- package/build/utils/encodingToBitDepth.d.ts +0 -5
- package/build/utils/encodingToBitDepth.d.ts.map +0 -1
- package/build/utils/encodingToBitDepth.js +0 -13
- package/build/utils/encodingToBitDepth.js.map +0 -1
- package/build/utils/getWavFileInfo.d.ts +0 -26
- package/build/utils/getWavFileInfo.d.ts.map +0 -1
- package/build/utils/getWavFileInfo.js +0 -92
- package/build/utils/getWavFileInfo.js.map +0 -1
- package/build/utils/writeWavHeader.d.ts +0 -49
- package/build/utils/writeWavHeader.d.ts.map +0 -1
- package/build/utils/writeWavHeader.js +0 -91
- package/build/utils/writeWavHeader.js.map +0 -1
- package/build/workers/InlineFeaturesExtractor.web.d.ts +0 -2
- package/build/workers/InlineFeaturesExtractor.web.d.ts.map +0 -1
- package/build/workers/InlineFeaturesExtractor.web.js +0 -828
- package/build/workers/InlineFeaturesExtractor.web.js.map +0 -1
- package/build/workers/inlineAudioWebWorker.web.d.ts +0 -2
- package/build/workers/inlineAudioWebWorker.web.d.ts.map +0 -1
- package/build/workers/inlineAudioWebWorker.web.js +0 -157
- package/build/workers/inlineAudioWebWorker.web.js.map +0 -1
- package/expo-module.config.json +0 -9
- package/ios/AudioAnalysisData.swift +0 -74
- package/ios/AudioNotificationManager.swift +0 -135
- package/ios/AudioProcessingHelpers.swift +0 -743
- package/ios/AudioProcessor.swift +0 -1313
- package/ios/AudioStreamError.swift +0 -7
- package/ios/AudioStreamManager.swift +0 -1708
- package/ios/AudioStreamManagerDelegate.swift +0 -16
- package/ios/DataPoint.swift +0 -54
- package/ios/DecodingConfig.swift +0 -47
- package/ios/ExpoAudioStream.podspec +0 -27
- package/ios/ExpoAudioStreamModule.swift +0 -805
- package/ios/FFT.swift +0 -62
- package/ios/Features.swift +0 -95
- package/ios/Logger.swift +0 -7
- package/ios/NotificationExtension.swift +0 -15
- package/ios/RecordingResult.swift +0 -22
- package/ios/RecordingSettings.swift +0 -265
- package/ios/WaveformExtractor.swift +0 -105
- package/plugin/build/index.d.ts +0 -21
- package/plugin/build/index.js +0 -191
- package/plugin/src/index.ts +0 -278
- package/plugin/tsconfig.json +0 -10
- package/plugin/tsconfig.tsbuildinfo +0 -1
- package/src/AudioAnalysis/AudioAnalysis.types.ts +0 -202
- package/src/AudioAnalysis/extractAudioAnalysis.ts +0 -333
- package/src/AudioAnalysis/extractAudioData.ts +0 -6
- package/src/AudioAnalysis/extractMelSpectrogram.ts +0 -144
- package/src/AudioAnalysis/extractPreview.ts +0 -34
- package/src/AudioAnalysis/extractWaveform.ts +0 -22
- package/src/AudioRecorder.provider.tsx +0 -54
- package/src/ExpoAudioStream.native.ts +0 -6
- package/src/ExpoAudioStream.types.ts +0 -641
- package/src/ExpoAudioStream.web.ts +0 -359
- package/src/ExpoAudioStreamModule.ts +0 -967
- package/src/WebRecorder.web.ts +0 -580
- package/src/constants.ts +0 -18
- package/src/events.ts +0 -60
- package/src/trimAudio.ts +0 -90
- package/src/useAudioRecorder.tsx +0 -620
- package/src/utils/BlobFix.ts +0 -559
- package/src/utils/audioProcessing.ts +0 -205
- package/src/utils/concatenateBuffers.ts +0 -24
- package/src/utils/convertPCMToFloat32.ts +0 -170
- package/src/utils/encodingToBitDepth.ts +0 -18
- package/src/utils/getWavFileInfo.ts +0 -132
- package/src/utils/writeWavHeader.ts +0 -114
- package/src/workers/InlineFeaturesExtractor.web.tsx +0 -827
- package/src/workers/inlineAudioWebWorker.web.tsx +0 -156
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudioStream.web.d.ts","sourceRoot":"","sources":["../src/ExpoAudioStream.web.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAEtD,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAA;AACnE,OAAO,EACH,cAAc,EACd,iBAAiB,EACjB,QAAQ,EACR,WAAW,EACX,eAAe,EACf,oBAAoB,EACvB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAI/C,MAAM,WAAW,mBAAmB;IAChC,IAAI,EAAE,YAAY,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE;QACV,IAAI,EAAE,IAAI,CAAA;QACV,IAAI,EAAE,MAAM,CAAA;QACZ,SAAS,EAAE,MAAM,CAAA;QACjB,QAAQ,EAAE,MAAM,CAAA;QAChB,MAAM,EAAE,MAAM,CAAA;QACd,OAAO,EAAE,MAAM,CAAA;KAClB,CAAA;CACJ;AACD,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,EAAE,mBAAmB,KAAK,IAAI,CAAA;AACrE,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,EAAE,aAAa,KAAK,IAAI,CAAA;AAElE,MAAM,WAAW,uBAAuB;IACpC,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;IACvB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,qBAAa,kBAAmB,SAAQ,kBAAkB;IACtD,cAAc,EAAE,WAAW,GAAG,IAAI,CAAA;IAClC,WAAW,EAAE,YAAY,EAAE,CAAA;IAC3B,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,OAAO,CAAA;IACjB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,iBAAiB,EAAE,MAAM,CAAA;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;IACvB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,eAAe,EAAE,MAAM,CAAA;IACvB,eAAe,EAAE,MAAM,CAAA;IACvB,0BAA0B,EAAE,MAAM,CAAA;IAClC,uBAAuB,EAAE,MAAM,CAAA;IAC/B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,SAAS,EAAE,MAAM,GAAG,KAAK,CAAQ;IACjC,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,QAAQ,EAAE,QAAQ,CAAA;IAClB,eAAe,EAAE,MAAM,CAAA;IACvB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,cAAc,EAAE,MAAM,CAAI;IAC1B,mBAAmB,EAAE,MAAM,CAAI;IAC/B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAQ;gBAE1B,EACR,eAAe,EACf,mBAAmB,EACnB,MAAM,EACN,aAAmB,GACtB,EAAE,uBAAuB;IAmCpB,cAAc;IAUd,cAAc,CAChB,eAAe,GAAE,eAAoB,GACtC,OAAO,CAAC,oBAAoB,CAAC;IA8FhC,cAAc,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,mBAAmB;IAgC7D,aAAa,IAAI,OAAO,CAAC,cAAc,CAAC;IAoExC,cAAc;IAad,eAAe;IAarB,MAAM;CAsBT"}
|
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
// src/ExpoAudioStreamModule.web.ts
|
|
2
|
-
import { LegacyEventEmitter } from 'expo-modules-core';
|
|
3
|
-
import { WebRecorder } from './WebRecorder.web';
|
|
4
|
-
import { encodingToBitDepth } from './utils/encodingToBitDepth';
|
|
5
|
-
export class ExpoAudioStreamWeb extends LegacyEventEmitter {
|
|
6
|
-
customRecorder;
|
|
7
|
-
audioChunks;
|
|
8
|
-
isRecording;
|
|
9
|
-
isPaused;
|
|
10
|
-
recordingStartTime;
|
|
11
|
-
pausedTime;
|
|
12
|
-
currentDurationMs;
|
|
13
|
-
currentSize;
|
|
14
|
-
currentInterval;
|
|
15
|
-
currentIntervalAnalysis;
|
|
16
|
-
lastEmittedSize;
|
|
17
|
-
lastEmittedTime;
|
|
18
|
-
lastEmittedCompressionSize;
|
|
19
|
-
lastEmittedAnalysisTime;
|
|
20
|
-
streamUuid;
|
|
21
|
-
extension = 'wav'; // Default extension is 'wav'
|
|
22
|
-
recordingConfig;
|
|
23
|
-
bitDepth; // Bit depth of the audio
|
|
24
|
-
audioWorkletUrl;
|
|
25
|
-
featuresExtratorUrl;
|
|
26
|
-
logger;
|
|
27
|
-
latestPosition = 0;
|
|
28
|
-
totalCompressedSize = 0;
|
|
29
|
-
maxBufferSize;
|
|
30
|
-
constructor({ audioWorkletUrl, featuresExtratorUrl, logger, maxBufferSize = 100, // Default to storing last 100 chunks (1 chunk = 0.5 seconds)
|
|
31
|
-
}) {
|
|
32
|
-
const mockNativeModule = {
|
|
33
|
-
addListener: () => {
|
|
34
|
-
// Not used on web
|
|
35
|
-
},
|
|
36
|
-
removeListeners: () => {
|
|
37
|
-
// Not used on web
|
|
38
|
-
},
|
|
39
|
-
};
|
|
40
|
-
super(mockNativeModule); // Pass the mock native module to the parent class
|
|
41
|
-
this.logger = logger;
|
|
42
|
-
this.customRecorder = null;
|
|
43
|
-
this.audioChunks = [];
|
|
44
|
-
this.isRecording = false;
|
|
45
|
-
this.isPaused = false;
|
|
46
|
-
this.recordingStartTime = 0;
|
|
47
|
-
this.pausedTime = 0;
|
|
48
|
-
this.currentDurationMs = 0;
|
|
49
|
-
this.currentSize = 0;
|
|
50
|
-
this.bitDepth = 32; // Default
|
|
51
|
-
this.currentInterval = 1000; // Default interval in ms
|
|
52
|
-
this.currentIntervalAnalysis = 500; // Default analysis interval in ms
|
|
53
|
-
this.lastEmittedSize = 0;
|
|
54
|
-
this.lastEmittedTime = 0;
|
|
55
|
-
this.latestPosition = 0;
|
|
56
|
-
this.lastEmittedCompressionSize = 0;
|
|
57
|
-
this.lastEmittedAnalysisTime = 0;
|
|
58
|
-
this.streamUuid = null; // Initialize UUID on first recording start
|
|
59
|
-
this.audioWorkletUrl = audioWorkletUrl;
|
|
60
|
-
this.featuresExtratorUrl = featuresExtratorUrl;
|
|
61
|
-
this.maxBufferSize = maxBufferSize;
|
|
62
|
-
}
|
|
63
|
-
// Utility to handle user media stream
|
|
64
|
-
async getMediaStream() {
|
|
65
|
-
try {
|
|
66
|
-
return await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
67
|
-
}
|
|
68
|
-
catch (error) {
|
|
69
|
-
this.logger?.error('Failed to get media stream:', error);
|
|
70
|
-
throw error;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// Start recording with options
|
|
74
|
-
async startRecording(recordingConfig = {}) {
|
|
75
|
-
if (this.isRecording) {
|
|
76
|
-
throw new Error('Recording is already in progress');
|
|
77
|
-
}
|
|
78
|
-
this.bitDepth = encodingToBitDepth({
|
|
79
|
-
encoding: recordingConfig.encoding ?? 'pcm_32bit',
|
|
80
|
-
});
|
|
81
|
-
const audioContext = new (window.AudioContext ||
|
|
82
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
83
|
-
// @ts-ignore - Allow webkitAudioContext for Safari
|
|
84
|
-
window.webkitAudioContext)();
|
|
85
|
-
const stream = await this.getMediaStream();
|
|
86
|
-
const source = audioContext.createMediaStreamSource(stream);
|
|
87
|
-
this.customRecorder = new WebRecorder({
|
|
88
|
-
logger: this.logger,
|
|
89
|
-
audioContext,
|
|
90
|
-
source,
|
|
91
|
-
recordingConfig,
|
|
92
|
-
emitAudioEventCallback: ({ data, position, compression, }) => {
|
|
93
|
-
// Keep only the latest chunks based on maxBufferSize
|
|
94
|
-
this.audioChunks.push(new Float32Array(data));
|
|
95
|
-
if (this.audioChunks.length > this.maxBufferSize) {
|
|
96
|
-
this.audioChunks.shift(); // Remove oldest chunk
|
|
97
|
-
}
|
|
98
|
-
this.currentSize += data.byteLength;
|
|
99
|
-
this.emitAudioEvent({ data, position, compression });
|
|
100
|
-
this.lastEmittedTime = Date.now();
|
|
101
|
-
this.lastEmittedSize = this.currentSize;
|
|
102
|
-
this.lastEmittedCompressionSize = compression?.size ?? 0;
|
|
103
|
-
},
|
|
104
|
-
emitAudioAnalysisCallback: (audioAnalysisData) => {
|
|
105
|
-
this.logger?.log(`Emitted AudioAnalysis:`, audioAnalysisData);
|
|
106
|
-
this.emit('AudioAnalysis', audioAnalysisData);
|
|
107
|
-
},
|
|
108
|
-
});
|
|
109
|
-
await this.customRecorder.init();
|
|
110
|
-
this.customRecorder.start();
|
|
111
|
-
// // Set a timer to stop recording after 5 seconds
|
|
112
|
-
// setTimeout(() => {
|
|
113
|
-
// logger.log("AUTO Stopping recording");
|
|
114
|
-
// this.customRecorder?.stopAndPlay();
|
|
115
|
-
// this.isRecording = false;
|
|
116
|
-
// }, 3000);
|
|
117
|
-
this.isRecording = true;
|
|
118
|
-
this.recordingConfig = recordingConfig;
|
|
119
|
-
this.recordingStartTime = Date.now();
|
|
120
|
-
this.pausedTime = 0;
|
|
121
|
-
this.isPaused = false;
|
|
122
|
-
this.lastEmittedSize = 0;
|
|
123
|
-
this.lastEmittedTime = 0;
|
|
124
|
-
this.lastEmittedCompressionSize = 0;
|
|
125
|
-
this.currentInterval = recordingConfig.interval ?? 1000;
|
|
126
|
-
this.currentIntervalAnalysis = recordingConfig.intervalAnalysis ?? 500;
|
|
127
|
-
this.lastEmittedAnalysisTime = Date.now();
|
|
128
|
-
// Use custom filename if provided, otherwise fallback to timestamp
|
|
129
|
-
if (recordingConfig.filename) {
|
|
130
|
-
// Remove any existing extension from the filename
|
|
131
|
-
this.streamUuid = recordingConfig.filename.replace(/\.[^/.]+$/, '');
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
this.streamUuid = Date.now().toString();
|
|
135
|
-
}
|
|
136
|
-
const fileUri = `${this.streamUuid}.${this.extension}`;
|
|
137
|
-
const streamConfig = {
|
|
138
|
-
fileUri,
|
|
139
|
-
mimeType: `audio/${this.extension}`,
|
|
140
|
-
bitDepth: this.bitDepth,
|
|
141
|
-
channels: recordingConfig.channels ?? 1,
|
|
142
|
-
sampleRate: recordingConfig.sampleRate ?? 44100,
|
|
143
|
-
compression: recordingConfig.compression
|
|
144
|
-
? {
|
|
145
|
-
...recordingConfig.compression,
|
|
146
|
-
bitrate: recordingConfig.compression?.bitrate ?? 128000,
|
|
147
|
-
size: 0,
|
|
148
|
-
mimeType: 'audio/webm',
|
|
149
|
-
format: recordingConfig.compression?.format ?? 'opus',
|
|
150
|
-
compressedFileUri: '',
|
|
151
|
-
}
|
|
152
|
-
: undefined,
|
|
153
|
-
};
|
|
154
|
-
return streamConfig;
|
|
155
|
-
}
|
|
156
|
-
emitAudioEvent({ data, position, compression }) {
|
|
157
|
-
const fileUri = `${this.streamUuid}.${this.extension}`;
|
|
158
|
-
if (compression?.size) {
|
|
159
|
-
this.lastEmittedCompressionSize = compression.size;
|
|
160
|
-
this.totalCompressedSize = compression.totalSize;
|
|
161
|
-
}
|
|
162
|
-
this.latestPosition = position;
|
|
163
|
-
this.currentDurationMs = position * 1000; // Convert position (in seconds) to ms
|
|
164
|
-
const audioEventPayload = {
|
|
165
|
-
fileUri,
|
|
166
|
-
mimeType: `audio/${this.extension}`,
|
|
167
|
-
lastEmittedSize: this.lastEmittedSize,
|
|
168
|
-
deltaSize: data.byteLength,
|
|
169
|
-
position,
|
|
170
|
-
totalSize: this.currentSize,
|
|
171
|
-
buffer: data,
|
|
172
|
-
streamUuid: this.streamUuid ?? '',
|
|
173
|
-
compression: compression
|
|
174
|
-
? {
|
|
175
|
-
data: compression?.data,
|
|
176
|
-
totalSize: this.totalCompressedSize,
|
|
177
|
-
eventDataSize: compression?.size ?? 0,
|
|
178
|
-
position,
|
|
179
|
-
}
|
|
180
|
-
: undefined,
|
|
181
|
-
};
|
|
182
|
-
this.emit('AudioData', audioEventPayload);
|
|
183
|
-
}
|
|
184
|
-
// Stop recording
|
|
185
|
-
async stopRecording() {
|
|
186
|
-
if (!this.customRecorder) {
|
|
187
|
-
throw new Error('Recorder is not initialized');
|
|
188
|
-
}
|
|
189
|
-
this.logger?.debug('[Stop] Starting stop process');
|
|
190
|
-
const startTime = performance.now();
|
|
191
|
-
try {
|
|
192
|
-
this.logger?.debug('[Stop] Stopping recorder');
|
|
193
|
-
const { compressedBlob } = await this.customRecorder.stop();
|
|
194
|
-
this.isRecording = false;
|
|
195
|
-
this.isPaused = false;
|
|
196
|
-
this.currentDurationMs = Date.now() - this.recordingStartTime;
|
|
197
|
-
let compression;
|
|
198
|
-
let fileUri = `${this.streamUuid}.${this.extension}`;
|
|
199
|
-
let mimeType = `audio/${this.extension}`;
|
|
200
|
-
if (compressedBlob && this.recordingConfig?.compression?.enabled) {
|
|
201
|
-
const compressedUri = URL.createObjectURL(compressedBlob);
|
|
202
|
-
compression = {
|
|
203
|
-
compressedFileUri: compressedUri,
|
|
204
|
-
size: compressedBlob.size,
|
|
205
|
-
mimeType: 'audio/webm',
|
|
206
|
-
format: 'opus',
|
|
207
|
-
bitrate: this.recordingConfig.compression.bitrate ?? 128000,
|
|
208
|
-
};
|
|
209
|
-
// Use compressed values when compression is enabled
|
|
210
|
-
fileUri = compressedUri;
|
|
211
|
-
mimeType = 'audio/webm';
|
|
212
|
-
}
|
|
213
|
-
this.logger?.debug(`[Stop] Completed stop process in ${performance.now() - startTime}ms`, {
|
|
214
|
-
durationMs: this.currentDurationMs,
|
|
215
|
-
compressedSize: compression?.size,
|
|
216
|
-
});
|
|
217
|
-
// Use the stored streamUuid (which contains our custom filename) for the final filename
|
|
218
|
-
const filename = `${this.streamUuid}.${this.extension}`;
|
|
219
|
-
const result = {
|
|
220
|
-
fileUri,
|
|
221
|
-
filename, // This will now use our custom filename
|
|
222
|
-
bitDepth: this.bitDepth,
|
|
223
|
-
createdAt: this.recordingStartTime,
|
|
224
|
-
channels: this.recordingConfig?.channels ?? 1,
|
|
225
|
-
sampleRate: this.recordingConfig?.sampleRate ?? 44100,
|
|
226
|
-
durationMs: this.currentDurationMs,
|
|
227
|
-
size: this.currentSize,
|
|
228
|
-
mimeType,
|
|
229
|
-
compression,
|
|
230
|
-
};
|
|
231
|
-
// Reset after creating the result
|
|
232
|
-
this.streamUuid = null;
|
|
233
|
-
return result;
|
|
234
|
-
}
|
|
235
|
-
catch (error) {
|
|
236
|
-
this.logger?.error('[Stop] Error stopping recording:', error);
|
|
237
|
-
throw error;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
// Pause recording
|
|
241
|
-
async pauseRecording() {
|
|
242
|
-
if (!this.isRecording || this.isPaused) {
|
|
243
|
-
throw new Error('Recording is not active or already paused');
|
|
244
|
-
}
|
|
245
|
-
if (this.customRecorder) {
|
|
246
|
-
this.customRecorder.pause();
|
|
247
|
-
}
|
|
248
|
-
this.isPaused = true;
|
|
249
|
-
this.pausedTime = Date.now();
|
|
250
|
-
}
|
|
251
|
-
// Resume recording
|
|
252
|
-
async resumeRecording() {
|
|
253
|
-
if (!this.isPaused) {
|
|
254
|
-
throw new Error('Recording is not paused');
|
|
255
|
-
}
|
|
256
|
-
if (this.customRecorder) {
|
|
257
|
-
this.customRecorder.resume();
|
|
258
|
-
}
|
|
259
|
-
this.isPaused = false;
|
|
260
|
-
this.recordingStartTime += Date.now() - this.pausedTime;
|
|
261
|
-
}
|
|
262
|
-
// Get current status
|
|
263
|
-
status() {
|
|
264
|
-
const status = {
|
|
265
|
-
isRecording: this.isRecording,
|
|
266
|
-
isPaused: this.isPaused,
|
|
267
|
-
durationMs: this.currentDurationMs,
|
|
268
|
-
size: this.currentSize,
|
|
269
|
-
interval: this.currentInterval,
|
|
270
|
-
intervalAnalysis: this.currentIntervalAnalysis,
|
|
271
|
-
mimeType: `audio/${this.extension}`,
|
|
272
|
-
compression: this.recordingConfig?.compression?.enabled
|
|
273
|
-
? {
|
|
274
|
-
size: this.totalCompressedSize,
|
|
275
|
-
mimeType: 'audio/webm',
|
|
276
|
-
format: this.recordingConfig.compression.format ?? 'opus',
|
|
277
|
-
bitrate: this.recordingConfig.compression.bitrate ?? 128000,
|
|
278
|
-
compressedFileUri: `${this.streamUuid}.webm`,
|
|
279
|
-
}
|
|
280
|
-
: undefined,
|
|
281
|
-
};
|
|
282
|
-
return status;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
//# sourceMappingURL=ExpoAudioStream.web.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudioStream.web.js","sourceRoot":"","sources":["../src/ExpoAudioStream.web.ts"],"names":[],"mappings":"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","sourcesContent":["// src/ExpoAudioStreamModule.web.ts\nimport { LegacyEventEmitter } from 'expo-modules-core'\n\nimport { AudioAnalysis } from './AudioAnalysis/AudioAnalysis.types'\nimport {\n AudioRecording,\n AudioStreamStatus,\n BitDepth,\n ConsoleLike,\n RecordingConfig,\n StartRecordingResult,\n} from './ExpoAudioStream.types'\nimport { WebRecorder } from './WebRecorder.web'\nimport { AudioEventPayload } from './events'\nimport { encodingToBitDepth } from './utils/encodingToBitDepth'\n\nexport interface EmitAudioEventProps {\n data: Float32Array\n position: number\n compression?: {\n data: Blob\n size: number\n totalSize: number\n mimeType: string\n format: string\n bitrate: number\n }\n}\nexport type EmitAudioEventFunction = (_: EmitAudioEventProps) => void\nexport type EmitAudioAnalysisFunction = (_: AudioAnalysis) => void\n\nexport interface ExpoAudioStreamWebProps {\n logger?: ConsoleLike\n audioWorkletUrl: string\n featuresExtratorUrl: string\n maxBufferSize?: number // Maximum number of chunks to keep in memory\n}\n\nexport class ExpoAudioStreamWeb extends LegacyEventEmitter {\n customRecorder: WebRecorder | null\n audioChunks: Float32Array[]\n isRecording: boolean\n isPaused: boolean\n recordingStartTime: number\n pausedTime: number\n currentDurationMs: number\n currentSize: number\n currentInterval: number\n currentIntervalAnalysis: number\n lastEmittedSize: number\n lastEmittedTime: number\n lastEmittedCompressionSize: number\n lastEmittedAnalysisTime: number\n streamUuid: string | null\n extension: 'webm' | 'wav' = 'wav' // Default extension is 'wav'\n recordingConfig?: RecordingConfig\n bitDepth: BitDepth // Bit depth of the audio\n audioWorkletUrl: string\n featuresExtratorUrl: string\n logger?: ConsoleLike\n latestPosition: number = 0\n totalCompressedSize: number = 0\n private readonly maxBufferSize: number\n\n constructor({\n audioWorkletUrl,\n featuresExtratorUrl,\n logger,\n maxBufferSize = 100, // Default to storing last 100 chunks (1 chunk = 0.5 seconds)\n }: ExpoAudioStreamWebProps) {\n const mockNativeModule = {\n addListener: () => {\n // Not used on web\n },\n removeListeners: () => {\n // Not used on web\n },\n }\n super(mockNativeModule) // Pass the mock native module to the parent class\n\n this.logger = logger\n this.customRecorder = null\n this.audioChunks = []\n this.isRecording = false\n this.isPaused = false\n this.recordingStartTime = 0\n this.pausedTime = 0\n this.currentDurationMs = 0\n this.currentSize = 0\n this.bitDepth = 32 // Default\n this.currentInterval = 1000 // Default interval in ms\n this.currentIntervalAnalysis = 500 // Default analysis interval in ms\n this.lastEmittedSize = 0\n this.lastEmittedTime = 0\n this.latestPosition = 0\n this.lastEmittedCompressionSize = 0\n this.lastEmittedAnalysisTime = 0\n this.streamUuid = null // Initialize UUID on first recording start\n this.audioWorkletUrl = audioWorkletUrl\n this.featuresExtratorUrl = featuresExtratorUrl\n this.maxBufferSize = maxBufferSize\n }\n\n // Utility to handle user media stream\n async getMediaStream() {\n try {\n return await navigator.mediaDevices.getUserMedia({ audio: true })\n } catch (error) {\n this.logger?.error('Failed to get media stream:', error)\n throw error\n }\n }\n\n // Start recording with options\n async startRecording(\n recordingConfig: RecordingConfig = {}\n ): Promise<StartRecordingResult> {\n if (this.isRecording) {\n throw new Error('Recording is already in progress')\n }\n\n this.bitDepth = encodingToBitDepth({\n encoding: recordingConfig.encoding ?? 'pcm_32bit',\n })\n\n const audioContext = new (window.AudioContext ||\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore - Allow webkitAudioContext for Safari\n window.webkitAudioContext)()\n const stream = await this.getMediaStream()\n\n const source = audioContext.createMediaStreamSource(stream)\n\n this.customRecorder = new WebRecorder({\n logger: this.logger,\n audioContext,\n source,\n recordingConfig,\n emitAudioEventCallback: ({\n data,\n position,\n compression,\n }: EmitAudioEventProps) => {\n // Keep only the latest chunks based on maxBufferSize\n this.audioChunks.push(new Float32Array(data))\n if (this.audioChunks.length > this.maxBufferSize) {\n this.audioChunks.shift() // Remove oldest chunk\n }\n this.currentSize += data.byteLength\n this.emitAudioEvent({ data, position, compression })\n this.lastEmittedTime = Date.now()\n this.lastEmittedSize = this.currentSize\n this.lastEmittedCompressionSize = compression?.size ?? 0\n },\n emitAudioAnalysisCallback: (audioAnalysisData: AudioAnalysis) => {\n this.logger?.log(`Emitted AudioAnalysis:`, audioAnalysisData)\n this.emit('AudioAnalysis', audioAnalysisData)\n },\n })\n await this.customRecorder.init()\n this.customRecorder.start()\n\n // // Set a timer to stop recording after 5 seconds\n // setTimeout(() => {\n // logger.log(\"AUTO Stopping recording\");\n // this.customRecorder?.stopAndPlay();\n // this.isRecording = false;\n // }, 3000);\n\n this.isRecording = true\n this.recordingConfig = recordingConfig\n this.recordingStartTime = Date.now()\n this.pausedTime = 0\n this.isPaused = false\n this.lastEmittedSize = 0\n this.lastEmittedTime = 0\n this.lastEmittedCompressionSize = 0\n this.currentInterval = recordingConfig.interval ?? 1000\n this.currentIntervalAnalysis = recordingConfig.intervalAnalysis ?? 500\n this.lastEmittedAnalysisTime = Date.now()\n\n // Use custom filename if provided, otherwise fallback to timestamp\n if (recordingConfig.filename) {\n // Remove any existing extension from the filename\n this.streamUuid = recordingConfig.filename.replace(/\\.[^/.]+$/, '')\n } else {\n this.streamUuid = Date.now().toString()\n }\n\n const fileUri = `${this.streamUuid}.${this.extension}`\n const streamConfig: StartRecordingResult = {\n fileUri,\n mimeType: `audio/${this.extension}`,\n bitDepth: this.bitDepth,\n channels: recordingConfig.channels ?? 1,\n sampleRate: recordingConfig.sampleRate ?? 44100,\n compression: recordingConfig.compression\n ? {\n ...recordingConfig.compression,\n bitrate: recordingConfig.compression?.bitrate ?? 128000,\n size: 0,\n mimeType: 'audio/webm',\n format: recordingConfig.compression?.format ?? 'opus',\n compressedFileUri: '',\n }\n : undefined,\n }\n return streamConfig\n }\n\n emitAudioEvent({ data, position, compression }: EmitAudioEventProps) {\n const fileUri = `${this.streamUuid}.${this.extension}`\n if (compression?.size) {\n this.lastEmittedCompressionSize = compression.size\n this.totalCompressedSize = compression.totalSize\n }\n this.latestPosition = position\n this.currentDurationMs = position * 1000 // Convert position (in seconds) to ms\n\n const audioEventPayload: AudioEventPayload = {\n fileUri,\n mimeType: `audio/${this.extension}`,\n lastEmittedSize: this.lastEmittedSize,\n deltaSize: data.byteLength,\n position,\n totalSize: this.currentSize,\n buffer: data,\n streamUuid: this.streamUuid ?? '',\n compression: compression\n ? {\n data: compression?.data,\n totalSize: this.totalCompressedSize,\n eventDataSize: compression?.size ?? 0,\n position,\n }\n : undefined,\n }\n\n this.emit('AudioData', audioEventPayload)\n }\n\n // Stop recording\n async stopRecording(): Promise<AudioRecording> {\n if (!this.customRecorder) {\n throw new Error('Recorder is not initialized')\n }\n\n this.logger?.debug('[Stop] Starting stop process')\n const startTime = performance.now()\n\n try {\n this.logger?.debug('[Stop] Stopping recorder')\n const { compressedBlob } = await this.customRecorder.stop()\n\n this.isRecording = false\n this.isPaused = false\n this.currentDurationMs = Date.now() - this.recordingStartTime\n\n let compression: AudioRecording['compression']\n let fileUri = `${this.streamUuid}.${this.extension}`\n let mimeType = `audio/${this.extension}`\n\n if (compressedBlob && this.recordingConfig?.compression?.enabled) {\n const compressedUri = URL.createObjectURL(compressedBlob)\n compression = {\n compressedFileUri: compressedUri,\n size: compressedBlob.size,\n mimeType: 'audio/webm',\n format: 'opus',\n bitrate: this.recordingConfig.compression.bitrate ?? 128000,\n }\n // Use compressed values when compression is enabled\n fileUri = compressedUri\n mimeType = 'audio/webm'\n }\n\n this.logger?.debug(\n `[Stop] Completed stop process in ${performance.now() - startTime}ms`,\n {\n durationMs: this.currentDurationMs,\n compressedSize: compression?.size,\n }\n )\n\n // Use the stored streamUuid (which contains our custom filename) for the final filename\n const filename = `${this.streamUuid}.${this.extension}`\n const result: AudioRecording = {\n fileUri,\n filename, // This will now use our custom filename\n bitDepth: this.bitDepth,\n createdAt: this.recordingStartTime,\n channels: this.recordingConfig?.channels ?? 1,\n sampleRate: this.recordingConfig?.sampleRate ?? 44100,\n durationMs: this.currentDurationMs,\n size: this.currentSize,\n mimeType,\n compression,\n }\n\n // Reset after creating the result\n this.streamUuid = null\n\n return result\n } catch (error) {\n this.logger?.error('[Stop] Error stopping recording:', error)\n throw error\n }\n }\n\n // Pause recording\n async pauseRecording() {\n if (!this.isRecording || this.isPaused) {\n throw new Error('Recording is not active or already paused')\n }\n\n if (this.customRecorder) {\n this.customRecorder.pause()\n }\n this.isPaused = true\n this.pausedTime = Date.now()\n }\n\n // Resume recording\n async resumeRecording() {\n if (!this.isPaused) {\n throw new Error('Recording is not paused')\n }\n\n if (this.customRecorder) {\n this.customRecorder.resume()\n }\n this.isPaused = false\n this.recordingStartTime += Date.now() - this.pausedTime\n }\n\n // Get current status\n status() {\n const status: AudioStreamStatus = {\n isRecording: this.isRecording,\n isPaused: this.isPaused,\n durationMs: this.currentDurationMs,\n size: this.currentSize,\n interval: this.currentInterval,\n intervalAnalysis: this.currentIntervalAnalysis,\n mimeType: `audio/${this.extension}`,\n compression: this.recordingConfig?.compression?.enabled\n ? {\n size: this.totalCompressedSize,\n mimeType: 'audio/webm',\n format: this.recordingConfig.compression.format ?? 'opus',\n bitrate:\n this.recordingConfig.compression.bitrate ?? 128000,\n compressedFileUri: `${this.streamUuid}.webm`,\n }\n : undefined,\n }\n return status\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudioStreamModule.d.ts","sourceRoot":"","sources":["../src/ExpoAudioStreamModule.ts"],"names":[],"mappings":"AAmBA,QAAA,IAAI,qBAAqB,EAAE,GAAG,CAAA;AAm7B9B,eAAe,qBAAqB,CAAA"}
|