@siteed/expo-audio-stream 1.17.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -1
- package/README.md +1 -1
- package/android/src/main/java/net/siteed/audiostream/AudioAnalysisData.kt +68 -22
- package/android/src/main/java/net/siteed/audiostream/AudioFormatUtils.kt +24 -0
- package/android/src/main/java/net/siteed/audiostream/AudioProcessor.kt +836 -386
- package/android/src/main/java/net/siteed/audiostream/AudioRecorderManager.kt +0 -2
- package/android/src/main/java/net/siteed/audiostream/AudioRecordingService.kt +35 -29
- package/android/src/main/java/net/siteed/audiostream/ExpoAudioStreamModule.kt +236 -96
- package/android/src/main/java/net/siteed/audiostream/FFT.kt +55 -0
- package/android/src/main/java/net/siteed/audiostream/Features.kt +49 -7
- package/android/src/main/java/net/siteed/audiostream/RecordingConfig.kt +2 -4
- package/build/AudioAnalysis/AudioAnalysis.types.d.ts +55 -47
- package/build/AudioAnalysis/AudioAnalysis.types.d.ts.map +1 -1
- package/build/AudioAnalysis/AudioAnalysis.types.js.map +1 -1
- package/build/AudioAnalysis/extractAudioAnalysis.d.ts +60 -13
- package/build/AudioAnalysis/extractAudioAnalysis.d.ts.map +1 -1
- package/build/AudioAnalysis/extractAudioAnalysis.js +147 -162
- package/build/AudioAnalysis/extractAudioAnalysis.js.map +1 -1
- package/build/ExpoAudioStream.types.d.ts +47 -3
- package/build/ExpoAudioStream.types.d.ts.map +1 -1
- package/build/ExpoAudioStream.types.js.map +1 -1
- package/build/ExpoAudioStream.web.d.ts.map +1 -1
- package/build/ExpoAudioStream.web.js +0 -1
- package/build/ExpoAudioStream.web.js.map +1 -1
- package/build/ExpoAudioStreamModule.d.ts.map +1 -1
- package/build/ExpoAudioStreamModule.js +216 -12
- package/build/ExpoAudioStreamModule.js.map +1 -1
- package/build/WebRecorder.web.d.ts +67 -13
- package/build/WebRecorder.web.d.ts.map +1 -1
- package/build/WebRecorder.web.js +177 -173
- package/build/WebRecorder.web.js.map +1 -1
- package/build/index.d.ts +3 -3
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -2
- package/build/index.js.map +1 -1
- package/build/useAudioRecorder.d.ts.map +1 -1
- package/build/useAudioRecorder.js +12 -8
- package/build/useAudioRecorder.js.map +1 -1
- package/build/utils/audioProcessing.d.ts +24 -0
- package/build/utils/audioProcessing.d.ts.map +1 -0
- package/build/utils/audioProcessing.js +133 -0
- package/build/utils/audioProcessing.js.map +1 -0
- package/build/workers/InlineFeaturesExtractor.web.d.ts +1 -1
- package/build/workers/InlineFeaturesExtractor.web.d.ts.map +1 -1
- package/build/workers/InlineFeaturesExtractor.web.js +694 -194
- package/build/workers/InlineFeaturesExtractor.web.js.map +1 -1
- package/build/workers/inlineAudioWebWorker.web.d.ts +1 -1
- package/build/workers/inlineAudioWebWorker.web.d.ts.map +1 -1
- package/build/workers/inlineAudioWebWorker.web.js +3 -2
- package/build/workers/inlineAudioWebWorker.web.js.map +1 -1
- package/ios/AudioAnalysisData.swift +51 -16
- package/ios/AudioProcessingHelpers.swift +710 -26
- package/ios/AudioProcessor.swift +334 -185
- package/ios/AudioStreamManager.swift +2 -3
- package/ios/DataPoint.swift +25 -12
- package/ios/DecodingConfig.swift +47 -0
- package/ios/ExpoAudioStreamModule.swift +187 -103
- package/ios/FFT.swift +62 -0
- package/ios/Features.swift +24 -3
- package/ios/RecordingSettings.swift +7 -7
- package/package.json +2 -1
- package/src/AudioAnalysis/AudioAnalysis.types.ts +68 -52
- package/src/AudioAnalysis/extractAudioAnalysis.ts +223 -219
- package/src/ExpoAudioStream.types.ts +53 -7
- package/src/ExpoAudioStream.web.ts +0 -1
- package/src/ExpoAudioStreamModule.ts +255 -10
- package/src/WebRecorder.web.ts +231 -244
- package/src/index.ts +5 -3
- package/src/useAudioRecorder.tsx +14 -10
- package/src/utils/audioProcessing.ts +205 -0
- package/src/workers/InlineFeaturesExtractor.web.tsx +694 -194
- package/src/workers/inlineAudioWebWorker.web.tsx +3 -2
|
@@ -1 +1 @@
|
|
|
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;
|
|
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"}
|
|
@@ -89,7 +89,6 @@ export class ExpoAudioStreamWeb extends LegacyEventEmitter {
|
|
|
89
89
|
audioContext,
|
|
90
90
|
source,
|
|
91
91
|
recordingConfig,
|
|
92
|
-
audioWorkletUrl: this.audioWorkletUrl,
|
|
93
92
|
emitAudioEventCallback: ({ data, position, compression, }) => {
|
|
94
93
|
// Keep only the latest chunks based on maxBufferSize
|
|
95
94
|
this.audioChunks.push(new Float32Array(data));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudioStream.web.js","sourceRoot":"","sources":["../src/ExpoAudioStream.web.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAWtD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAwB/D,MAAM,OAAO,kBAAmB,SAAQ,kBAAkB;IACtD,cAAc,CAAoB;IAClC,WAAW,CAAgB;IAC3B,WAAW,CAAS;IACpB,QAAQ,CAAS;IACjB,kBAAkB,CAAQ;IAC1B,UAAU,CAAQ;IAClB,iBAAiB,CAAQ;IACzB,WAAW,CAAQ;IACnB,eAAe,CAAQ;IACvB,uBAAuB,CAAQ;IAC/B,eAAe,CAAQ;IACvB,eAAe,CAAQ;IACvB,0BAA0B,CAAQ;IAClC,uBAAuB,CAAQ;IAC/B,UAAU,CAAe;IACzB,SAAS,GAAmB,KAAK,CAAA,CAAC,6BAA6B;IAC/D,eAAe,CAAkB;IACjC,QAAQ,CAAU,CAAC,yBAAyB;IAC5C,eAAe,CAAQ;IACvB,mBAAmB,CAAQ;IAC3B,MAAM,CAAc;IACpB,cAAc,GAAW,CAAC,CAAA;IAC1B,mBAAmB,GAAW,CAAC,CAAA;IACd,aAAa,CAAQ;IAEtC,YAAY,EACR,eAAe,EACf,mBAAmB,EACnB,MAAM,EACN,aAAa,GAAG,GAAG,EAAE,6DAA6D;MAC5D;QACtB,MAAM,gBAAgB,GAAG;YACrB,WAAW,EAAE,GAAG,EAAE;gBACd,kBAAkB;YACtB,CAAC;YACD,eAAe,EAAE,GAAG,EAAE;gBAClB,kBAAkB;YACtB,CAAC;SACJ,CAAA;QACD,KAAK,CAAC,gBAAgB,CAAC,CAAA,CAAC,kDAAkD;QAE1E,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAA;QAC1B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAA;QACrB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAA;QACxB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAA;QACrB,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAA;QAC3B,IAAI,CAAC,UAAU,GAAG,CAAC,CAAA;QACnB,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAA;QAC1B,IAAI,CAAC,WAAW,GAAG,CAAC,CAAA;QACpB,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAA,CAAC,UAAU;QAC7B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAA,CAAC,yBAAyB;QACrD,IAAI,CAAC,uBAAuB,GAAG,GAAG,CAAA,CAAC,kCAAkC;QACrE,IAAI,CAAC,eAAe,GAAG,CAAC,CAAA;QACxB,IAAI,CAAC,eAAe,GAAG,CAAC,CAAA;QACxB,IAAI,CAAC,cAAc,GAAG,CAAC,CAAA;QACvB,IAAI,CAAC,0BAA0B,GAAG,CAAC,CAAA;QACnC,IAAI,CAAC,uBAAuB,GAAG,CAAC,CAAA;QAChC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA,CAAC,2CAA2C;QAClE,IAAI,CAAC,eAAe,GAAG,eAAe,CAAA;QACtC,IAAI,CAAC,mBAAmB,GAAG,mBAAmB,CAAA;QAC9C,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA;IACtC,CAAC;IAED,sCAAsC;IACtC,KAAK,CAAC,cAAc;QAChB,IAAI,CAAC;YACD,OAAO,MAAM,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QACrE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAA;YACxD,MAAM,KAAK,CAAA;QACf,CAAC;IACL,CAAC;IAED,+BAA+B;IAC/B,KAAK,CAAC,cAAc,CAChB,kBAAmC,EAAE;QAErC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAA;QACvD,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,kBAAkB,CAAC;YAC/B,QAAQ,EAAE,eAAe,CAAC,QAAQ,IAAI,WAAW;SACpD,CAAC,CAAA;QAEF,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY;YACzC,6DAA6D;YAC7D,mDAAmD;YACnD,MAAM,CAAC,kBAAkB,CAAC,EAAE,CAAA;QAChC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAA;QAE1C,MAAM,MAAM,GAAG,YAAY,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAA;QAE3D,IAAI,CAAC,cAAc,GAAG,IAAI,WAAW,CAAC;YAClC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,YAAY;YACZ,MAAM;YACN,eAAe;YACf,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,sBAAsB,EAAE,CAAC,EACrB,IAAI,EACJ,QAAQ,EACR,WAAW,GACO,EAAE,EAAE;gBACtB,qDAAqD;gBACrD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,CAAA;gBAC7C,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;oBAC/C,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAA,CAAC,sBAAsB;gBACnD,CAAC;gBACD,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,UAAU,CAAA;gBACnC,IAAI,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAA;gBACpD,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;gBACjC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,WAAW,CAAA;gBACvC,IAAI,CAAC,0BAA0B,GAAG,WAAW,EAAE,IAAI,IAAI,CAAC,CAAA;YAC5D,CAAC;YACD,yBAAyB,EAAE,CAAC,iBAAgC,EAAE,EAAE;gBAC5D,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,wBAAwB,EAAE,iBAAiB,CAAC,CAAA;gBAC7D,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAA;YACjD,CAAC;SACJ,CAAC,CAAA;QACF,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAA;QAChC,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAA;QAE3B,mDAAmD;QACnD,qBAAqB;QACrB,2CAA2C;QAC3C,wCAAwC;QACxC,8BAA8B;QAC9B,YAAY;QAEZ,IAAI,CAAC,WAAW,GAAG,IAAI,CAAA;QACvB,IAAI,CAAC,eAAe,GAAG,eAAe,CAAA;QACtC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACpC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAA;QACnB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAA;QACrB,IAAI,CAAC,eAAe,GAAG,CAAC,CAAA;QACxB,IAAI,CAAC,eAAe,GAAG,CAAC,CAAA;QACxB,IAAI,CAAC,0BAA0B,GAAG,CAAC,CAAA;QACnC,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC,QAAQ,IAAI,IAAI,CAAA;QACvD,IAAI,CAAC,uBAAuB,GAAG,eAAe,CAAC,gBAAgB,IAAI,GAAG,CAAA;QACtE,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAEzC,mEAAmE;QACnE,IAAI,eAAe,CAAC,QAAQ,EAAE,CAAC;YAC3B,kDAAkD;YAClD,IAAI,CAAC,UAAU,GAAG,eAAe,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;QACvE,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAA;QAC3C,CAAC;QAED,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,SAAS,EAAE,CAAA;QACtD,MAAM,YAAY,GAAyB;YACvC,OAAO;YACP,QAAQ,EAAE,SAAS,IAAI,CAAC,SAAS,EAAE;YACnC,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,QAAQ,EAAE,eAAe,CAAC,QAAQ,IAAI,CAAC;YACvC,UAAU,EAAE,eAAe,CAAC,UAAU,IAAI,KAAK;YAC/C,WAAW,EAAE,eAAe,CAAC,WAAW;gBACpC,CAAC,CAAC;oBACI,GAAG,eAAe,CAAC,WAAW;oBAC9B,OAAO,EAAE,eAAe,CAAC,WAAW,EAAE,OAAO,IAAI,MAAM;oBACvD,IAAI,EAAE,CAAC;oBACP,QAAQ,EAAE,YAAY;oBACtB,MAAM,EAAE,eAAe,CAAC,WAAW,EAAE,MAAM,IAAI,MAAM;oBACrD,iBAAiB,EAAE,EAAE;iBACxB;gBACH,CAAC,CAAC,SAAS;SAClB,CAAA;QACD,OAAO,YAAY,CAAA;IACvB,CAAC;IAED,cAAc,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAuB;QAC/D,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,SAAS,EAAE,CAAA;QACtD,IAAI,WAAW,EAAE,IAAI,EAAE,CAAC;YACpB,IAAI,CAAC,0BAA0B,GAAG,WAAW,CAAC,IAAI,CAAA;YAClD,IAAI,CAAC,mBAAmB,GAAG,WAAW,CAAC,SAAS,CAAA;QACpD,CAAC;QACD,IAAI,CAAC,cAAc,GAAG,QAAQ,CAAA;QAC9B,IAAI,CAAC,iBAAiB,GAAG,QAAQ,GAAG,IAAI,CAAA,CAAC,sCAAsC;QAE/E,MAAM,iBAAiB,GAAsB;YACzC,OAAO;YACP,QAAQ,EAAE,SAAS,IAAI,CAAC,SAAS,EAAE;YACnC,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,SAAS,EAAE,IAAI,CAAC,UAAU;YAC1B,QAAQ;YACR,SAAS,EAAE,IAAI,CAAC,WAAW;YAC3B,MAAM,EAAE,IAAI;YACZ,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,EAAE;YACjC,WAAW,EAAE,WAAW;gBACpB,CAAC,CAAC;oBACI,IAAI,EAAE,WAAW,EAAE,IAAI;oBACvB,SAAS,EAAE,IAAI,CAAC,mBAAmB;oBACnC,aAAa,EAAE,WAAW,EAAE,IAAI,IAAI,CAAC;oBACrC,QAAQ;iBACX;gBACH,CAAC,CAAC,SAAS;SAClB,CAAA;QAED,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAA;IAC7C,CAAC;IAED,iBAAiB;IACjB,KAAK,CAAC,aAAa;QACf,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;QAClD,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,8BAA8B,CAAC,CAAA;QAClD,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;QAEnC,IAAI,CAAC;YACD,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,0BAA0B,CAAC,CAAA;YAC9C,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAA;YAE3D,IAAI,CAAC,WAAW,GAAG,KAAK,CAAA;YACxB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAA;YACrB,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,kBAAkB,CAAA;YAE7D,IAAI,WAA0C,CAAA;YAC9C,IAAI,OAAO,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,SAAS,EAAE,CAAA;YACpD,IAAI,QAAQ,GAAG,SAAS,IAAI,CAAC,SAAS,EAAE,CAAA;YAExC,IAAI,cAAc,IAAI,IAAI,CAAC,eAAe,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;gBAC/D,MAAM,aAAa,GAAG,GAAG,CAAC,eAAe,CAAC,cAAc,CAAC,CAAA;gBACzD,WAAW,GAAG;oBACV,iBAAiB,EAAE,aAAa;oBAChC,IAAI,EAAE,cAAc,CAAC,IAAI;oBACzB,QAAQ,EAAE,YAAY;oBACtB,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,OAAO,IAAI,MAAM;iBAC9D,CAAA;gBACD,oDAAoD;gBACpD,OAAO,GAAG,aAAa,CAAA;gBACvB,QAAQ,GAAG,YAAY,CAAA;YAC3B,CAAC;YAED,IAAI,CAAC,MAAM,EAAE,KAAK,CACd,oCAAoC,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,IAAI,EACrE;gBACI,UAAU,EAAE,IAAI,CAAC,iBAAiB;gBAClC,cAAc,EAAE,WAAW,EAAE,IAAI;aACpC,CACJ,CAAA;YAED,wFAAwF;YACxF,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,SAAS,EAAE,CAAA;YACvD,MAAM,MAAM,GAAmB;gBAC3B,OAAO;gBACP,QAAQ,EAAE,wCAAwC;gBAClD,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,SAAS,EAAE,IAAI,CAAC,kBAAkB;gBAClC,QAAQ,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,IAAI,CAAC;gBAC7C,UAAU,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,IAAI,KAAK;gBACrD,UAAU,EAAE,IAAI,CAAC,iBAAiB;gBAClC,IAAI,EAAE,IAAI,CAAC,WAAW;gBACtB,QAAQ;gBACR,WAAW;aACd,CAAA;YAED,kCAAkC;YAClC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;YAEtB,OAAO,MAAM,CAAA;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAA;YAC7D,MAAM,KAAK,CAAA;QACf,CAAC;IACL,CAAC;IAED,kBAAkB;IAClB,KAAK,CAAC,cAAc;QAChB,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;QAChE,CAAC;QAED,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAA;QAC/B,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;QACpB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAChC,CAAC;IAED,mBAAmB;IACnB,KAAK,CAAC,eAAe;QACjB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAA;QAC9C,CAAC;QAED,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,CAAA;QAChC,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAA;QACrB,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,CAAA;IAC3D,CAAC;IAED,qBAAqB;IACrB,MAAM;QACF,MAAM,MAAM,GAAsB;YAC9B,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,UAAU,EAAE,IAAI,CAAC,iBAAiB;YAClC,IAAI,EAAE,IAAI,CAAC,WAAW;YACtB,QAAQ,EAAE,IAAI,CAAC,eAAe;YAC9B,gBAAgB,EAAE,IAAI,CAAC,uBAAuB;YAC9C,QAAQ,EAAE,SAAS,IAAI,CAAC,SAAS,EAAE;YACnC,WAAW,EAAE,IAAI,CAAC,eAAe,EAAE,WAAW,EAAE,OAAO;gBACnD,CAAC,CAAC;oBACI,IAAI,EAAE,IAAI,CAAC,mBAAmB;oBAC9B,QAAQ,EAAE,YAAY;oBACtB,MAAM,EAAE,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,MAAM,IAAI,MAAM;oBACzD,OAAO,EACH,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,OAAO,IAAI,MAAM;oBACtD,iBAAiB,EAAE,GAAG,IAAI,CAAC,UAAU,OAAO;iBAC/C;gBACH,CAAC,CAAC,SAAS;SAClB,CAAA;QACD,OAAO,MAAM,CAAA;IACjB,CAAC;CACJ","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 audioWorkletUrl: this.audioWorkletUrl,\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
|
+
{"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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudioStreamModule.d.ts","sourceRoot":"","sources":["../src/ExpoAudioStreamModule.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ExpoAudioStreamModule.d.ts","sourceRoot":"","sources":["../src/ExpoAudioStreamModule.ts"],"names":[],"mappings":"AAiBA,QAAA,IAAI,qBAAqB,EAAE,GAAG,CAAA;AA4Q9B,eAAe,qBAAqB,CAAA"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import crc32 from 'crc-32';
|
|
1
2
|
import { requireNativeModule } from 'expo-modules-core';
|
|
2
3
|
import { Platform } from 'react-native';
|
|
3
4
|
import { ExpoAudioStreamWeb, } from './ExpoAudioStream.web';
|
|
5
|
+
import { processAudioBuffer } from './utils/audioProcessing';
|
|
6
|
+
import { writeWavHeader } from './utils/writeWavHeader';
|
|
4
7
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
8
|
let ExpoAudioStreamModule;
|
|
6
9
|
if (Platform.OS === 'web') {
|
|
@@ -12,20 +15,221 @@ if (Platform.OS === 'web') {
|
|
|
12
15
|
return instance;
|
|
13
16
|
};
|
|
14
17
|
ExpoAudioStreamModule.requestPermissionsAsync = async () => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
try {
|
|
19
|
+
const stream = await navigator.mediaDevices.getUserMedia({
|
|
20
|
+
audio: true,
|
|
21
|
+
});
|
|
22
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
23
|
+
return {
|
|
24
|
+
status: 'granted',
|
|
25
|
+
expires: 'never',
|
|
26
|
+
canAskAgain: true,
|
|
27
|
+
granted: true,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return {
|
|
32
|
+
status: 'denied',
|
|
33
|
+
expires: 'never',
|
|
34
|
+
canAskAgain: true,
|
|
35
|
+
granted: false,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
21
38
|
};
|
|
22
39
|
ExpoAudioStreamModule.getPermissionsAsync = async () => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
40
|
+
let maybeStatus = null;
|
|
41
|
+
if (navigator?.permissions?.query) {
|
|
42
|
+
try {
|
|
43
|
+
const { state } = await navigator.permissions.query({
|
|
44
|
+
name: 'microphone',
|
|
45
|
+
});
|
|
46
|
+
maybeStatus = state;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
maybeStatus = null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
switch (maybeStatus) {
|
|
53
|
+
case 'granted':
|
|
54
|
+
return {
|
|
55
|
+
status: 'granted',
|
|
56
|
+
expires: 'never',
|
|
57
|
+
canAskAgain: true,
|
|
58
|
+
granted: true,
|
|
59
|
+
};
|
|
60
|
+
case 'denied':
|
|
61
|
+
return {
|
|
62
|
+
status: 'denied',
|
|
63
|
+
expires: 'never',
|
|
64
|
+
canAskAgain: true,
|
|
65
|
+
granted: false,
|
|
66
|
+
};
|
|
67
|
+
default:
|
|
68
|
+
return await ExpoAudioStreamModule.requestPermissionsAsync();
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
ExpoAudioStreamModule.extractAudioData = async (options) => {
|
|
72
|
+
try {
|
|
73
|
+
const { fileUri, position, length, startTimeMs, endTimeMs, decodingOptions, includeNormalizedData, includeBase64Data, includeWavHeader = false, logger, } = options;
|
|
74
|
+
logger?.debug('EXTRACT AUDIO - Step 1: Initial request', {
|
|
75
|
+
fileUri,
|
|
76
|
+
extractionParams: {
|
|
77
|
+
position,
|
|
78
|
+
length,
|
|
79
|
+
startTimeMs,
|
|
80
|
+
endTimeMs,
|
|
81
|
+
},
|
|
82
|
+
decodingOptions: {
|
|
83
|
+
targetSampleRate: decodingOptions?.targetSampleRate ?? 16000,
|
|
84
|
+
targetChannels: decodingOptions?.targetChannels ?? 1,
|
|
85
|
+
targetBitDepth: decodingOptions?.targetBitDepth ?? 16,
|
|
86
|
+
normalizeAudio: decodingOptions?.normalizeAudio ?? false,
|
|
87
|
+
},
|
|
88
|
+
outputOptions: {
|
|
89
|
+
includeNormalizedData,
|
|
90
|
+
includeBase64Data,
|
|
91
|
+
includeWavHeader,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
// Process the audio using shared helper function
|
|
95
|
+
const processedBuffer = await processAudioBuffer({
|
|
96
|
+
fileUri,
|
|
97
|
+
targetSampleRate: decodingOptions?.targetSampleRate ?? 16000,
|
|
98
|
+
targetChannels: decodingOptions?.targetChannels ?? 1,
|
|
99
|
+
normalizeAudio: decodingOptions?.normalizeAudio ?? false,
|
|
100
|
+
position,
|
|
101
|
+
length,
|
|
102
|
+
startTimeMs,
|
|
103
|
+
endTimeMs,
|
|
104
|
+
logger,
|
|
105
|
+
});
|
|
106
|
+
logger?.debug('EXTRACT AUDIO - Step 2: Audio processing complete', {
|
|
107
|
+
processedData: {
|
|
108
|
+
samples: processedBuffer.samples,
|
|
109
|
+
sampleRate: processedBuffer.sampleRate,
|
|
110
|
+
channels: processedBuffer.channels,
|
|
111
|
+
durationMs: processedBuffer.durationMs,
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
const channelData = processedBuffer.channelData;
|
|
115
|
+
const bitDepth = (decodingOptions?.targetBitDepth ?? 16);
|
|
116
|
+
const bytesPerSample = bitDepth / 8;
|
|
117
|
+
const numSamples = processedBuffer.samples;
|
|
118
|
+
logger?.debug('EXTRACT AUDIO - Step 3: PCM conversion setup', {
|
|
119
|
+
channelData: {
|
|
120
|
+
length: channelData.length,
|
|
121
|
+
first: channelData[0],
|
|
122
|
+
last: channelData[channelData.length - 1],
|
|
123
|
+
},
|
|
124
|
+
calculation: {
|
|
125
|
+
bitDepth,
|
|
126
|
+
bytesPerSample,
|
|
127
|
+
numSamples,
|
|
128
|
+
expectedBytes: numSamples * bytesPerSample,
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
// Create PCM data with correct length based on original byte length
|
|
132
|
+
const pcmData = new Uint8Array(numSamples * bytesPerSample);
|
|
133
|
+
let offset = 0;
|
|
134
|
+
// Convert Float32 samples to PCM format
|
|
135
|
+
for (let i = 0; i < numSamples; i++) {
|
|
136
|
+
const sample = channelData[i];
|
|
137
|
+
const value = Math.max(-1, Math.min(1, sample));
|
|
138
|
+
// Convert to 16-bit signed integer
|
|
139
|
+
let intValue = Math.round(value * 32767);
|
|
140
|
+
// Handle negative values correctly
|
|
141
|
+
if (intValue < 0) {
|
|
142
|
+
intValue = 65536 + intValue;
|
|
143
|
+
}
|
|
144
|
+
// Write as little-endian
|
|
145
|
+
pcmData[offset++] = intValue & 255; // Low byte
|
|
146
|
+
pcmData[offset++] = (intValue >> 8) & 255; // High byte
|
|
147
|
+
}
|
|
148
|
+
const durationMs = Math.round((numSamples / processedBuffer.sampleRate) * 1000);
|
|
149
|
+
logger?.debug('EXTRACT AUDIO - Step 4: Final output', {
|
|
150
|
+
pcmData: {
|
|
151
|
+
length: pcmData.length,
|
|
152
|
+
first: pcmData[0],
|
|
153
|
+
last: pcmData[pcmData.length - 1],
|
|
154
|
+
},
|
|
155
|
+
timing: {
|
|
156
|
+
numSamples,
|
|
157
|
+
sampleRate: processedBuffer.sampleRate,
|
|
158
|
+
durationMs,
|
|
159
|
+
shouldBe3000ms: endTimeMs
|
|
160
|
+
? endTimeMs - (startTimeMs ?? 0) === 3000
|
|
161
|
+
: undefined,
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
const result = {
|
|
165
|
+
pcmData: new Uint8Array(pcmData.buffer),
|
|
166
|
+
sampleRate: processedBuffer.sampleRate,
|
|
167
|
+
channels: processedBuffer.channels,
|
|
168
|
+
bitDepth,
|
|
169
|
+
durationMs,
|
|
170
|
+
format: `pcm_${bitDepth}bit`,
|
|
171
|
+
samples: numSamples,
|
|
172
|
+
};
|
|
173
|
+
// Add WAV header if requested
|
|
174
|
+
if (includeWavHeader) {
|
|
175
|
+
logger?.debug('EXTRACT AUDIO - Step 4: Adding WAV header', {
|
|
176
|
+
originalLength: pcmData.length,
|
|
177
|
+
newLength: result.pcmData.length,
|
|
178
|
+
firstBytes: Array.from(result.pcmData.slice(0, 44)), // WAV header is 44 bytes
|
|
179
|
+
});
|
|
180
|
+
const wavBuffer = writeWavHeader({
|
|
181
|
+
buffer: pcmData.buffer.slice(0, pcmData.length),
|
|
182
|
+
sampleRate: processedBuffer.sampleRate,
|
|
183
|
+
numChannels: processedBuffer.channels,
|
|
184
|
+
bitDepth,
|
|
185
|
+
});
|
|
186
|
+
result.pcmData = new Uint8Array(wavBuffer);
|
|
187
|
+
result.hasWavHeader = true;
|
|
188
|
+
}
|
|
189
|
+
if (includeNormalizedData) {
|
|
190
|
+
// // Simple approach: Create normalized data directly from the PCM data
|
|
191
|
+
// // Just convert to -1 to 1 range without any amplification
|
|
192
|
+
// const normalizedData = new Float32Array(numSamples)
|
|
193
|
+
// // Convert the PCM data to float values
|
|
194
|
+
// for (let i = 0; i < numSamples; i++) {
|
|
195
|
+
// // Get the 16-bit PCM value (little endian)
|
|
196
|
+
// const lowByte = pcmData[i * 2]
|
|
197
|
+
// const highByte = pcmData[i * 2 + 1]
|
|
198
|
+
// const pcmValue = (highByte << 8) | lowByte
|
|
199
|
+
// // Convert to signed 16-bit value
|
|
200
|
+
// const signedValue =
|
|
201
|
+
// pcmValue > 32767 ? pcmValue - 65536 : pcmValue
|
|
202
|
+
// // Normalize to float between -1 and 1
|
|
203
|
+
// normalizedData[i] = signedValue / 32768.0
|
|
204
|
+
// }
|
|
205
|
+
// Store the normalized data in the result
|
|
206
|
+
result.normalizedData = channelData;
|
|
207
|
+
}
|
|
208
|
+
if (includeBase64Data) {
|
|
209
|
+
// Convert the PCM data to a base64 string
|
|
210
|
+
const binary = Array.from(new Uint8Array(pcmData.buffer))
|
|
211
|
+
.map((b) => String.fromCharCode(b))
|
|
212
|
+
.join('');
|
|
213
|
+
result.base64Data = btoa(binary);
|
|
214
|
+
}
|
|
215
|
+
if (options.computeChecksum) {
|
|
216
|
+
result.checksum = crc32.buf(pcmData);
|
|
217
|
+
}
|
|
218
|
+
logger?.debug('EXTRACT AUDIO - Step 3: PCM conversion complete', {
|
|
219
|
+
pcmStats: {
|
|
220
|
+
length: pcmData.length,
|
|
221
|
+
bytesPerSample,
|
|
222
|
+
totalSamples: numSamples,
|
|
223
|
+
firstBytes: Array.from(pcmData.slice(0, 16)),
|
|
224
|
+
lastBytes: Array.from(pcmData.slice(-16)),
|
|
225
|
+
},
|
|
226
|
+
});
|
|
227
|
+
return result;
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
options.logger?.error('EXTRACT AUDIO - Error:', error);
|
|
231
|
+
throw error;
|
|
232
|
+
}
|
|
29
233
|
};
|
|
30
234
|
}
|
|
31
235
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudioStreamModule.js","sourceRoot":"","sources":["../src/ExpoAudioStreamModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEvC,OAAO,EACH,kBAAkB,GAErB,MAAM,uBAAuB,CAAA;AAE9B,8DAA8D;AAC9D,IAAI,qBAA0B,CAAA;AAE9B,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;IACxB,IAAI,QAAQ,GAA8B,IAAI,CAAA;IAE9C,qBAAqB,GAAG,CAAC,QAAiC,EAAE,EAAE;QAC1D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,QAAQ,GAAG,IAAI,kBAAkB,CAAC,QAAQ,CAAC,CAAA;QAC/C,CAAC;QACD,OAAO,QAAQ,CAAA;IACnB,CAAC,CAAA;IACD,qBAAqB,CAAC,uBAAuB,GAAG,KAAK,IAAI,EAAE;QACvD,OAAO;YACH,MAAM,EAAE,SAAS;YACjB,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,OAAO;YAChB,WAAW,EAAE,IAAI;SACpB,CAAA;IACL,CAAC,CAAA;IACD,qBAAqB,CAAC,mBAAmB,GAAG,KAAK,IAAI,EAAE;QACnD,OAAO;YACH,MAAM,EAAE,SAAS;YACjB,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,OAAO;YAChB,WAAW,EAAE,IAAI;SACpB,CAAA;IACL,CAAC,CAAA;AACL,CAAC;KAAM,CAAC;IACJ,qBAAqB,GAAG,mBAAmB,CAAC,iBAAiB,CAAC,CAAA;AAClE,CAAC;AAED,eAAe,qBAAqB,CAAA","sourcesContent":["import { requireNativeModule } from 'expo-modules-core'\nimport { Platform } from 'react-native'\n\nimport {\n ExpoAudioStreamWeb,\n ExpoAudioStreamWebProps,\n} from './ExpoAudioStream.web'\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 return {\n status: 'granted',\n granted: true,\n expires: 'never',\n canAskAgain: true,\n }\n }\n ExpoAudioStreamModule.getPermissionsAsync = async () => {\n return {\n status: 'granted',\n granted: true,\n expires: 'never',\n canAskAgain: true,\n }\n }\n} else {\n ExpoAudioStreamModule = requireNativeModule('ExpoAudioStream')\n}\n\nexport default ExpoAudioStreamModule\n"]}
|
|
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"]}
|
|
@@ -12,7 +12,6 @@ export declare class WebRecorder {
|
|
|
12
12
|
private audioWorkletNode;
|
|
13
13
|
private featureExtractorWorker?;
|
|
14
14
|
private source;
|
|
15
|
-
private audioWorkletUrl;
|
|
16
15
|
private emitAudioEventCallback;
|
|
17
16
|
private emitAudioAnalysisCallback;
|
|
18
17
|
private config;
|
|
@@ -28,38 +27,93 @@ export declare class WebRecorder {
|
|
|
28
27
|
private compressedSize;
|
|
29
28
|
private pendingCompressedChunk;
|
|
30
29
|
private readonly wavMimeType;
|
|
31
|
-
|
|
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, }: {
|
|
32
41
|
audioContext: AudioContext;
|
|
33
42
|
source: MediaStreamAudioSourceNode;
|
|
34
43
|
recordingConfig: RecordingConfig;
|
|
35
|
-
audioWorkletUrl: string;
|
|
36
44
|
emitAudioEventCallback: EmitAudioEventFunction;
|
|
37
45
|
emitAudioAnalysisCallback: EmitAudioAnalysisFunction;
|
|
38
46
|
logger?: ConsoleLike;
|
|
39
47
|
});
|
|
48
|
+
/**
|
|
49
|
+
* Initializes the audio worklet using an inline script
|
|
50
|
+
* Creates and connects the audio processing pipeline
|
|
51
|
+
*/
|
|
40
52
|
init(): Promise<void>;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
+
*/
|
|
44
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
|
+
*/
|
|
45
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
|
+
*/
|
|
46
78
|
stop(): Promise<{
|
|
47
79
|
pcmData: Float32Array;
|
|
48
80
|
compressedBlob?: Blob;
|
|
49
81
|
}>;
|
|
82
|
+
/**
|
|
83
|
+
* Cleans up resources when recording is stopped
|
|
84
|
+
* Closes audio context and disconnects nodes
|
|
85
|
+
*/
|
|
50
86
|
private cleanup;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
87
|
+
/**
|
|
88
|
+
* Pauses the audio recording process
|
|
89
|
+
* Disconnects audio nodes and pauses the media recorder
|
|
90
|
+
*/
|
|
54
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
|
+
*/
|
|
55
96
|
stopMediaStreamTracks(): void;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
+
*/
|
|
60
102
|
private checkAudioContextFormat;
|
|
103
|
+
/**
|
|
104
|
+
* Resumes a paused recording
|
|
105
|
+
* Reconnects audio nodes and resumes the media recorder
|
|
106
|
+
*/
|
|
61
107
|
resume(): void;
|
|
108
|
+
/**
|
|
109
|
+
* Initializes the compressed media recorder if compression is enabled
|
|
110
|
+
* Sets up event handlers for compressed audio data
|
|
111
|
+
*/
|
|
62
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;
|
|
63
117
|
}
|
|
64
118
|
export {};
|
|
65
119
|
//# sourceMappingURL=WebRecorder.web.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
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"}
|