@siteed/expo-audio-stream 1.1.2 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/build/AudioAnalysis/AudioAnalysis.types.d.ts +74 -0
  2. package/build/AudioAnalysis/AudioAnalysis.types.d.ts.map +1 -0
  3. package/build/AudioAnalysis/AudioAnalysis.types.js +3 -0
  4. package/build/AudioAnalysis/AudioAnalysis.types.js.map +1 -0
  5. package/build/AudioAnalysis/extractAudioAnalysis.d.ts +20 -0
  6. package/build/AudioAnalysis/extractAudioAnalysis.d.ts.map +1 -0
  7. package/build/AudioAnalysis/extractAudioAnalysis.js +88 -0
  8. package/build/AudioAnalysis/extractAudioAnalysis.js.map +1 -0
  9. package/build/AudioAnalysis/extractWaveform.d.ts +8 -0
  10. package/build/AudioAnalysis/extractWaveform.d.ts.map +1 -0
  11. package/build/AudioAnalysis/extractWaveform.js +14 -0
  12. package/build/AudioAnalysis/extractWaveform.js.map +1 -0
  13. package/build/AudioRecorder.provider.d.ts +23 -0
  14. package/build/AudioRecorder.provider.d.ts.map +1 -0
  15. package/build/AudioRecorder.provider.js +36 -0
  16. package/build/AudioRecorder.provider.js.map +1 -0
  17. package/build/ExpoAudioStream.native.d.ts +3 -0
  18. package/build/ExpoAudioStream.native.d.ts.map +1 -0
  19. package/{src/ExpoAudioStream.native.ts → build/ExpoAudioStream.native.js} +3 -3
  20. package/build/ExpoAudioStream.native.js.map +1 -0
  21. package/build/ExpoAudioStream.types.d.ts +65 -0
  22. package/build/ExpoAudioStream.types.d.ts.map +1 -0
  23. package/build/ExpoAudioStream.types.js +2 -0
  24. package/build/ExpoAudioStream.types.js.map +1 -0
  25. package/build/ExpoAudioStream.web.d.ts +42 -0
  26. package/build/ExpoAudioStream.web.d.ts.map +1 -0
  27. package/build/ExpoAudioStream.web.js +203 -0
  28. package/build/ExpoAudioStream.web.js.map +1 -0
  29. package/build/ExpoAudioStreamModule.d.ts +3 -0
  30. package/build/ExpoAudioStreamModule.d.ts.map +1 -0
  31. package/build/ExpoAudioStreamModule.js +25 -0
  32. package/build/ExpoAudioStreamModule.js.map +1 -0
  33. package/build/WebRecorder.web.d.ts +51 -0
  34. package/build/WebRecorder.web.d.ts.map +1 -0
  35. package/build/WebRecorder.web.js +298 -0
  36. package/build/WebRecorder.web.js.map +1 -0
  37. package/build/constants.d.ts +11 -0
  38. package/build/constants.d.ts.map +1 -0
  39. package/build/constants.js +14 -0
  40. package/build/constants.js.map +1 -0
  41. package/build/events.d.ts +18 -0
  42. package/build/events.d.ts.map +1 -0
  43. package/build/events.js +15 -0
  44. package/build/events.js.map +1 -0
  45. package/build/index.d.ts +11 -0
  46. package/build/index.d.ts.map +1 -0
  47. package/build/index.js.map +1 -0
  48. package/build/logger.d.ts +9 -0
  49. package/build/logger.d.ts.map +1 -0
  50. package/build/logger.js +13 -0
  51. package/build/logger.js.map +1 -0
  52. package/build/useAudioRecorder.d.ts +20 -0
  53. package/build/useAudioRecorder.d.ts.map +1 -0
  54. package/build/useAudioRecorder.js +271 -0
  55. package/build/useAudioRecorder.js.map +1 -0
  56. package/build/utils/BlobFix.d.ts +9 -0
  57. package/build/utils/BlobFix.d.ts.map +1 -0
  58. package/{src/utils/BlobFix.ts → build/utils/BlobFix.js} +66 -122
  59. package/build/utils/BlobFix.js.map +1 -0
  60. package/build/utils/concatenateBuffers.d.ts +8 -0
  61. package/build/utils/concatenateBuffers.d.ts.map +1 -0
  62. package/{src/utils/concatenateBuffers.ts → build/utils/concatenateBuffers.js} +10 -13
  63. package/build/utils/concatenateBuffers.js.map +1 -0
  64. package/build/utils/convertPCMToFloat32.d.ts +11 -0
  65. package/build/utils/convertPCMToFloat32.d.ts.map +1 -0
  66. package/build/utils/convertPCMToFloat32.js +54 -0
  67. package/build/utils/convertPCMToFloat32.js.map +1 -0
  68. package/build/utils/encodingToBitDepth.d.ts +5 -0
  69. package/build/utils/encodingToBitDepth.d.ts.map +1 -0
  70. package/build/utils/encodingToBitDepth.js +13 -0
  71. package/build/utils/encodingToBitDepth.js.map +1 -0
  72. package/build/utils/getWavFileInfo.d.ts +26 -0
  73. package/build/utils/getWavFileInfo.d.ts.map +1 -0
  74. package/build/utils/getWavFileInfo.js +92 -0
  75. package/build/utils/getWavFileInfo.js.map +1 -0
  76. package/build/utils/writeWavHeader.d.ts +9 -0
  77. package/build/utils/writeWavHeader.d.ts.map +1 -0
  78. package/build/utils/writeWavHeader.js +45 -0
  79. package/build/utils/writeWavHeader.js.map +1 -0
  80. package/build/workers/InlineFeaturesExtractor.web.d.ts +2 -0
  81. package/build/workers/InlineFeaturesExtractor.web.d.ts.map +1 -0
  82. package/{src/workers/InlineFeaturesExtractor.web.tsx → build/workers/InlineFeaturesExtractor.web.js} +2 -1
  83. package/build/workers/InlineFeaturesExtractor.web.js.map +1 -0
  84. package/build/workers/inlineAudioWebWorker.web.d.ts +2 -0
  85. package/build/workers/inlineAudioWebWorker.web.d.ts.map +1 -0
  86. package/{src/workers/inlineAudioWebWorker.web.tsx → build/workers/inlineAudioWebWorker.web.js} +2 -1
  87. package/build/workers/inlineAudioWebWorker.web.js.map +1 -0
  88. package/package.json +2 -2
  89. package/src/AudioAnalysis/AudioAnalysis.types.ts +0 -84
  90. package/src/AudioAnalysis/extractAudioAnalysis.ts +0 -147
  91. package/src/AudioAnalysis/extractWaveform.ts +0 -25
  92. package/src/AudioRecorder.provider.tsx +0 -70
  93. package/src/ExpoAudioStream.types.ts +0 -80
  94. package/src/ExpoAudioStream.web.ts +0 -255
  95. package/src/ExpoAudioStreamModule.ts +0 -31
  96. package/src/WebRecorder.web.ts +0 -433
  97. package/src/constants.ts +0 -18
  98. package/src/events.ts +0 -39
  99. package/src/index.ts +0 -24
  100. package/src/logger.ts +0 -22
  101. package/src/useAudioRecorder.tsx +0 -420
  102. package/src/utils/convertPCMToFloat32.ts +0 -75
  103. package/src/utils/encodingToBitDepth.ts +0 -18
  104. package/src/utils/getWavFileInfo.ts +0 -132
  105. package/src/utils/writeWavHeader.ts +0 -61
@@ -1,70 +0,0 @@
1
- // packages/expo-audio-stream/src/AudioRecorder.provider.tsx
2
- import React, { createContext, useContext } from 'react'
3
-
4
- import { AudioAnalysis } from './AudioAnalysis/AudioAnalysis.types'
5
- import {
6
- AudioRecording,
7
- RecordingConfig,
8
- StartRecordingResult,
9
- } from './ExpoAudioStream.types'
10
- import { UseAudioRecorderProps, useAudioRecorder } from './useAudioRecorder'
11
-
12
- export interface UseAudioRecorderState {
13
- startRecording: (_: RecordingConfig) => Promise<StartRecordingResult>
14
- stopRecording: () => Promise<AudioRecording | null>
15
- pauseRecording: () => void
16
- resumeRecording: () => void
17
- isRecording: boolean
18
- isPaused: boolean
19
- durationMs: number // Duration of the recording
20
- size: number // Size in bytes of the recorded audio
21
- analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag
22
- }
23
-
24
- const initContext: UseAudioRecorderState = {
25
- isRecording: false,
26
- isPaused: false,
27
- durationMs: 0,
28
- size: 0,
29
- startRecording: async () => {
30
- throw new Error('AudioRecorderProvider not found')
31
- },
32
- stopRecording: async () => {
33
- throw new Error('AudioRecorderProvider not found')
34
- },
35
- pauseRecording: () => {
36
- throw new Error('AudioRecorderProvider not found')
37
- },
38
- resumeRecording: () => {
39
- throw new Error('AudioRecorderProvider not found')
40
- },
41
- }
42
-
43
- const AudioRecorderContext = createContext<UseAudioRecorderState>(initContext)
44
-
45
- interface AudioRecorderProviderProps {
46
- children: React.ReactNode
47
- config?: UseAudioRecorderProps
48
- }
49
-
50
- export const AudioRecorderProvider: React.FC<AudioRecorderProviderProps> = ({
51
- children,
52
- config = {},
53
- }) => {
54
- const audioRecorder = useAudioRecorder(config)
55
- return (
56
- <AudioRecorderContext.Provider value={audioRecorder}>
57
- {children}
58
- </AudioRecorderContext.Provider>
59
- )
60
- }
61
-
62
- export const useSharedAudioRecorder = () => {
63
- const context = useContext(AudioRecorderContext)
64
- if (!context) {
65
- throw new Error(
66
- 'useSharedAudioRecorder must be used within an AudioRecorderProvider'
67
- )
68
- }
69
- return context
70
- }
@@ -1,80 +0,0 @@
1
- // packages/expo-audio-stream/src/ExpoAudioStream.types.ts
2
- import {
3
- AmplitudeAlgorithm,
4
- AudioAnalysis,
5
- AudioFeaturesOptions,
6
- } from './AudioAnalysis/AudioAnalysis.types'
7
- import { AudioAnalysisEvent } from './events'
8
-
9
- export interface AudioStreamStatus {
10
- isRecording: boolean
11
- isPaused: boolean
12
- durationMs: number
13
- size: number
14
- interval: number
15
- mimeType: string
16
- }
17
-
18
- export interface AudioDataEvent {
19
- data: string | Float32Array
20
- position: number
21
- fileUri: string
22
- eventDataSize: number
23
- totalSize: number
24
- }
25
-
26
- export type EncodingType = 'pcm_32bit' | 'pcm_16bit' | 'pcm_8bit'
27
- export type SampleRate = 16000 | 44100 | 48000
28
- export type BitDepth = 8 | 16 | 32
29
-
30
- export interface Chunk {
31
- text: string
32
- timestamp: [number, number | null]
33
- }
34
-
35
- export interface TranscriberData {
36
- id: string
37
- isBusy: boolean
38
- text: string
39
- startTime: number
40
- endTime: number
41
- chunks: Chunk[]
42
- }
43
-
44
- export interface AudioRecording {
45
- fileUri: string
46
- filename: string
47
- durationMs: number
48
- size: number
49
- mimeType: string
50
- channels: number
51
- bitDepth: BitDepth
52
- sampleRate: SampleRate
53
- transcripts?: TranscriberData[]
54
- wavPCMData?: Float32Array // Full PCM data for the recording in WAV format (only on web, for native use the fileUri)
55
- analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag
56
- }
57
-
58
- export interface StartRecordingResult {
59
- fileUri: string
60
- mimeType: string
61
- channels?: number
62
- bitDepth?: BitDepth
63
- sampleRate?: SampleRate
64
- }
65
-
66
- export interface RecordingConfig {
67
- sampleRate?: SampleRate // Sample rate for recording
68
- channels?: 1 | 2 // 1 or 2 (MONO or STEREO)
69
- encoding?: EncodingType // Encoding type for the recording
70
- interval?: number // Interval in milliseconds at which to emit recording data
71
-
72
- // Optional parameters for audio processing
73
- enableProcessing?: boolean // Boolean to enable/disable audio processing (default is false)
74
- pointsPerSecond?: number // Number of data points to extract per second of audio (default is 1000)
75
- algorithm?: AmplitudeAlgorithm // Algorithm to use for amplitude computation (default is "rms")
76
- features?: AudioFeaturesOptions // Feature options to extract (default is empty)
77
-
78
- onAudioStream?: (_: AudioDataEvent) => Promise<void> // Callback function to handle audio stream
79
- onAudioAnalysis?: (_: AudioAnalysisEvent) => Promise<void> // Callback function to handle audio features extraction results
80
- }
@@ -1,255 +0,0 @@
1
- // src/ExpoAudioStreamModule.web.ts
2
- import { EventEmitter } from 'expo-modules-core'
3
-
4
- import { AudioAnalysis } from './AudioAnalysis/AudioAnalysis.types'
5
- 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 { encodingToBitDepth } from './utils/encodingToBitDepth'
16
- import { writeWavHeader } from './utils/writeWavHeader'
17
-
18
- export interface EmitAudioEventProps {
19
- data: Float32Array
20
- position: number
21
- }
22
- export type EmitAudioEventFunction = (_: EmitAudioEventProps) => void
23
- export type EmitAudioAnalysisFunction = (_: AudioAnalysis) => void
24
-
25
- export interface ExpoAudioStreamWebProps {
26
- audioWorkletUrl: string
27
- featuresExtratorUrl: string
28
- }
29
-
30
- const logger = getLogger('ExpoAudioStreamWeb')
31
-
32
- export class ExpoAudioStreamWeb extends EventEmitter {
33
- customRecorder: WebRecorder | null
34
- audioChunks: ArrayBuffer[]
35
- isRecording: boolean
36
- isPaused: boolean
37
- recordingStartTime: number
38
- pausedTime: number
39
- currentDurationMs: number
40
- currentSize: number
41
- currentInterval: number
42
- lastEmittedSize: number
43
- lastEmittedTime: number
44
- streamUuid: string | null
45
- extension: 'webm' | 'wav' = 'wav' // Default extension is 'webm'
46
- recordingConfig?: RecordingConfig
47
- bitDepth: BitDepth // Bit depth of the audio
48
- audioWorkletUrl: string
49
- featuresExtratorUrl: string
50
-
51
- constructor({
52
- audioWorkletUrl,
53
- featuresExtratorUrl,
54
- }: ExpoAudioStreamWebProps) {
55
- const mockNativeModule = {
56
- addListener: () => {
57
- // Not used on web
58
- },
59
- removeListeners: () => {
60
- // Not used on web
61
- },
62
- }
63
- super(mockNativeModule) // Pass the mock native module to the parent class
64
-
65
- this.customRecorder = null
66
- this.audioChunks = []
67
- this.isRecording = false
68
- this.isPaused = false
69
- this.recordingStartTime = 0
70
- this.pausedTime = 0
71
- this.currentDurationMs = 0
72
- this.currentSize = 0
73
- this.bitDepth = 32 // Default
74
- this.currentInterval = 1000 // Default interval in ms
75
- this.lastEmittedSize = 0
76
- this.lastEmittedTime = 0
77
- this.streamUuid = null // Initialize UUID on first recording start
78
- this.audioWorkletUrl = audioWorkletUrl
79
- this.featuresExtratorUrl = featuresExtratorUrl
80
- }
81
-
82
- // Utility to handle user media stream
83
- async getMediaStream() {
84
- try {
85
- return await navigator.mediaDevices.getUserMedia({ audio: true })
86
- } catch (error) {
87
- console.error('Failed to get media stream:', error)
88
- throw error
89
- }
90
- }
91
-
92
- // Start recording with options
93
- async startRecording(recordingConfig: RecordingConfig = {}) {
94
- if (this.isRecording) {
95
- throw new Error('Recording is already in progress')
96
- }
97
-
98
- this.bitDepth = encodingToBitDepth({
99
- encoding: recordingConfig.encoding ?? 'pcm_32bit',
100
- })
101
-
102
- const audioContext = new (window.AudioContext ||
103
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
104
- // @ts-ignore - Allow webkitAudioContext for Safari
105
- window.webkitAudioContext)()
106
- const stream = await this.getMediaStream()
107
-
108
- const source = audioContext.createMediaStreamSource(stream)
109
-
110
- this.customRecorder = new WebRecorder({
111
- audioContext,
112
- source,
113
- recordingConfig,
114
- audioWorkletUrl: this.audioWorkletUrl,
115
- emitAudioEventCallback: ({
116
- data,
117
- position,
118
- }: EmitAudioEventProps) => {
119
- this.audioChunks.push(data)
120
- this.currentSize += data.byteLength
121
- this.emitAudioEvent({ data, position })
122
- this.lastEmittedTime = Date.now()
123
- this.lastEmittedSize = this.currentSize
124
- },
125
- emitAudioAnalysisCallback: (audioAnalysisData: AudioAnalysis) => {
126
- logger.log(`Emitted AudioAnalysis:`, audioAnalysisData)
127
- this.emit('AudioAnalysis', audioAnalysisData)
128
- },
129
- })
130
- await this.customRecorder.init()
131
- this.customRecorder.start()
132
-
133
- // // Set a timer to stop recording after 5 seconds
134
- // setTimeout(() => {
135
- // logger.log("AUTO Stopping recording");
136
- // this.customRecorder?.stopAndPlay();
137
- // this.isRecording = false;
138
- // }, 3000);
139
-
140
- this.isRecording = true
141
- this.recordingConfig = recordingConfig
142
- this.recordingStartTime = Date.now()
143
- this.pausedTime = 0
144
- this.lastEmittedSize = 0
145
- this.lastEmittedTime = 0
146
- this.streamUuid = Date.now().toString()
147
- const fileUri = `${this.streamUuid}.${this.extension}`
148
- const streamConfig: StartRecordingResult = {
149
- fileUri,
150
- mimeType: `audio/${this.extension}`,
151
- bitDepth: this.bitDepth,
152
- channels: recordingConfig.channels ?? 1,
153
- sampleRate: recordingConfig.sampleRate ?? 44100,
154
- }
155
- return streamConfig
156
- }
157
-
158
- emitAudioEvent({ data, position }: EmitAudioEventProps) {
159
- const fileUri = `${this.streamUuid}.${this.extension}`
160
- const audioEventPayload: AudioEventPayload = {
161
- fileUri,
162
- mimeType: `audio/${this.extension}`,
163
- lastEmittedSize: this.lastEmittedSize, // Since this might be continuously streaming, adjust accordingly
164
- deltaSize: data.byteLength,
165
- position,
166
- totalSize: this.currentSize,
167
- buffer: data,
168
- streamUuid: this.streamUuid ?? '', // Generate or manage UUID for stream identification
169
- }
170
-
171
- this.emit('AudioData', audioEventPayload)
172
- }
173
-
174
- // Stop recording
175
- async stopRecording(): Promise<AudioRecording> {
176
- if (!this.customRecorder) {
177
- throw new Error('Recorder is not initialized')
178
- }
179
-
180
- const fullPcmBufferArray = await this.customRecorder.stop()
181
-
182
- // concat all audio chunks
183
- logger.debug(`Stopped recording`, fullPcmBufferArray)
184
- this.isRecording = false
185
- this.currentDurationMs = Date.now() - this.recordingStartTime
186
-
187
- const wavConfig = {
188
- buffer: fullPcmBufferArray.buffer,
189
- sampleRate: this.recordingConfig?.sampleRate ?? 44100,
190
- numChannels: this.recordingConfig?.channels ?? 1,
191
- bitDepth: this.bitDepth,
192
- }
193
- logger.debug(`Writing wav header`, wavConfig)
194
- const wavBuffer = writeWavHeader(wavConfig).slice(0)
195
-
196
- // Create blob fileUri from audio chunks
197
- const blob = new Blob([wavBuffer], {
198
- type: `audio/${this.extension}`,
199
- })
200
- const fileUri = URL.createObjectURL(blob)
201
-
202
- const result: AudioRecording = {
203
- fileUri,
204
- filename: `${this.streamUuid}.${this.extension}`,
205
- wavPCMData: fullPcmBufferArray,
206
- bitDepth: this.bitDepth,
207
- channels: this.recordingConfig?.channels ?? 1,
208
- sampleRate: this.recordingConfig?.sampleRate ?? 44100,
209
- durationMs: this.currentDurationMs,
210
- size: this.currentSize,
211
- mimeType: `audio/${this.extension}`,
212
- }
213
-
214
- return result
215
- }
216
-
217
- // Pause recording
218
- async pauseRecording() {
219
- if (!this.isRecording || this.isPaused) {
220
- throw new Error('Recording is not active or already paused')
221
- }
222
-
223
- if (this.customRecorder) {
224
- this.customRecorder.pause()
225
- }
226
- this.isPaused = true
227
- this.pausedTime = Date.now()
228
- }
229
-
230
- // Resume recording
231
- async resumeRecording() {
232
- if (!this.isPaused) {
233
- throw new Error('Recording is not paused')
234
- }
235
-
236
- if (this.customRecorder) {
237
- this.customRecorder.resume()
238
- }
239
- this.isPaused = false
240
- this.recordingStartTime += Date.now() - this.pausedTime
241
- }
242
-
243
- // Get current status
244
- status() {
245
- const status: AudioStreamStatus = {
246
- isRecording: this.isRecording,
247
- isPaused: this.isPaused,
248
- durationMs: Date.now() - this.recordingStartTime,
249
- size: this.currentSize,
250
- interval: this.currentInterval,
251
- mimeType: `audio/${this.extension}`,
252
- }
253
- return status
254
- }
255
- }
@@ -1,31 +0,0 @@
1
- import { requireNativeModule } from 'expo-modules-core'
2
- import { Platform } from 'react-native'
3
-
4
- import {
5
- ExpoAudioStreamWeb,
6
- ExpoAudioStreamWebProps,
7
- } from './ExpoAudioStream.web'
8
-
9
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
- let ExpoAudioStreamModule: any
11
-
12
- if (Platform.OS === 'web') {
13
- let instance: ExpoAudioStreamWeb | null = null
14
-
15
- ExpoAudioStreamModule = (webProps: ExpoAudioStreamWebProps) => {
16
- if (!instance) {
17
- instance = new ExpoAudioStreamWeb(webProps)
18
- }
19
- return instance
20
- }
21
- ExpoAudioStreamModule.requestPermissionsAsync = async () => {
22
- return { status: 'granted' }
23
- }
24
- ExpoAudioStreamModule.getPermissionsAsync = async () => {
25
- return { status: 'granted' }
26
- }
27
- } else {
28
- ExpoAudioStreamModule = requireNativeModule('ExpoAudioStream')
29
- }
30
-
31
- export default ExpoAudioStreamModule