@siteed/expo-audio-stream 1.0.1 → 1.0.2
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 +6 -6
- package/android/build.gradle +5 -0
- package/android/src/main/java/net/siteed/audiostream/AudioAnalysisData.kt +120 -0
- package/android/src/main/java/net/siteed/audiostream/AudioFileHandler.kt +34 -4
- package/android/src/main/java/net/siteed/audiostream/AudioProcessor.kt +635 -0
- package/android/src/main/java/net/siteed/audiostream/AudioRecorderManager.kt +194 -79
- package/android/src/main/java/net/siteed/audiostream/Constants.kt +1 -0
- package/android/src/main/java/net/siteed/audiostream/ExpoAudioStreamModule.kt +48 -2
- package/android/src/main/java/net/siteed/audiostream/FFT.kt +44 -0
- package/android/src/main/java/net/siteed/audiostream/Features.kt +56 -0
- package/android/src/main/java/net/siteed/audiostream/RecordingConfig.kt +12 -0
- package/android/src/main/test/java/net/siteed/audiostream/AudioProcessorTest.kt +56 -0
- package/app.plugin.js +1 -1
- package/build/AudioRecorder.provider.js +1 -1
- package/build/AudioRecorder.provider.js.map +1 -1
- package/build/ExpoAudioStream.native.d.ts +3 -0
- package/build/ExpoAudioStream.native.d.ts.map +1 -0
- package/build/ExpoAudioStream.native.js +6 -0
- package/build/ExpoAudioStream.native.js.map +1 -0
- package/build/ExpoAudioStream.types.d.ts +79 -6
- package/build/ExpoAudioStream.types.d.ts.map +1 -1
- package/build/ExpoAudioStream.types.js.map +1 -1
- package/build/ExpoAudioStream.web.d.ts +41 -0
- package/build/ExpoAudioStream.web.d.ts.map +1 -0
- package/build/ExpoAudioStream.web.js +184 -0
- package/build/ExpoAudioStream.web.js.map +1 -0
- package/build/ExpoAudioStreamModule.d.ts +2 -2
- package/build/ExpoAudioStreamModule.d.ts.map +1 -1
- package/build/ExpoAudioStreamModule.js +12 -3
- package/build/ExpoAudioStreamModule.js.map +1 -1
- package/build/WebRecorder.d.ts +47 -0
- package/build/WebRecorder.d.ts.map +1 -0
- package/build/WebRecorder.js +243 -0
- package/build/WebRecorder.js.map +1 -0
- package/build/index.d.ts +14 -5
- package/build/index.d.ts.map +1 -1
- package/build/index.js +106 -7
- package/build/index.js.map +1 -1
- package/build/inlineAudioWebWorker.d.ts +3 -0
- package/build/inlineAudioWebWorker.d.ts.map +1 -0
- package/build/inlineAudioWebWorker.js +340 -0
- package/build/inlineAudioWebWorker.js.map +1 -0
- package/build/useAudioRecording.d.ts +24 -9
- package/build/useAudioRecording.d.ts.map +1 -1
- package/build/useAudioRecording.js +107 -29
- package/build/useAudioRecording.js.map +1 -1
- package/build/utils.d.ts +31 -0
- package/build/utils.d.ts.map +1 -0
- package/build/utils.js +143 -0
- package/build/utils.js.map +1 -0
- package/expo-module.config.json +13 -4
- package/ios/AudioAnalysisData.swift +39 -0
- package/ios/AudioProcessingHelpers.swift +59 -0
- package/ios/AudioProcessor.swift +317 -0
- package/ios/AudioStreamError.swift +7 -0
- package/ios/AudioStreamManager.swift +204 -52
- package/ios/AudioStreamManagerDelegate.swift +4 -0
- package/ios/DataPoint.swift +41 -0
- package/ios/ExpoAudioStreamModule.swift +188 -6
- package/ios/Features.swift +44 -0
- package/ios/RecordingResult.swift +19 -0
- package/ios/RecordingSettings.swift +13 -0
- package/ios/WaveformExtractor.swift +105 -0
- package/package.json +9 -9
- package/plugin/tsconfig.json +13 -8
- package/publish.sh +8 -0
- package/src/AudioRecorder.provider.tsx +1 -1
- package/src/ExpoAudioStream.native.ts +6 -0
- package/src/ExpoAudioStream.types.ts +97 -11
- package/src/ExpoAudioStream.web.ts +228 -0
- package/src/ExpoAudioStreamModule.ts +17 -3
- package/src/WebRecorder.ts +364 -0
- package/src/index.ts +166 -20
- package/src/inlineAudioWebWorker.tsx +340 -0
- package/src/useAudioRecording.tsx +410 -0
- package/src/utils.ts +189 -0
- package/build/ExpoAudioStreamModule.web.d.ts +0 -37
- package/build/ExpoAudioStreamModule.web.d.ts.map +0 -1
- package/build/ExpoAudioStreamModule.web.js +0 -156
- package/build/ExpoAudioStreamModule.web.js.map +0 -1
- package/docs/demo.gif +0 -0
- package/release-it.js +0 -18
- package/src/ExpoAudioStreamModule.web.ts +0 -181
- package/src/useAudioRecording.ts +0 -268
- package/yarn-error.log +0 -7793
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
package net.siteed.audiostream
|
|
2
|
+
|
|
3
|
+
import org.junit.Test
|
|
4
|
+
import org.junit.Assert.*
|
|
5
|
+
|
|
6
|
+
class AudioProcessorTest {
|
|
7
|
+
|
|
8
|
+
private val sampleRate = 44100
|
|
9
|
+
private val channels = 1
|
|
10
|
+
private val encoding = "pcm_16bit"
|
|
11
|
+
private val pointsPerSecond = 1000
|
|
12
|
+
private val algorithm = "rms"
|
|
13
|
+
private val features = mapOf("rms" to true, "zcr" to true)
|
|
14
|
+
|
|
15
|
+
private val recordingConfig = RecordingConfig(
|
|
16
|
+
sampleRate = sampleRate,
|
|
17
|
+
channels = channels,
|
|
18
|
+
encoding = encoding,
|
|
19
|
+
interval = 1000,
|
|
20
|
+
enableProcessing = true,
|
|
21
|
+
pointsPerSecond = pointsPerSecond,
|
|
22
|
+
algorithm = algorithm,
|
|
23
|
+
features = features
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
private val audioProcessor = AudioProcessor()
|
|
27
|
+
|
|
28
|
+
@Test
|
|
29
|
+
fun testProcessAudioData() {
|
|
30
|
+
val data = generateSineWave(440.0, sampleRate, 2.0)
|
|
31
|
+
|
|
32
|
+
val result = audioProcessor.processAudioData(data, recordingConfig)
|
|
33
|
+
|
|
34
|
+
assertNotNull(result)
|
|
35
|
+
assertEquals(pointsPerSecond, result.pointsPerSecond)
|
|
36
|
+
assertEquals((data.size / sampleRate) * 1000, result.durationMs.toInt())
|
|
37
|
+
assertEquals(16, result.bitDepth)
|
|
38
|
+
assertEquals(channels, result.numberOfChannels)
|
|
39
|
+
assertEquals(sampleRate, result.sampleRate.toInt())
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Helper function to generate a sine wave
|
|
43
|
+
private fun generateSineWave(frequency: Double, sampleRate: Int, durationSeconds: Double): ByteArray {
|
|
44
|
+
val numSamples = (sampleRate * durationSeconds).toInt()
|
|
45
|
+
val output = ByteArray(numSamples * 2) // 16-bit PCM
|
|
46
|
+
|
|
47
|
+
for (i in 0 until numSamples) {
|
|
48
|
+
val time = i / sampleRate.toDouble()
|
|
49
|
+
val amplitude = (Math.sin(2.0 * Math.PI * frequency * time) * 32767).toInt()
|
|
50
|
+
output[i * 2] = (amplitude and 0xff).toByte()
|
|
51
|
+
output[i * 2 + 1] = ((amplitude shr 8) and 0xff).toByte()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return output
|
|
55
|
+
}
|
|
56
|
+
}
|
package/app.plugin.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
module.exports = require(
|
|
1
|
+
module.exports = require("./plugin/build");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioRecorder.provider.js","sourceRoot":"","sources":["../src/AudioRecorder.provider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAEzD,OAAO,EAGL,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,oBAAoB,GAAG,aAAa,CAAwB;IAChE,WAAW,EAAE,KAAK;IAClB,QAAQ,EAAE,KAAK;IACf,
|
|
1
|
+
{"version":3,"file":"AudioRecorder.provider.js","sourceRoot":"","sources":["../src/AudioRecorder.provider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAEzD,OAAO,EAGL,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,oBAAoB,GAAG,aAAa,CAAwB;IAChE,WAAW,EAAE,KAAK;IAClB,QAAQ,EAAE,KAAK;IACf,UAAU,EAAE,CAAC;IACb,IAAI,EAAE,CAAC;IACP,8CAA8C;CACtB,CAAC,CAAC;AAO5B,MAAM,CAAC,MAAM,qBAAqB,GAAyC,CAAC,EAC1E,QAAQ,EACR,MAAM,GAAG,EAAE,GACZ,EAAE,EAAE;IACH,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAC/C,OAAO,CACL,CAAC,oBAAoB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,CAClD;MAAA,CAAC,QAAQ,CACX;IAAA,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CACjC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,EAAE;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,oBAAoB,CAAC,CAAC;IACjD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,qEAAqE,CACtE,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC","sourcesContent":["import React, { createContext, useContext } from \"react\";\n\nimport {\n UseAudioRecorderProps,\n UseAudioRecorderState,\n useAudioRecorder,\n} from \"./useAudioRecording\";\n\nconst AudioRecorderContext = createContext<UseAudioRecorderState>({\n isRecording: false,\n isPaused: false,\n durationMs: 0,\n size: 0,\n // other properties filled on useAudioRecorder\n} as UseAudioRecorderState);\n\ninterface AudioRecorderProviderProps {\n children: React.ReactNode;\n config?: UseAudioRecorderProps;\n}\n\nexport const AudioRecorderProvider: React.FC<AudioRecorderProviderProps> = ({\n children,\n config = {},\n}) => {\n const audioRecorder = useAudioRecorder(config);\n return (\n <AudioRecorderContext.Provider value={audioRecorder}>\n {children}\n </AudioRecorderContext.Provider>\n );\n};\n\nexport const useSharedAudioRecorder = () => {\n const context = useContext(AudioRecorderContext);\n if (!context) {\n throw new Error(\n \"useSharedAudioRecorder must be used within an AudioRecorderProvider\",\n );\n }\n return context;\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoAudioStream.native.d.ts","sourceRoot":"","sources":["../src/ExpoAudioStream.native.ts"],"names":[],"mappings":";AAKA,wBAAsD"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// src/ExpoAudioStreamModule.ts
|
|
2
|
+
import { requireNativeModule } from "expo-modules-core";
|
|
3
|
+
// It loads the native module object from the JSI or falls back to
|
|
4
|
+
// the bridge module (from NativeModulesProxy) if the remote debugger is on.
|
|
5
|
+
export default requireNativeModule("ExpoAudioStream");
|
|
6
|
+
//# sourceMappingURL=ExpoAudioStream.native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoAudioStream.native.js","sourceRoot":"","sources":["../src/ExpoAudioStream.native.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,kEAAkE;AAClE,4EAA4E;AAC5E,eAAe,mBAAmB,CAAC,iBAAiB,CAAC,CAAC","sourcesContent":["// src/ExpoAudioStreamModule.ts\nimport { requireNativeModule } from \"expo-modules-core\";\n\n// It loads the native module object from the JSI or falls back to\n// the bridge module (from NativeModulesProxy) if the remote debugger is on.\nexport default requireNativeModule(\"ExpoAudioStream\");\n"]}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { AudioDataEvent } from "./useAudioRecording";
|
|
2
1
|
export interface AudioEventPayload {
|
|
3
2
|
encoded?: string;
|
|
4
|
-
buffer?:
|
|
3
|
+
buffer?: ArrayBuffer;
|
|
5
4
|
fileUri: string;
|
|
6
5
|
lastEmittedSize: number;
|
|
7
6
|
position: number;
|
|
@@ -12,7 +11,8 @@ export interface AudioEventPayload {
|
|
|
12
11
|
}
|
|
13
12
|
export interface AudioStreamResult {
|
|
14
13
|
fileUri: string;
|
|
15
|
-
|
|
14
|
+
webAudioUri?: string;
|
|
15
|
+
durationMs: number;
|
|
16
16
|
size: number;
|
|
17
17
|
mimeType: string;
|
|
18
18
|
channels?: number;
|
|
@@ -29,17 +29,90 @@ export interface StartAudioStreamResult {
|
|
|
29
29
|
export interface AudioStreamStatus {
|
|
30
30
|
isRecording: boolean;
|
|
31
31
|
isPaused: boolean;
|
|
32
|
-
|
|
32
|
+
durationMs: number;
|
|
33
33
|
size: number;
|
|
34
34
|
interval: number;
|
|
35
35
|
mimeType: string;
|
|
36
36
|
}
|
|
37
|
-
export
|
|
37
|
+
export interface AudioDataEvent {
|
|
38
|
+
data: string | ArrayBuffer;
|
|
39
|
+
position: number;
|
|
40
|
+
fileUri: string;
|
|
41
|
+
eventDataSize: number;
|
|
42
|
+
totalSize: number;
|
|
43
|
+
}
|
|
44
|
+
export interface AudioFeatures {
|
|
45
|
+
energy: number;
|
|
46
|
+
mfcc: number[];
|
|
47
|
+
rms: number;
|
|
48
|
+
minAmplitude: number;
|
|
49
|
+
maxAmplitude: number;
|
|
50
|
+
zcr: number;
|
|
51
|
+
spectralCentroid: number;
|
|
52
|
+
spectralFlatness: number;
|
|
53
|
+
spectralRolloff: number;
|
|
54
|
+
spectralBandwidth: number;
|
|
55
|
+
chromagram: number[];
|
|
56
|
+
tempo: number;
|
|
57
|
+
hnr: number;
|
|
58
|
+
}
|
|
59
|
+
export interface AudioFeaturesOptions {
|
|
60
|
+
energy?: boolean;
|
|
61
|
+
mfcc?: boolean;
|
|
62
|
+
rms?: boolean;
|
|
63
|
+
zcr?: boolean;
|
|
64
|
+
spectralCentroid?: boolean;
|
|
65
|
+
spectralFlatness?: boolean;
|
|
66
|
+
spectralRolloff?: boolean;
|
|
67
|
+
spectralBandwidth?: boolean;
|
|
68
|
+
chromagram?: boolean;
|
|
69
|
+
tempo?: boolean;
|
|
70
|
+
hnr?: boolean;
|
|
71
|
+
}
|
|
72
|
+
export interface DataPoint {
|
|
73
|
+
id: number;
|
|
74
|
+
amplitude: number;
|
|
75
|
+
activeSpeech?: boolean;
|
|
76
|
+
dB?: number;
|
|
77
|
+
silent?: boolean;
|
|
78
|
+
features?: AudioFeatures;
|
|
79
|
+
startTime?: number;
|
|
80
|
+
endTime?: number;
|
|
81
|
+
startPosition?: number;
|
|
82
|
+
endPosition?: number;
|
|
83
|
+
samples?: number;
|
|
84
|
+
speaker?: number;
|
|
85
|
+
}
|
|
86
|
+
export interface AudioAnalysisData {
|
|
87
|
+
pointsPerSecond: number;
|
|
88
|
+
durationMs: number;
|
|
89
|
+
bitDepth: number;
|
|
90
|
+
samples: number;
|
|
91
|
+
numberOfChannels: number;
|
|
92
|
+
sampleRate: number;
|
|
93
|
+
dataPoints: DataPoint[];
|
|
94
|
+
amplitudeRange: {
|
|
95
|
+
min: number;
|
|
96
|
+
max: number;
|
|
97
|
+
};
|
|
98
|
+
speakerChanges?: {
|
|
99
|
+
timestamp: number;
|
|
100
|
+
speaker: number;
|
|
101
|
+
}[];
|
|
102
|
+
}
|
|
103
|
+
export type EncodingType = "pcm_32bit" | "pcm_16bit" | "pcm_8bit";
|
|
104
|
+
export type SampleRate = 16000 | 44100 | 48000;
|
|
38
105
|
export interface RecordingConfig {
|
|
39
|
-
sampleRate?:
|
|
106
|
+
sampleRate?: SampleRate;
|
|
40
107
|
channels?: 1 | 2;
|
|
41
108
|
encoding?: EncodingType;
|
|
42
109
|
interval?: number;
|
|
110
|
+
maxRecentDataDuration?: number;
|
|
111
|
+
enableProcessing?: boolean;
|
|
112
|
+
pointsPerSecond?: number;
|
|
113
|
+
algorithm?: string;
|
|
114
|
+
features?: AudioFeaturesOptions;
|
|
43
115
|
onAudioStream?: (_: AudioDataEvent) => Promise<void>;
|
|
116
|
+
onProcessingResult?: (_: AudioAnalysisData) => Promise<void>;
|
|
44
117
|
}
|
|
45
118
|
//# sourceMappingURL=ExpoAudioStream.types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudioStream.types.d.ts","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"ExpoAudioStream.types.d.ts","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudioStream.types.js","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"","sourcesContent":["
|
|
1
|
+
{"version":3,"file":"ExpoAudioStream.types.js","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"","sourcesContent":["export interface AudioEventPayload {\n encoded?: string;\n buffer?: ArrayBuffer;\n fileUri: string;\n lastEmittedSize: number;\n position: number;\n deltaSize: number;\n totalSize: number;\n mimeType: string;\n streamUuid: string;\n}\n\nexport interface AudioStreamResult {\n fileUri: string;\n webAudioUri?: string;\n durationMs: number;\n size: number;\n mimeType: string;\n channels?: number;\n bitDepth?: number;\n sampleRate?: number;\n}\n\nexport interface StartAudioStreamResult {\n fileUri: string;\n mimeType: string;\n channels?: number;\n bitDepth?: number;\n sampleRate?: number;\n}\n\nexport interface AudioStreamStatus {\n isRecording: boolean;\n isPaused: boolean;\n durationMs: number;\n size: number;\n interval: number;\n mimeType: string;\n}\n\nexport interface AudioDataEvent {\n data: string | ArrayBuffer;\n position: number;\n fileUri: string;\n eventDataSize: number;\n totalSize: number;\n}\n\nexport interface AudioFeatures {\n energy: number;\n mfcc: number[];\n rms: number;\n minAmplitude: number;\n maxAmplitude: number;\n zcr: number;\n spectralCentroid: number;\n spectralFlatness: number;\n spectralRolloff: number;\n spectralBandwidth: number;\n chromagram: number[];\n tempo: number;\n hnr: number;\n}\n\nexport interface AudioFeaturesOptions {\n energy?: boolean;\n mfcc?: boolean;\n rms?: boolean;\n zcr?: boolean;\n spectralCentroid?: boolean;\n spectralFlatness?: boolean;\n spectralRolloff?: boolean;\n spectralBandwidth?: boolean;\n chromagram?: boolean;\n tempo?: boolean;\n hnr?: boolean;\n}\n\nexport interface DataPoint {\n id: number;\n amplitude: number;\n activeSpeech?: boolean;\n dB?: number;\n silent?: boolean;\n features?: AudioFeatures;\n startTime?: number;\n endTime?: number;\n // start / end position in bytes\n startPosition?: number;\n endPosition?: number;\n // number of audio samples for this point (samples size depends on bit depth)\n samples?: number;\n // Id of the speaker for this point\n speaker?: number;\n}\n\nexport interface AudioAnalysisData {\n pointsPerSecond: number; // How many consolidated value per second\n durationMs: number; // Duration of the audio in milliseconds\n bitDepth: number; // Bit depth of the audio\n samples: number; // Size of the audio in bytes\n numberOfChannels: number; // Number of audio channels\n sampleRate: number; // Sample rate of the audio\n dataPoints: DataPoint[];\n amplitudeRange: {\n min: number;\n max: number;\n };\n speakerChanges?: {\n timestamp: number;\n speaker: number;\n }[];\n}\n\nexport type EncodingType = \"pcm_32bit\" | \"pcm_16bit\" | \"pcm_8bit\";\nexport type SampleRate = 16000 | 44100 | 48000;\nexport interface RecordingConfig {\n sampleRate?: SampleRate; // Sample rate for recording\n channels?: 1 | 2; // 1 or 2 (MONO or STEREO)\n encoding?: EncodingType; // Encoding type for the recording\n interval?: number; // Interval in milliseconds at which to emit recording data\n\n // Optional parameters for audio processing\n //TODO remove maxRecentDataDuration - should be replaced by maxDataPoints to 100.\n maxRecentDataDuration?: number; // Maximum duration of recent data to keep for processing (default is 10.0 seconds)\n enableProcessing?: boolean; // Boolean to enable/disable audio processing (default is false)\n pointsPerSecond?: number; // Number of data points to extract per second of audio (default is 1000)\n algorithm?: string; // Algorithm to use for extraction (default is \"rms\")\n features?: AudioFeaturesOptions; // Feature options to extract (default is empty)\n\n // Optional paramters from web\n\n onAudioStream?: (_: AudioDataEvent) => Promise<void>; // Callback function to handle audio stream\n onProcessingResult?: (_: AudioAnalysisData) => Promise<void>; // Callback function to handle processing results\n}\n"]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { EventEmitter } from "expo-modules-core";
|
|
2
|
+
import { AudioAnalysisData, AudioStreamResult, AudioStreamStatus, RecordingConfig, StartAudioStreamResult } from "./ExpoAudioStream.types";
|
|
3
|
+
import { WebRecorder } from "./WebRecorder";
|
|
4
|
+
export interface EmitAudioEventProps {
|
|
5
|
+
data: ArrayBuffer;
|
|
6
|
+
position: number;
|
|
7
|
+
}
|
|
8
|
+
export type EmitAudioEventFunction = (_: EmitAudioEventProps) => void;
|
|
9
|
+
export type EmitAudioAnalysisFunction = (_: AudioAnalysisData) => void;
|
|
10
|
+
export interface ExpoAudioStreamWebProps {
|
|
11
|
+
audioWorkletUrl: string;
|
|
12
|
+
featuresExtratorUrl: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class ExpoAudioStreamWeb extends EventEmitter {
|
|
15
|
+
customRecorder: WebRecorder | null;
|
|
16
|
+
audioChunks: ArrayBuffer[];
|
|
17
|
+
isRecording: boolean;
|
|
18
|
+
isPaused: boolean;
|
|
19
|
+
recordingStartTime: number;
|
|
20
|
+
pausedTime: number;
|
|
21
|
+
currentDurationMs: number;
|
|
22
|
+
currentSize: number;
|
|
23
|
+
currentInterval: number;
|
|
24
|
+
lastEmittedSize: number;
|
|
25
|
+
lastEmittedTime: number;
|
|
26
|
+
streamUuid: string | null;
|
|
27
|
+
extension: "webm" | "wav";
|
|
28
|
+
recordingConfig?: RecordingConfig;
|
|
29
|
+
bitDepth: number;
|
|
30
|
+
audioWorkletUrl: string;
|
|
31
|
+
featuresExtratorUrl: string;
|
|
32
|
+
constructor({ audioWorkletUrl, featuresExtratorUrl, }: ExpoAudioStreamWebProps);
|
|
33
|
+
getMediaStream(): Promise<MediaStream>;
|
|
34
|
+
startRecording(recordingConfig?: RecordingConfig): Promise<StartAudioStreamResult>;
|
|
35
|
+
emitAudioEvent({ data, position }: EmitAudioEventProps): void;
|
|
36
|
+
stopRecording(): Promise<AudioStreamResult | null>;
|
|
37
|
+
pauseRecording(): Promise<void>;
|
|
38
|
+
resumeRecording(): Promise<void>;
|
|
39
|
+
status(): AudioStreamStatus;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=ExpoAudioStream.web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoAudioStream.web.d.ts","sourceRoot":"","sources":["../src/ExpoAudioStream.web.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EACL,iBAAiB,EAEjB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,EAAE,mBAAmB,KAAK,IAAI,CAAC;AACtE,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAEvE,MAAM,WAAW,uBAAuB;IACtC,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAID,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,cAAc,EAAE,WAAW,GAAG,IAAI,CAAC;IACnC,WAAW,EAAE,WAAW,EAAE,CAAC;IAC3B,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,KAAK,CAAS;IAClC,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;gBAEhB,EACV,eAAe,EACf,mBAAmB,GACpB,EAAE,uBAAuB;IA6BpB,cAAc;IAUd,cAAc,CAAC,eAAe,GAAE,eAAoB;IA8D1D,cAAc,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,mBAAmB;IAiBhD,aAAa,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAqBlD,cAAc;IAad,eAAe;IAarB,MAAM;CAWP"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { EventEmitter } from "expo-modules-core";
|
|
2
|
+
import { WebRecorder } from "./WebRecorder";
|
|
3
|
+
import { encodingToBitDepth } from "./utils";
|
|
4
|
+
// const log = debug("expo-audio-stream:useAudioRecording");
|
|
5
|
+
const log = console;
|
|
6
|
+
export class ExpoAudioStreamWeb extends EventEmitter {
|
|
7
|
+
customRecorder;
|
|
8
|
+
audioChunks;
|
|
9
|
+
isRecording;
|
|
10
|
+
isPaused;
|
|
11
|
+
recordingStartTime;
|
|
12
|
+
pausedTime;
|
|
13
|
+
currentDurationMs;
|
|
14
|
+
currentSize;
|
|
15
|
+
currentInterval;
|
|
16
|
+
lastEmittedSize;
|
|
17
|
+
lastEmittedTime;
|
|
18
|
+
streamUuid;
|
|
19
|
+
extension = "wav"; // Default extension is 'webm'
|
|
20
|
+
recordingConfig;
|
|
21
|
+
bitDepth; // Bit depth of the audio
|
|
22
|
+
audioWorkletUrl;
|
|
23
|
+
featuresExtratorUrl;
|
|
24
|
+
constructor({ audioWorkletUrl, featuresExtratorUrl, }) {
|
|
25
|
+
const mockNativeModule = {
|
|
26
|
+
addListener: (eventName) => {
|
|
27
|
+
// Not used on web
|
|
28
|
+
},
|
|
29
|
+
removeListeners: (count) => {
|
|
30
|
+
// Not used on web
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
super(mockNativeModule); // Pass the mock native module to the parent class
|
|
34
|
+
this.customRecorder = null;
|
|
35
|
+
this.audioChunks = [];
|
|
36
|
+
this.isRecording = false;
|
|
37
|
+
this.isPaused = false;
|
|
38
|
+
this.recordingStartTime = 0;
|
|
39
|
+
this.pausedTime = 0;
|
|
40
|
+
this.currentDurationMs = 0;
|
|
41
|
+
this.currentSize = 0;
|
|
42
|
+
this.bitDepth = 32; // Default
|
|
43
|
+
this.currentInterval = 1000; // Default interval in ms
|
|
44
|
+
this.lastEmittedSize = 0;
|
|
45
|
+
this.lastEmittedTime = 0;
|
|
46
|
+
this.streamUuid = null; // Initialize UUID on first recording start
|
|
47
|
+
this.audioWorkletUrl = audioWorkletUrl;
|
|
48
|
+
this.featuresExtratorUrl = featuresExtratorUrl;
|
|
49
|
+
}
|
|
50
|
+
// Utility to handle user media stream
|
|
51
|
+
async getMediaStream() {
|
|
52
|
+
try {
|
|
53
|
+
return await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
console.error("Failed to get media stream:", error);
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Start recording with options
|
|
61
|
+
async startRecording(recordingConfig = {}) {
|
|
62
|
+
if (this.isRecording) {
|
|
63
|
+
throw new Error("Recording is already in progress");
|
|
64
|
+
}
|
|
65
|
+
this.bitDepth = encodingToBitDepth({
|
|
66
|
+
encoding: recordingConfig.encoding ?? "pcm_32bit",
|
|
67
|
+
});
|
|
68
|
+
const audioContext = new (window.AudioContext ||
|
|
69
|
+
// @ts-ignore - Allow webkitAudioContext for Safari
|
|
70
|
+
window.webkitAudioContext)();
|
|
71
|
+
const stream = await this.getMediaStream();
|
|
72
|
+
const source = audioContext.createMediaStreamSource(stream);
|
|
73
|
+
this.customRecorder = new WebRecorder({
|
|
74
|
+
audioContext,
|
|
75
|
+
source,
|
|
76
|
+
recordingConfig,
|
|
77
|
+
audioWorkletUrl: this.audioWorkletUrl,
|
|
78
|
+
featuresExtratorUrl: this.featuresExtratorUrl,
|
|
79
|
+
emitAudioEventCallback: ({ data, position }) => {
|
|
80
|
+
this.audioChunks.push(data);
|
|
81
|
+
this.currentSize += data.byteLength;
|
|
82
|
+
this.emitAudioEvent({ data, position });
|
|
83
|
+
this.lastEmittedTime = Date.now();
|
|
84
|
+
this.lastEmittedSize = this.currentSize;
|
|
85
|
+
},
|
|
86
|
+
emitAudioAnalysisCallback: (audioAnalysisData) => {
|
|
87
|
+
console.log(`Emitted AudioAnalysis:`, audioAnalysisData);
|
|
88
|
+
this.emit("AudioAnalysis", audioAnalysisData);
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
await this.customRecorder.init();
|
|
92
|
+
this.customRecorder.start();
|
|
93
|
+
// // Set a timer to stop recording after 5 seconds
|
|
94
|
+
// setTimeout(() => {
|
|
95
|
+
// console.log("AUTO Stopping recording");
|
|
96
|
+
// this.customRecorder?.stopAndPlay();
|
|
97
|
+
// this.isRecording = false;
|
|
98
|
+
// }, 3000);
|
|
99
|
+
this.isRecording = true;
|
|
100
|
+
this.recordingConfig = recordingConfig;
|
|
101
|
+
this.recordingStartTime = Date.now();
|
|
102
|
+
this.pausedTime = 0;
|
|
103
|
+
this.lastEmittedSize = 0;
|
|
104
|
+
this.lastEmittedTime = 0;
|
|
105
|
+
this.streamUuid = Date.now().toString();
|
|
106
|
+
const fileUri = `${this.streamUuid}.${this.extension}`;
|
|
107
|
+
const streamConfig = {
|
|
108
|
+
fileUri,
|
|
109
|
+
mimeType: `audio/${this.extension}`,
|
|
110
|
+
bitDepth: this.bitDepth,
|
|
111
|
+
channels: recordingConfig.channels ?? 1,
|
|
112
|
+
sampleRate: recordingConfig.sampleRate ?? 44100,
|
|
113
|
+
};
|
|
114
|
+
return streamConfig;
|
|
115
|
+
}
|
|
116
|
+
emitAudioEvent({ data, position }) {
|
|
117
|
+
const fileUri = `${this.streamUuid}.${this.extension}`;
|
|
118
|
+
const audioEventPayload = {
|
|
119
|
+
fileUri,
|
|
120
|
+
mimeType: `audio/${this.extension}`,
|
|
121
|
+
lastEmittedSize: this.lastEmittedSize, // Since this might be continuously streaming, adjust accordingly
|
|
122
|
+
deltaSize: data.byteLength,
|
|
123
|
+
position,
|
|
124
|
+
totalSize: this.currentSize,
|
|
125
|
+
buffer: data,
|
|
126
|
+
streamUuid: this.streamUuid ?? "", // Generate or manage UUID for stream identification
|
|
127
|
+
};
|
|
128
|
+
this.emit("AudioData", audioEventPayload);
|
|
129
|
+
}
|
|
130
|
+
// Stop recording
|
|
131
|
+
async stopRecording() {
|
|
132
|
+
if (this.customRecorder) {
|
|
133
|
+
const fullPcmBuffer = await this.customRecorder.stop();
|
|
134
|
+
log.debug(`Stopped recording`, fullPcmBuffer);
|
|
135
|
+
}
|
|
136
|
+
this.isRecording = false;
|
|
137
|
+
this.currentDurationMs = Date.now() - this.recordingStartTime;
|
|
138
|
+
const result = {
|
|
139
|
+
fileUri: `${this.streamUuid}.${this.extension}`,
|
|
140
|
+
bitDepth: this.bitDepth,
|
|
141
|
+
channels: this.recordingConfig?.channels ?? 1,
|
|
142
|
+
sampleRate: this.recordingConfig?.sampleRate ?? 44100,
|
|
143
|
+
durationMs: this.currentDurationMs,
|
|
144
|
+
size: this.currentSize,
|
|
145
|
+
mimeType: `audio/${this.extension}`,
|
|
146
|
+
};
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
// Pause recording
|
|
150
|
+
async pauseRecording() {
|
|
151
|
+
if (!this.isRecording || this.isPaused) {
|
|
152
|
+
throw new Error("Recording is not active or already paused");
|
|
153
|
+
}
|
|
154
|
+
if (this.customRecorder) {
|
|
155
|
+
this.customRecorder.stop();
|
|
156
|
+
}
|
|
157
|
+
this.isPaused = true;
|
|
158
|
+
this.pausedTime = Date.now();
|
|
159
|
+
}
|
|
160
|
+
// Resume recording
|
|
161
|
+
async resumeRecording() {
|
|
162
|
+
if (!this.isPaused) {
|
|
163
|
+
throw new Error("Recording is not paused");
|
|
164
|
+
}
|
|
165
|
+
if (this.customRecorder) {
|
|
166
|
+
this.customRecorder.resume();
|
|
167
|
+
}
|
|
168
|
+
this.isPaused = false;
|
|
169
|
+
this.recordingStartTime += Date.now() - this.pausedTime;
|
|
170
|
+
}
|
|
171
|
+
// Get current status
|
|
172
|
+
status() {
|
|
173
|
+
const status = {
|
|
174
|
+
isRecording: this.isRecording,
|
|
175
|
+
isPaused: this.isPaused,
|
|
176
|
+
durationMs: Date.now() - this.recordingStartTime,
|
|
177
|
+
size: this.currentSize,
|
|
178
|
+
interval: this.currentInterval,
|
|
179
|
+
mimeType: `audio/${this.extension}`,
|
|
180
|
+
};
|
|
181
|
+
return status;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=ExpoAudioStream.web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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 debug from \"debug\";\nimport { EventEmitter } from \"expo-modules-core\";\n\nimport {\n AudioAnalysisData,\n AudioEventPayload,\n AudioStreamResult,\n AudioStreamStatus,\n RecordingConfig,\n StartAudioStreamResult,\n} from \"./ExpoAudioStream.types\";\nimport { WebRecorder } from \"./WebRecorder\";\nimport { encodingToBitDepth } from \"./utils\";\n\nexport interface EmitAudioEventProps {\n data: ArrayBuffer;\n position: number;\n}\nexport type EmitAudioEventFunction = (_: EmitAudioEventProps) => void;\nexport type EmitAudioAnalysisFunction = (_: AudioAnalysisData) => void;\n\nexport interface ExpoAudioStreamWebProps {\n audioWorkletUrl: string;\n featuresExtratorUrl: string;\n}\n\n// const log = debug(\"expo-audio-stream:useAudioRecording\");\nconst log = console;\nexport class ExpoAudioStreamWeb extends EventEmitter {\n customRecorder: WebRecorder | null;\n audioChunks: ArrayBuffer[];\n isRecording: boolean;\n isPaused: boolean;\n recordingStartTime: number;\n pausedTime: number;\n currentDurationMs: number;\n currentSize: number;\n currentInterval: number;\n lastEmittedSize: number;\n lastEmittedTime: number;\n streamUuid: string | null;\n extension: \"webm\" | \"wav\" = \"wav\"; // Default extension is 'webm'\n recordingConfig?: RecordingConfig;\n bitDepth: number; // Bit depth of the audio\n audioWorkletUrl: string;\n featuresExtratorUrl: string;\n\n constructor({\n audioWorkletUrl,\n featuresExtratorUrl,\n }: ExpoAudioStreamWebProps) {\n const mockNativeModule = {\n addListener: (eventName: string) => {\n // Not used on web\n },\n removeListeners: (count: number) => {\n // Not used on web\n },\n };\n super(mockNativeModule); // Pass the mock native module to the parent class\n\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.lastEmittedSize = 0;\n this.lastEmittedTime = 0;\n this.streamUuid = null; // Initialize UUID on first recording start\n this.audioWorkletUrl = audioWorkletUrl;\n this.featuresExtratorUrl = featuresExtratorUrl;\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 console.error(\"Failed to get media stream:\", error);\n throw error;\n }\n }\n\n // Start recording with options\n async startRecording(recordingConfig: RecordingConfig = {}) {\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 // @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 audioContext,\n source,\n recordingConfig,\n audioWorkletUrl: this.audioWorkletUrl,\n featuresExtratorUrl: this.featuresExtratorUrl,\n emitAudioEventCallback: ({ data, position }: EmitAudioEventProps) => {\n this.audioChunks.push(data);\n this.currentSize += data.byteLength;\n this.emitAudioEvent({ data, position });\n this.lastEmittedTime = Date.now();\n this.lastEmittedSize = this.currentSize;\n },\n emitAudioAnalysisCallback: (audioAnalysisData: AudioAnalysisData) => {\n console.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 // console.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.lastEmittedSize = 0;\n this.lastEmittedTime = 0;\n this.streamUuid = Date.now().toString();\n const fileUri = `${this.streamUuid}.${this.extension}`;\n const streamConfig: StartAudioStreamResult = {\n fileUri,\n mimeType: `audio/${this.extension}`,\n bitDepth: this.bitDepth,\n channels: recordingConfig.channels ?? 1,\n sampleRate: recordingConfig.sampleRate ?? 44100,\n };\n return streamConfig;\n }\n\n emitAudioEvent({ data, position }: EmitAudioEventProps) {\n const fileUri = `${this.streamUuid}.${this.extension}`;\n const audioEventPayload: AudioEventPayload = {\n fileUri,\n mimeType: `audio/${this.extension}`,\n lastEmittedSize: this.lastEmittedSize, // Since this might be continuously streaming, adjust accordingly\n deltaSize: data.byteLength,\n position,\n totalSize: this.currentSize,\n buffer: data,\n streamUuid: this.streamUuid ?? \"\", // Generate or manage UUID for stream identification\n };\n\n this.emit(\"AudioData\", audioEventPayload);\n }\n\n // Stop recording\n async stopRecording(): Promise<AudioStreamResult | null> {\n if (this.customRecorder) {\n const fullPcmBuffer = await this.customRecorder.stop();\n log.debug(`Stopped recording`, fullPcmBuffer);\n }\n this.isRecording = false;\n this.currentDurationMs = Date.now() - this.recordingStartTime;\n const result: AudioStreamResult = {\n fileUri: `${this.streamUuid}.${this.extension}`,\n bitDepth: this.bitDepth,\n channels: this.recordingConfig?.channels ?? 1,\n sampleRate: this.recordingConfig?.sampleRate ?? 44100,\n durationMs: this.currentDurationMs,\n size: this.currentSize,\n mimeType: `audio/${this.extension}`,\n };\n\n return result;\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.stop();\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: Date.now() - this.recordingStartTime,\n size: this.currentSize,\n interval: this.currentInterval,\n mimeType: `audio/${this.extension}`,\n };\n return status;\n }\n}\n"]}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
declare
|
|
2
|
-
export default
|
|
1
|
+
declare let ExpoAudioStreamModule: any;
|
|
2
|
+
export default ExpoAudioStreamModule;
|
|
3
3
|
//# sourceMappingURL=ExpoAudioStreamModule.d.ts.map
|
|
@@ -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":"AAQA,QAAA,IAAI,qBAAqB,EAAE,GAAG,CAAC;AAU/B,eAAe,qBAAqB,CAAC"}
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { requireNativeModule } from "expo-modules-core";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { Platform } from "react-native";
|
|
3
|
+
import { ExpoAudioStreamWeb, } from "./ExpoAudioStream.web";
|
|
4
|
+
let ExpoAudioStreamModule;
|
|
5
|
+
if (Platform.OS === "web") {
|
|
6
|
+
ExpoAudioStreamModule = (webProps) => {
|
|
7
|
+
return new ExpoAudioStreamWeb(webProps);
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
ExpoAudioStreamModule = requireNativeModule("ExpoAudioStream");
|
|
12
|
+
}
|
|
13
|
+
export default ExpoAudioStreamModule;
|
|
5
14
|
//# sourceMappingURL=ExpoAudioStreamModule.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudioStreamModule.js","sourceRoot":"","sources":["../src/ExpoAudioStreamModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"ExpoAudioStreamModule.js","sourceRoot":"","sources":["../src/ExpoAudioStreamModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,EACL,kBAAkB,GAEnB,MAAM,uBAAuB,CAAC;AAE/B,IAAI,qBAA0B,CAAC;AAE/B,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;IAC1B,qBAAqB,GAAG,CAAC,QAAiC,EAAE,EAAE;QAC5D,OAAO,IAAI,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC,CAAC;AACJ,CAAC;KAAM,CAAC;IACN,qBAAqB,GAAG,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;AACjE,CAAC;AAED,eAAe,qBAAqB,CAAC","sourcesContent":["import { requireNativeModule } from \"expo-modules-core\";\nimport { Platform } from \"react-native\";\n\nimport {\n ExpoAudioStreamWeb,\n ExpoAudioStreamWebProps,\n} from \"./ExpoAudioStream.web\";\n\nlet ExpoAudioStreamModule: any;\n\nif (Platform.OS === \"web\") {\n ExpoAudioStreamModule = (webProps: ExpoAudioStreamWebProps) => {\n return new ExpoAudioStreamWeb(webProps);\n };\n} else {\n ExpoAudioStreamModule = requireNativeModule(\"ExpoAudioStream\");\n}\n\nexport default ExpoAudioStreamModule;\n"]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { AudioAnalysisData, RecordingConfig } from "./ExpoAudioStream.types";
|
|
2
|
+
import { EmitAudioAnalysisFunction, EmitAudioEventFunction } from "./ExpoAudioStream.web";
|
|
3
|
+
interface AudioFeaturesEvent {
|
|
4
|
+
data: {
|
|
5
|
+
command: string;
|
|
6
|
+
result: AudioAnalysisData;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export declare class WebRecorder {
|
|
10
|
+
private audioContext;
|
|
11
|
+
private audioWorkletNode;
|
|
12
|
+
private featureExtractorWorker;
|
|
13
|
+
private source;
|
|
14
|
+
private audioWorkletUrl;
|
|
15
|
+
private emitAudioEventCallback;
|
|
16
|
+
private emitAudioAnalysisCallback;
|
|
17
|
+
private config;
|
|
18
|
+
private position;
|
|
19
|
+
private numberOfChannels;
|
|
20
|
+
private bitDepth;
|
|
21
|
+
private exportBitDepth;
|
|
22
|
+
private buffers;
|
|
23
|
+
private audioAnalysisData;
|
|
24
|
+
constructor({ audioContext, source, recordingConfig, featuresExtratorUrl, audioWorkletUrl, emitAudioEventCallback, emitAudioAnalysisCallback, }: {
|
|
25
|
+
audioContext: AudioContext;
|
|
26
|
+
source: MediaStreamAudioSourceNode;
|
|
27
|
+
recordingConfig: RecordingConfig;
|
|
28
|
+
featuresExtratorUrl: string;
|
|
29
|
+
audioWorkletUrl: string;
|
|
30
|
+
emitAudioEventCallback: EmitAudioEventFunction;
|
|
31
|
+
emitAudioAnalysisCallback: EmitAudioAnalysisFunction;
|
|
32
|
+
});
|
|
33
|
+
init(): Promise<void>;
|
|
34
|
+
handleFeatureExtractorMessage(event: AudioFeaturesEvent): void;
|
|
35
|
+
start(): void;
|
|
36
|
+
stop(): Promise<unknown>;
|
|
37
|
+
pause(): void;
|
|
38
|
+
stopMediaStreamTracks(): void;
|
|
39
|
+
playRecordedData({ recordedData, }: {
|
|
40
|
+
recordedData: ArrayBuffer;
|
|
41
|
+
mimeType?: string;
|
|
42
|
+
}): Promise<void>;
|
|
43
|
+
private checkAudioContextFormat;
|
|
44
|
+
resume(): void;
|
|
45
|
+
}
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=WebRecorder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebRecorder.d.ts","sourceRoot":"","sources":["../src/WebRecorder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC7E,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACvB,MAAM,uBAAuB,CAAC;AAU/B,UAAU,kBAAkB;IAC1B,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,iBAAiB,CAAC;KAC3B,CAAC;CACH;AASD,qBAAa,WAAW;IACtB,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,gBAAgB,CAAoB;IAC5C,OAAO,CAAC,sBAAsB,CAAS;IACvC,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,sBAAsB,CAAyB;IACvD,OAAO,CAAC,yBAAyB,CAA4B;IAC7D,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,iBAAiB,CAAoB;gBAEjC,EACV,YAAY,EACZ,MAAM,EACN,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,sBAAsB,EACtB,yBAAyB,GAC1B,EAAE;QACD,YAAY,EAAE,YAAY,CAAC;QAC3B,MAAM,EAAE,0BAA0B,CAAC;QACnC,eAAe,EAAE,eAAe,CAAC;QACjC,mBAAmB,EAAE,MAAM,CAAC;QAC5B,eAAe,EAAE,MAAM,CAAC;QACxB,sBAAsB,EAAE,sBAAsB,CAAC;QAC/C,yBAAyB,EAAE,yBAAyB,CAAC;KACtD;IAoDK,IAAI;IA6FV,6BAA6B,CAAC,KAAK,EAAE,kBAAkB;IA6BvD,KAAK;IAKL,IAAI;IA4DJ,KAAK;IAML,qBAAqB;IAMf,gBAAgB,CAAC,EACrB,YAAY,GACb,EAAE;QACD,YAAY,EAAE,WAAW,CAAC;QAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB;IAqBD,OAAO,CAAC,uBAAuB;IAoB/B,MAAM;CAKP"}
|