@siteed/expo-audio-stream 1.0.3 → 1.0.5
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/.size-limit.json +4 -4
- package/README.md +18 -176
- package/android/src/main/java/net/siteed/audiostream/AudioRecorderManager.kt +1 -0
- package/app.plugin.js +1 -1
- package/build/AudioAnalysis/AudioAnalysis.types.d.ts +3 -5
- 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 +19 -3
- package/build/AudioAnalysis/extractAudioAnalysis.d.ts.map +1 -1
- package/build/AudioAnalysis/extractAudioAnalysis.js +14 -27
- package/build/AudioAnalysis/extractAudioAnalysis.js.map +1 -1
- package/build/AudioAnalysis/extractWaveform.d.ts.map +1 -1
- package/build/AudioAnalysis/extractWaveform.js +3 -3
- package/build/AudioAnalysis/extractWaveform.js.map +1 -1
- package/build/AudioRecorder.provider.d.ts +6 -6
- package/build/AudioRecorder.provider.d.ts.map +1 -1
- package/build/AudioRecorder.provider.js +9 -9
- package/build/AudioRecorder.provider.js.map +1 -1
- package/build/ExpoAudioStream.native.d.ts.map +1 -1
- package/build/ExpoAudioStream.native.js +2 -2
- package/build/ExpoAudioStream.native.js.map +1 -1
- package/build/ExpoAudioStream.types.d.ts +20 -18
- package/build/ExpoAudioStream.types.d.ts.map +1 -1
- package/build/ExpoAudioStream.types.js.map +1 -1
- package/build/ExpoAudioStream.web.d.ts +8 -8
- package/build/ExpoAudioStream.web.d.ts.map +1 -1
- package/build/ExpoAudioStream.web.js +40 -22
- package/build/ExpoAudioStream.web.js.map +1 -1
- package/build/ExpoAudioStreamModule.d.ts.map +1 -1
- package/build/ExpoAudioStreamModule.js +8 -7
- package/build/ExpoAudioStreamModule.js.map +1 -1
- package/build/WebRecorder.web.d.ts +8 -8
- package/build/WebRecorder.web.d.ts.map +1 -1
- package/build/WebRecorder.web.js +60 -50
- package/build/WebRecorder.web.js.map +1 -1
- package/build/constants.d.ts +1 -1
- package/build/constants.d.ts.map +1 -1
- package/build/constants.js +3 -3
- package/build/constants.js.map +1 -1
- package/build/events.d.ts +16 -4
- package/build/events.d.ts.map +1 -1
- package/build/events.js +8 -8
- package/build/events.js.map +1 -1
- package/build/index.d.ts +8 -8
- package/build/index.d.ts.map +1 -1
- package/build/index.js +6 -6
- package/build/index.js.map +1 -1
- package/build/logger.d.ts +2 -2
- package/build/logger.d.ts.map +1 -1
- package/build/logger.js +7 -11
- package/build/logger.js.map +1 -1
- package/build/useAudioRecorder.d.ts +4 -21
- package/build/useAudioRecorder.d.ts.map +1 -1
- package/build/useAudioRecorder.js +33 -33
- package/build/useAudioRecorder.js.map +1 -1
- package/build/utils/BlobFix.d.ts +9 -0
- package/build/utils/BlobFix.d.ts.map +1 -0
- package/build/utils/BlobFix.js +494 -0
- package/build/utils/BlobFix.js.map +1 -0
- package/build/utils/concatenateBuffers.d.ts +8 -0
- package/build/utils/concatenateBuffers.d.ts.map +1 -0
- package/build/utils/concatenateBuffers.js +21 -0
- package/build/utils/concatenateBuffers.js.map +1 -0
- package/build/utils/convertPCMToFloat32.d.ts +2 -2
- package/build/utils/convertPCMToFloat32.d.ts.map +1 -1
- package/build/utils/convertPCMToFloat32.js +49 -36
- package/build/utils/convertPCMToFloat32.js.map +1 -1
- package/build/utils/encodingToBitDepth.d.ts +1 -1
- package/build/utils/encodingToBitDepth.d.ts.map +1 -1
- package/build/utils/encodingToBitDepth.js +3 -3
- package/build/utils/encodingToBitDepth.js.map +1 -1
- package/build/utils/getWavFileInfo.d.ts +4 -3
- package/build/utils/getWavFileInfo.d.ts.map +1 -1
- package/build/utils/getWavFileInfo.js +18 -15
- package/build/utils/getWavFileInfo.js.map +1 -1
- package/build/utils/writeWavHeader.d.ts.map +1 -1
- package/build/utils/writeWavHeader.js +4 -4
- package/build/utils/writeWavHeader.js.map +1 -1
- package/build/workers/InlineFeaturesExtractor.web.d.ts.map +1 -1
- package/build/workers/InlineFeaturesExtractor.web.js.map +1 -1
- package/build/workers/inlineAudioWebWorker.web.d.ts.map +1 -1
- package/build/workers/inlineAudioWebWorker.web.js.map +1 -1
- package/expo-module.config.json +8 -17
- package/ios/AudioStreamManager.swift +1 -0
- package/ios/ExpoAudioStreamModule.swift +1 -0
- package/ios/RecordingResult.swift +1 -0
- package/package.json +72 -65
- package/plugin/build/index.d.ts +1 -1
- package/plugin/build/index.js +7 -7
- package/plugin/src/index.ts +47 -47
- package/plugin/tsconfig.json +8 -13
- package/src/AudioAnalysis/AudioAnalysis.types.ts +59 -60
- package/src/AudioAnalysis/extractAudioAnalysis.ts +132 -121
- package/src/AudioAnalysis/extractWaveform.ts +18 -18
- package/src/AudioRecorder.provider.tsx +53 -53
- package/src/ExpoAudioStream.native.ts +2 -2
- package/src/ExpoAudioStream.types.ts +56 -53
- package/src/ExpoAudioStream.web.ts +232 -205
- package/src/ExpoAudioStreamModule.ts +17 -16
- package/src/WebRecorder.web.ts +407 -390
- package/src/constants.ts +11 -11
- package/src/events.ts +27 -13
- package/src/index.ts +15 -15
- package/src/logger.ts +15 -18
- package/src/useAudioRecorder.tsx +394 -389
- package/src/utils/BlobFix.ts +550 -0
- package/src/utils/concatenateBuffers.ts +24 -0
- package/src/utils/convertPCMToFloat32.ts +72 -45
- package/src/utils/encodingToBitDepth.ts +14 -14
- package/src/utils/getWavFileInfo.ts +106 -99
- package/src/utils/writeWavHeader.ts +45 -45
- package/src/workers/InlineFeaturesExtractor.web.tsx +1 -1
- package/src/workers/inlineAudioWebWorker.web.tsx +1 -1
- package/tsconfig.json +12 -7
|
@@ -1,229 +1,256 @@
|
|
|
1
1
|
// src/ExpoAudioStreamModule.web.ts
|
|
2
|
-
import { EventEmitter } from
|
|
2
|
+
import { EventEmitter } from 'expo-modules-core'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { AudioAnalysis } from './AudioAnalysis/AudioAnalysis.types'
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} from
|
|
13
|
-
import {
|
|
14
|
-
import { getLogger } from
|
|
15
|
-
import {
|
|
6
|
+
AudioRecording,
|
|
7
|
+
AudioStreamStatus,
|
|
8
|
+
BitDepth,
|
|
9
|
+
RecordingConfig,
|
|
10
|
+
StartRecordingResult,
|
|
11
|
+
} from './ExpoAudioStream.types'
|
|
12
|
+
import { WebRecorder } from './WebRecorder.web'
|
|
13
|
+
import { AudioEventPayload } from './events'
|
|
14
|
+
import { getLogger } from './logger'
|
|
15
|
+
import { concatenateBuffers } from './utils/concatenateBuffers'
|
|
16
|
+
import { encodingToBitDepth } from './utils/encodingToBitDepth'
|
|
17
|
+
import { writeWavHeader } from './utils/writeWavHeader'
|
|
16
18
|
|
|
17
19
|
export interface EmitAudioEventProps {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
data: Float32Array
|
|
21
|
+
position: number
|
|
20
22
|
}
|
|
21
|
-
export type EmitAudioEventFunction = (_: EmitAudioEventProps) => void
|
|
22
|
-
export type EmitAudioAnalysisFunction = (_:
|
|
23
|
+
export type EmitAudioEventFunction = (_: EmitAudioEventProps) => void
|
|
24
|
+
export type EmitAudioAnalysisFunction = (_: AudioAnalysis) => void
|
|
23
25
|
|
|
24
26
|
export interface ExpoAudioStreamWebProps {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
audioWorkletUrl: string
|
|
28
|
+
featuresExtratorUrl: string
|
|
27
29
|
}
|
|
28
30
|
|
|
29
|
-
const logger = getLogger(
|
|
31
|
+
const logger = getLogger('ExpoAudioStreamWeb')
|
|
30
32
|
|
|
31
33
|
export class ExpoAudioStreamWeb extends EventEmitter {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Utility to handle user media stream
|
|
82
|
-
async getMediaStream() {
|
|
83
|
-
try {
|
|
84
|
-
return await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
85
|
-
} catch (error) {
|
|
86
|
-
console.error("Failed to get media stream:", error);
|
|
87
|
-
throw error;
|
|
34
|
+
customRecorder: WebRecorder | null
|
|
35
|
+
audioChunks: ArrayBuffer[]
|
|
36
|
+
isRecording: boolean
|
|
37
|
+
isPaused: boolean
|
|
38
|
+
recordingStartTime: number
|
|
39
|
+
pausedTime: number
|
|
40
|
+
currentDurationMs: number
|
|
41
|
+
currentSize: number
|
|
42
|
+
currentInterval: number
|
|
43
|
+
lastEmittedSize: number
|
|
44
|
+
lastEmittedTime: number
|
|
45
|
+
streamUuid: string | null
|
|
46
|
+
extension: 'webm' | 'wav' = 'wav' // Default extension is 'webm'
|
|
47
|
+
recordingConfig?: RecordingConfig
|
|
48
|
+
bitDepth: BitDepth // Bit depth of the audio
|
|
49
|
+
audioWorkletUrl: string
|
|
50
|
+
featuresExtratorUrl: string
|
|
51
|
+
|
|
52
|
+
constructor({
|
|
53
|
+
audioWorkletUrl,
|
|
54
|
+
featuresExtratorUrl,
|
|
55
|
+
}: ExpoAudioStreamWebProps) {
|
|
56
|
+
const mockNativeModule = {
|
|
57
|
+
addListener: () => {
|
|
58
|
+
// Not used on web
|
|
59
|
+
},
|
|
60
|
+
removeListeners: () => {
|
|
61
|
+
// Not used on web
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
super(mockNativeModule) // Pass the mock native module to the parent class
|
|
65
|
+
|
|
66
|
+
this.customRecorder = null
|
|
67
|
+
this.audioChunks = []
|
|
68
|
+
this.isRecording = false
|
|
69
|
+
this.isPaused = false
|
|
70
|
+
this.recordingStartTime = 0
|
|
71
|
+
this.pausedTime = 0
|
|
72
|
+
this.currentDurationMs = 0
|
|
73
|
+
this.currentSize = 0
|
|
74
|
+
this.bitDepth = 32 // Default
|
|
75
|
+
this.currentInterval = 1000 // Default interval in ms
|
|
76
|
+
this.lastEmittedSize = 0
|
|
77
|
+
this.lastEmittedTime = 0
|
|
78
|
+
this.streamUuid = null // Initialize UUID on first recording start
|
|
79
|
+
this.audioWorkletUrl = audioWorkletUrl
|
|
80
|
+
this.featuresExtratorUrl = featuresExtratorUrl
|
|
88
81
|
}
|
|
89
|
-
}
|
|
90
82
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
83
|
+
// Utility to handle user media stream
|
|
84
|
+
async getMediaStream() {
|
|
85
|
+
try {
|
|
86
|
+
return await navigator.mediaDevices.getUserMedia({ audio: true })
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.error('Failed to get media stream:', error)
|
|
89
|
+
throw error
|
|
90
|
+
}
|
|
95
91
|
}
|
|
96
92
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
this.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
position,
|
|
162
|
-
totalSize: this.currentSize,
|
|
163
|
-
buffer: data,
|
|
164
|
-
streamUuid: this.streamUuid ?? "", // Generate or manage UUID for stream identification
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
this.emit("AudioData", audioEventPayload);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Stop recording
|
|
171
|
-
async stopRecording(): Promise<AudioRecordingResult | null> {
|
|
172
|
-
if (this.customRecorder) {
|
|
173
|
-
const fullPcmBuffer = await this.customRecorder.stop();
|
|
174
|
-
logger.debug(`Stopped recording`, fullPcmBuffer);
|
|
93
|
+
// Start recording with options
|
|
94
|
+
async startRecording(recordingConfig: RecordingConfig = {}) {
|
|
95
|
+
if (this.isRecording) {
|
|
96
|
+
throw new Error('Recording is already in progress')
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
this.bitDepth = encodingToBitDepth({
|
|
100
|
+
encoding: recordingConfig.encoding ?? 'pcm_32bit',
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
const audioContext = new (window.AudioContext ||
|
|
104
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
105
|
+
// @ts-ignore - Allow webkitAudioContext for Safari
|
|
106
|
+
window.webkitAudioContext)()
|
|
107
|
+
const stream = await this.getMediaStream()
|
|
108
|
+
|
|
109
|
+
const source = audioContext.createMediaStreamSource(stream)
|
|
110
|
+
|
|
111
|
+
this.customRecorder = new WebRecorder({
|
|
112
|
+
audioContext,
|
|
113
|
+
source,
|
|
114
|
+
recordingConfig,
|
|
115
|
+
audioWorkletUrl: this.audioWorkletUrl,
|
|
116
|
+
emitAudioEventCallback: ({
|
|
117
|
+
data,
|
|
118
|
+
position,
|
|
119
|
+
}: EmitAudioEventProps) => {
|
|
120
|
+
this.audioChunks.push(data)
|
|
121
|
+
this.currentSize += data.byteLength
|
|
122
|
+
this.emitAudioEvent({ data, position })
|
|
123
|
+
this.lastEmittedTime = Date.now()
|
|
124
|
+
this.lastEmittedSize = this.currentSize
|
|
125
|
+
},
|
|
126
|
+
emitAudioAnalysisCallback: (audioAnalysisData: AudioAnalysis) => {
|
|
127
|
+
logger.log(`Emitted AudioAnalysis:`, audioAnalysisData)
|
|
128
|
+
this.emit('AudioAnalysis', audioAnalysisData)
|
|
129
|
+
},
|
|
130
|
+
})
|
|
131
|
+
await this.customRecorder.init()
|
|
132
|
+
this.customRecorder.start()
|
|
133
|
+
|
|
134
|
+
// // Set a timer to stop recording after 5 seconds
|
|
135
|
+
// setTimeout(() => {
|
|
136
|
+
// logger.log("AUTO Stopping recording");
|
|
137
|
+
// this.customRecorder?.stopAndPlay();
|
|
138
|
+
// this.isRecording = false;
|
|
139
|
+
// }, 3000);
|
|
140
|
+
|
|
141
|
+
this.isRecording = true
|
|
142
|
+
this.recordingConfig = recordingConfig
|
|
143
|
+
this.recordingStartTime = Date.now()
|
|
144
|
+
this.pausedTime = 0
|
|
145
|
+
this.lastEmittedSize = 0
|
|
146
|
+
this.lastEmittedTime = 0
|
|
147
|
+
this.streamUuid = Date.now().toString()
|
|
148
|
+
const fileUri = `${this.streamUuid}.${this.extension}`
|
|
149
|
+
const streamConfig: StartRecordingResult = {
|
|
150
|
+
fileUri,
|
|
151
|
+
mimeType: `audio/${this.extension}`,
|
|
152
|
+
bitDepth: this.bitDepth,
|
|
153
|
+
channels: recordingConfig.channels ?? 1,
|
|
154
|
+
sampleRate: recordingConfig.sampleRate ?? 44100,
|
|
155
|
+
}
|
|
156
|
+
return streamConfig
|
|
175
157
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
// Pause recording
|
|
192
|
-
async pauseRecording() {
|
|
193
|
-
if (!this.isRecording || this.isPaused) {
|
|
194
|
-
throw new Error("Recording is not active or already paused");
|
|
158
|
+
|
|
159
|
+
emitAudioEvent({ data, position }: EmitAudioEventProps) {
|
|
160
|
+
const fileUri = `${this.streamUuid}.${this.extension}`
|
|
161
|
+
const audioEventPayload: AudioEventPayload = {
|
|
162
|
+
fileUri,
|
|
163
|
+
mimeType: `audio/${this.extension}`,
|
|
164
|
+
lastEmittedSize: this.lastEmittedSize, // Since this might be continuously streaming, adjust accordingly
|
|
165
|
+
deltaSize: data.byteLength,
|
|
166
|
+
position,
|
|
167
|
+
totalSize: this.currentSize,
|
|
168
|
+
buffer: data,
|
|
169
|
+
streamUuid: this.streamUuid ?? '', // Generate or manage UUID for stream identification
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
this.emit('AudioData', audioEventPayload)
|
|
195
173
|
}
|
|
196
174
|
|
|
197
|
-
|
|
198
|
-
|
|
175
|
+
// Stop recording
|
|
176
|
+
async stopRecording(): Promise<AudioRecording> {
|
|
177
|
+
if (!this.customRecorder) {
|
|
178
|
+
throw new Error('Recorder is not initialized')
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const fullPcmBufferArray = await this.customRecorder.stop()
|
|
182
|
+
|
|
183
|
+
// concat all audio chunks
|
|
184
|
+
logger.debug(`Stopped recording`, fullPcmBufferArray)
|
|
185
|
+
this.isRecording = false
|
|
186
|
+
this.currentDurationMs = Date.now() - this.recordingStartTime
|
|
187
|
+
|
|
188
|
+
const wavConfig = {
|
|
189
|
+
buffer: fullPcmBufferArray.buffer,
|
|
190
|
+
sampleRate: this.recordingConfig?.sampleRate ?? 44100,
|
|
191
|
+
numChannels: this.recordingConfig?.channels ?? 1,
|
|
192
|
+
bitDepth: this.bitDepth,
|
|
193
|
+
}
|
|
194
|
+
logger.debug(`Writing wav header`, wavConfig)
|
|
195
|
+
const wavBuffer = writeWavHeader(wavConfig).slice(0)
|
|
196
|
+
|
|
197
|
+
// Create blob fileUri from audio chunks
|
|
198
|
+
const blob = new Blob([wavBuffer], {
|
|
199
|
+
type: `audio/${this.extension}`,
|
|
200
|
+
})
|
|
201
|
+
const fileUri = URL.createObjectURL(blob)
|
|
202
|
+
|
|
203
|
+
const result: AudioRecording = {
|
|
204
|
+
fileUri,
|
|
205
|
+
filename: `${this.streamUuid}.${this.extension}`,
|
|
206
|
+
wavPCMData: fullPcmBufferArray,
|
|
207
|
+
bitDepth: this.bitDepth,
|
|
208
|
+
channels: this.recordingConfig?.channels ?? 1,
|
|
209
|
+
sampleRate: this.recordingConfig?.sampleRate ?? 44100,
|
|
210
|
+
durationMs: this.currentDurationMs,
|
|
211
|
+
size: this.currentSize,
|
|
212
|
+
mimeType: `audio/${this.extension}`,
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return result
|
|
199
216
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
217
|
+
|
|
218
|
+
// Pause recording
|
|
219
|
+
async pauseRecording() {
|
|
220
|
+
if (!this.isRecording || this.isPaused) {
|
|
221
|
+
throw new Error('Recording is not active or already paused')
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (this.customRecorder) {
|
|
225
|
+
this.customRecorder.pause()
|
|
226
|
+
}
|
|
227
|
+
this.isPaused = true
|
|
228
|
+
this.pausedTime = Date.now()
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Resume recording
|
|
232
|
+
async resumeRecording() {
|
|
233
|
+
if (!this.isPaused) {
|
|
234
|
+
throw new Error('Recording is not paused')
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (this.customRecorder) {
|
|
238
|
+
this.customRecorder.resume()
|
|
239
|
+
}
|
|
240
|
+
this.isPaused = false
|
|
241
|
+
this.recordingStartTime += Date.now() - this.pausedTime
|
|
208
242
|
}
|
|
209
243
|
|
|
210
|
-
|
|
211
|
-
|
|
244
|
+
// Get current status
|
|
245
|
+
status() {
|
|
246
|
+
const status: AudioStreamStatus = {
|
|
247
|
+
isRecording: this.isRecording,
|
|
248
|
+
isPaused: this.isPaused,
|
|
249
|
+
durationMs: Date.now() - this.recordingStartTime,
|
|
250
|
+
size: this.currentSize,
|
|
251
|
+
interval: this.currentInterval,
|
|
252
|
+
mimeType: `audio/${this.extension}`,
|
|
253
|
+
}
|
|
254
|
+
return status
|
|
212
255
|
}
|
|
213
|
-
this.isPaused = false;
|
|
214
|
-
this.recordingStartTime += Date.now() - this.pausedTime;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// Get current status
|
|
218
|
-
status() {
|
|
219
|
-
const status: AudioStreamStatus = {
|
|
220
|
-
isRecording: this.isRecording,
|
|
221
|
-
isPaused: this.isPaused,
|
|
222
|
-
durationMs: Date.now() - this.recordingStartTime,
|
|
223
|
-
size: this.currentSize,
|
|
224
|
-
interval: this.currentInterval,
|
|
225
|
-
mimeType: `audio/${this.extension}`,
|
|
226
|
-
};
|
|
227
|
-
return status;
|
|
228
|
-
}
|
|
229
256
|
}
|
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
import { requireNativeModule } from
|
|
2
|
-
import { Platform } from
|
|
1
|
+
import { requireNativeModule } from 'expo-modules-core'
|
|
2
|
+
import { Platform } from 'react-native'
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
} from
|
|
5
|
+
ExpoAudioStreamWeb,
|
|
6
|
+
ExpoAudioStreamWebProps,
|
|
7
|
+
} from './ExpoAudioStream.web'
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
+
let ExpoAudioStreamModule: any
|
|
10
11
|
|
|
11
|
-
if (Platform.OS ===
|
|
12
|
-
|
|
12
|
+
if (Platform.OS === 'web') {
|
|
13
|
+
let instance: ExpoAudioStreamWeb | null = null
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
ExpoAudioStreamModule = ((webProps: ExpoAudioStreamWebProps) => {
|
|
16
|
+
if (!instance) {
|
|
17
|
+
instance = new ExpoAudioStreamWeb(webProps)
|
|
18
|
+
}
|
|
19
|
+
return instance
|
|
20
|
+
})
|
|
20
21
|
} else {
|
|
21
|
-
|
|
22
|
+
ExpoAudioStreamModule = requireNativeModule('ExpoAudioStream')
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
export default ExpoAudioStreamModule
|
|
25
|
+
export default ExpoAudioStreamModule
|