@siteed/expo-audio-stream 0.4.6 → 0.5.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.
@@ -1,7 +1,8 @@
1
1
  import { AudioStreamResult, RecordingOptions } from "./ExpoAudioStream.types";
2
2
  export interface AudioDataEvent {
3
- arrayBuffer: ArrayBuffer;
3
+ data: string | Blob;
4
4
  position: number;
5
+ size: number;
5
6
  }
6
7
  export interface UseAudioRecorderState {
7
8
  startRecording: (_: RecordingOptions) => Promise<string | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"useAudioRecording.d.ts","sourceRoot":"","sources":["../src/useAudioRecording.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,iBAAiB,EAEjB,gBAAgB,EACjB,MAAM,yBAAyB,CAAC;AAGjC,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,WAAW,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAChE,aAAa,EAAE,MAAM,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACvD,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,aAAa,EACb,KAAa,GACd,EAAE;IACD,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,qBAAqB,CAmMxB"}
1
+ {"version":3,"file":"useAudioRecording.d.ts","sourceRoot":"","sources":["../src/useAudioRecording.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,iBAAiB,EAEjB,gBAAgB,EACjB,MAAM,yBAAyB,CAAC;AAGjC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AACD,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAChE,aAAa,EAAE,MAAM,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACvD,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,aAAa,EACb,KAAa,GACd,EAAE;IACD,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,qBAAqB,CA6LxB"}
@@ -1,6 +1,5 @@
1
1
  import { Platform } from "expo-modules-core";
2
2
  import { useCallback, useEffect, useState } from "react";
3
- import { atob } from "react-native-quick-base64";
4
3
  import { addAudioEventListener } from ".";
5
4
  import ExpoAudioStreamModule from "./ExpoAudioStreamModule";
6
5
  export function useAudioRecorder({ onAudioStream, debug = false, }) {
@@ -36,11 +35,6 @@ export function useAudioRecorder({ onAudioStream, debug = false, }) {
36
35
  useEffect(() => {
37
36
  if (debug) {
38
37
  console.log(`[useAudioRecorder] Registering audio event listener`, onAudioStream);
39
- onAudioStream?.({
40
- arrayBuffer: new ArrayBuffer(0),
41
- position: 0,
42
- }).catch(console.error);
43
- console.log(`[useAudioRecorder] Registered audio event listener`);
44
38
  }
45
39
  const subscribe = addAudioEventListener(async ({ fileUri, deltaSize, totalSize, lastEmittedSize, position, streamUuid, encoded, mimeType, buffer, }) => {
46
40
  try {
@@ -49,6 +43,7 @@ export function useAudioRecorder({ onAudioStream, debug = false, }) {
49
43
  fileUri,
50
44
  deltaSize,
51
45
  totalSize,
46
+ position,
52
47
  mimeType,
53
48
  lastEmittedSize,
54
49
  streamUuid,
@@ -64,17 +59,18 @@ export function useAudioRecorder({ onAudioStream, debug = false, }) {
64
59
  console.error("[useAudioRecorder] Encoded audio data is missing");
65
60
  throw new Error("Encoded audio data is missing");
66
61
  }
67
- console.log(`encoded.length: ${encoded.length}`);
68
- const binaryData = atob(encoded);
69
- const bytes = new Uint8Array(binaryData.length);
70
- for (let i = 0; i < binaryData.length; i++) {
71
- bytes[i] = binaryData.charCodeAt(i) & 0xff; // Mask to 8 bits
72
- }
73
- const arrayBuffer = bytes.buffer;
74
- if (debug) {
75
- console.log(`[useAudioRecorder] Read audio file deltaSize: ${deltaSize} vs encoded.length: ${encoded.length}`);
76
- }
77
- onAudioStream?.({ arrayBuffer, position });
62
+ // const binaryData = atob(encoded);
63
+ // const bytes = new Uint8Array(binaryData.length);
64
+ // for (let i = 0; i < binaryData.length; i++) {
65
+ // bytes[i] = binaryData.charCodeAt(i) & 0xff; // Mask to 8 bits
66
+ // }
67
+ // const arrayBuffer = bytes.buffer;
68
+ // if (debug) {
69
+ // console.log(
70
+ // `[useAudioRecorder] Read audio file position=${position} deltaSize: ${deltaSize} vs encoded.length: ${encoded.length}`,
71
+ // );
72
+ // }
73
+ onAudioStream?.({ data: encoded, position, size: deltaSize });
78
74
  // Below code is optional, used to compare encoded data to audio on file system
79
75
  // Fetch the audio data from the fileUri
80
76
  // const options = {
@@ -97,8 +93,7 @@ export function useAudioRecorder({ onAudioStream, debug = false, }) {
97
93
  }
98
94
  else if (buffer) {
99
95
  // Coming from web
100
- const arrayBuffer = await buffer.arrayBuffer();
101
- onAudioStream?.({ arrayBuffer, position });
96
+ onAudioStream?.({ data: buffer, position, size: deltaSize });
102
97
  }
103
98
  }
104
99
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useAudioRecording.js","sourceRoot":"","sources":["../src/useAudioRecording.ts"],"names":[],"mappings":"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","sourcesContent":["import { Platform } from \"expo-modules-core\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport { atob } from \"react-native-quick-base64\";\n\nimport { addAudioEventListener } from \".\";\nimport {\n AudioStreamResult,\n AudioStreamStatus,\n RecordingOptions,\n} from \"./ExpoAudioStream.types\";\nimport ExpoAudioStreamModule from \"./ExpoAudioStreamModule\";\n\nexport interface AudioDataEvent {\n arrayBuffer: ArrayBuffer;\n position: number;\n}\nexport interface UseAudioRecorderState {\n startRecording: (_: RecordingOptions) => Promise<string | null>;\n stopRecording: () => Promise<AudioStreamResult | null>;\n pauseRecording: () => void;\n isRecording: boolean;\n isPaused: boolean;\n duration: number; // Duration of the recording\n size: number; // Size in bytes of the recorded audio\n}\n\nexport function useAudioRecorder({\n onAudioStream,\n debug = false,\n}: {\n onAudioStream?: (_: AudioDataEvent) => Promise<void>;\n debug?: boolean;\n}): UseAudioRecorderState {\n const [isRecording, setIsRecording] = useState(false);\n const [isPaused, setIsPaused] = useState(false);\n const [duration, setDuration] = useState(0);\n const [size, setSize] = useState(0);\n\n useEffect(() => {\n if (debug) {\n console.log(\n `[useAudioRecorder] isRecording: ${isRecording}, isPaused: ${isPaused}`,\n );\n }\n if (isRecording || isPaused) {\n const interval = setInterval(() => {\n try {\n if (debug) console.log(`[useAudioRecorder] Getting status`);\n const status: AudioStreamStatus = ExpoAudioStreamModule.status();\n if (debug) {\n console.log(`[useAudioRecorder] Status:`, status);\n }\n // Extract matching file from filesystem\n setDuration(status.duration);\n setSize(status.size);\n } catch (error) {\n console.error(`[useAudioRecorder] Error getting status:`, error);\n }\n }, 1000);\n return () => clearInterval(interval);\n }\n\n return () => null;\n }, [isRecording, isPaused, debug]);\n\n useEffect(() => {\n if (debug) {\n console.log(\n `[useAudioRecorder] Registering audio event listener`,\n onAudioStream,\n );\n onAudioStream?.({\n arrayBuffer: new ArrayBuffer(0),\n position: 0,\n }).catch(console.error);\n console.log(`[useAudioRecorder] Registered audio event listener`);\n }\n const subscribe = addAudioEventListener(\n async ({\n fileUri,\n deltaSize,\n totalSize,\n lastEmittedSize,\n position,\n streamUuid,\n encoded,\n mimeType,\n buffer,\n }) => {\n try {\n if (debug) {\n console.log(`[useAudioRecorder] Received audio event:`, {\n fileUri,\n deltaSize,\n totalSize,\n mimeType,\n lastEmittedSize,\n streamUuid,\n encodedLength: encoded?.length,\n });\n }\n if (deltaSize > 0) {\n // Coming from native ( ios / android ) otherwise buffer is set\n if (Platform.OS !== \"web\") {\n // Read the audio file as a base64 string for comparison\n try {\n if (!encoded) {\n console.error(\n \"[useAudioRecorder] Encoded audio data is missing\",\n );\n throw new Error(\"Encoded audio data is missing\");\n }\n console.log(`encoded.length: ${encoded.length}`);\n const binaryData = atob(encoded);\n const bytes = new Uint8Array(binaryData.length);\n for (let i = 0; i < binaryData.length; i++) {\n bytes[i] = binaryData.charCodeAt(i) & 0xff; // Mask to 8 bits\n }\n const arrayBuffer = bytes.buffer;\n\n if (debug) {\n console.log(\n `[useAudioRecorder] Read audio file deltaSize: ${deltaSize} vs encoded.length: ${encoded.length}`,\n );\n }\n\n onAudioStream?.({ arrayBuffer, position });\n\n // Below code is optional, used to compare encoded data to audio on file system\n // Fetch the audio data from the fileUri\n // const options = {\n // encoding: FileSystem.EncodingType.Base64,\n // position: lastEmittedSize,\n // length: deltaSize,\n // };\n // const base64Content = await FileSystem.readAsStringAsync(fileUri, options);\n // const binaryData = atob(base64Content);\n // const content = new Uint8Array(binaryData.length);\n // for (let i = 0; i < binaryData.length; i++) {\n // content[i] = binaryData.charCodeAt(i);\n // }\n // const audioBlob = new Blob([content], { type: 'application/octet-stream' }); // Create a Blob from the byte array\n // console.debug(`Read audio file (len: ${content.length}) vs ${deltaSize}`)\n } catch (error) {\n console.error(\n \"[useAudioRecorder] Error reading audio file:\",\n error,\n );\n }\n } else if (buffer) {\n // Coming from web\n const arrayBuffer = await buffer.arrayBuffer();\n onAudioStream?.({ arrayBuffer, position });\n }\n }\n } catch (error) {\n console.error(\n \"[useAudioRecorder] Error processing audio event:\",\n error,\n );\n }\n },\n );\n if (debug) {\n console.log(\n `[useAudioRecorder] Subscribed to audio event listener`,\n subscribe,\n );\n }\n return () => {\n if (debug) {\n console.log(`[useAudioRecorder] Removing audio event listener`);\n }\n subscribe.remove();\n };\n }, []);\n\n const startRecording = useCallback(\n async (recordingOptions: RecordingOptions) => {\n setIsRecording(true);\n setIsPaused(false);\n setSize(0);\n setDuration(0);\n try {\n if (debug) {\n console.log(`[useAudioRecorder] start recoding`, recordingOptions);\n }\n\n const fileUrl =\n await ExpoAudioStreamModule.startRecording(recordingOptions);\n\n return fileUrl;\n } catch (error) {\n console.error(\"[useAudioRecorder] Error starting recording:\", error);\n setIsRecording(false);\n }\n },\n [debug],\n );\n\n const stopRecording = useCallback(async () => {\n setIsRecording(false);\n setIsPaused(false);\n const result: AudioStreamResult =\n await ExpoAudioStreamModule.stopRecording();\n return result;\n }, []);\n\n const pauseRecording = useCallback(async () => {\n try {\n await ExpoAudioStreamModule.stopRecording();\n setIsPaused(true);\n setIsRecording(false);\n } catch (error) {\n console.error(\"[useAudioRecorder] Error pausing recording:\", error);\n }\n }, [debug]);\n\n return {\n startRecording,\n stopRecording,\n pauseRecording,\n isPaused,\n isRecording,\n duration,\n size,\n };\n}\n"]}
1
+ {"version":3,"file":"useAudioRecording.js","sourceRoot":"","sources":["../src/useAudioRecording.ts"],"names":[],"mappings":"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","sourcesContent":["import { Platform } from \"expo-modules-core\";\nimport { useCallback, useEffect, useState } from \"react\";\n\nimport { addAudioEventListener } from \".\";\nimport {\n AudioStreamResult,\n AudioStreamStatus,\n RecordingOptions,\n} from \"./ExpoAudioStream.types\";\nimport ExpoAudioStreamModule from \"./ExpoAudioStreamModule\";\n\nexport interface AudioDataEvent {\n data: string | Blob;\n position: number;\n size: number;\n}\nexport interface UseAudioRecorderState {\n startRecording: (_: RecordingOptions) => Promise<string | null>;\n stopRecording: () => Promise<AudioStreamResult | null>;\n pauseRecording: () => void;\n isRecording: boolean;\n isPaused: boolean;\n duration: number; // Duration of the recording\n size: number; // Size in bytes of the recorded audio\n}\n\nexport function useAudioRecorder({\n onAudioStream,\n debug = false,\n}: {\n onAudioStream?: (_: AudioDataEvent) => Promise<void>;\n debug?: boolean;\n}): UseAudioRecorderState {\n const [isRecording, setIsRecording] = useState(false);\n const [isPaused, setIsPaused] = useState(false);\n const [duration, setDuration] = useState(0);\n const [size, setSize] = useState(0);\n\n useEffect(() => {\n if (debug) {\n console.log(\n `[useAudioRecorder] isRecording: ${isRecording}, isPaused: ${isPaused}`,\n );\n }\n if (isRecording || isPaused) {\n const interval = setInterval(() => {\n try {\n if (debug) console.log(`[useAudioRecorder] Getting status`);\n const status: AudioStreamStatus = ExpoAudioStreamModule.status();\n if (debug) {\n console.log(`[useAudioRecorder] Status:`, status);\n }\n // Extract matching file from filesystem\n setDuration(status.duration);\n setSize(status.size);\n } catch (error) {\n console.error(`[useAudioRecorder] Error getting status:`, error);\n }\n }, 1000);\n return () => clearInterval(interval);\n }\n\n return () => null;\n }, [isRecording, isPaused, debug]);\n\n useEffect(() => {\n if (debug) {\n console.log(\n `[useAudioRecorder] Registering audio event listener`,\n onAudioStream,\n );\n }\n const subscribe = addAudioEventListener(\n async ({\n fileUri,\n deltaSize,\n totalSize,\n lastEmittedSize,\n position,\n streamUuid,\n encoded,\n mimeType,\n buffer,\n }) => {\n try {\n if (debug) {\n console.log(`[useAudioRecorder] Received audio event:`, {\n fileUri,\n deltaSize,\n totalSize,\n position,\n mimeType,\n lastEmittedSize,\n streamUuid,\n encodedLength: encoded?.length,\n });\n }\n if (deltaSize > 0) {\n // Coming from native ( ios / android ) otherwise buffer is set\n if (Platform.OS !== \"web\") {\n // Read the audio file as a base64 string for comparison\n try {\n if (!encoded) {\n console.error(\n \"[useAudioRecorder] Encoded audio data is missing\",\n );\n throw new Error(\"Encoded audio data is missing\");\n }\n // const binaryData = atob(encoded);\n // const bytes = new Uint8Array(binaryData.length);\n // for (let i = 0; i < binaryData.length; i++) {\n // bytes[i] = binaryData.charCodeAt(i) & 0xff; // Mask to 8 bits\n // }\n // const arrayBuffer = bytes.buffer;\n\n // if (debug) {\n // console.log(\n // `[useAudioRecorder] Read audio file position=${position} deltaSize: ${deltaSize} vs encoded.length: ${encoded.length}`,\n // );\n // }\n\n onAudioStream?.({ data: encoded, position, size: deltaSize });\n\n // Below code is optional, used to compare encoded data to audio on file system\n // Fetch the audio data from the fileUri\n // const options = {\n // encoding: FileSystem.EncodingType.Base64,\n // position: lastEmittedSize,\n // length: deltaSize,\n // };\n // const base64Content = await FileSystem.readAsStringAsync(fileUri, options);\n // const binaryData = atob(base64Content);\n // const content = new Uint8Array(binaryData.length);\n // for (let i = 0; i < binaryData.length; i++) {\n // content[i] = binaryData.charCodeAt(i);\n // }\n // const audioBlob = new Blob([content], { type: 'application/octet-stream' }); // Create a Blob from the byte array\n // console.debug(`Read audio file (len: ${content.length}) vs ${deltaSize}`)\n } catch (error) {\n console.error(\n \"[useAudioRecorder] Error reading audio file:\",\n error,\n );\n }\n } else if (buffer) {\n // Coming from web\n onAudioStream?.({ data: buffer, position, size: deltaSize });\n }\n }\n } catch (error) {\n console.error(\n \"[useAudioRecorder] Error processing audio event:\",\n error,\n );\n }\n },\n );\n if (debug) {\n console.log(\n `[useAudioRecorder] Subscribed to audio event listener`,\n subscribe,\n );\n }\n return () => {\n if (debug) {\n console.log(`[useAudioRecorder] Removing audio event listener`);\n }\n subscribe.remove();\n };\n }, []);\n\n const startRecording = useCallback(\n async (recordingOptions: RecordingOptions) => {\n setIsRecording(true);\n setIsPaused(false);\n setSize(0);\n setDuration(0);\n try {\n if (debug) {\n console.log(`[useAudioRecorder] start recoding`, recordingOptions);\n }\n\n const fileUrl =\n await ExpoAudioStreamModule.startRecording(recordingOptions);\n\n return fileUrl;\n } catch (error) {\n console.error(\"[useAudioRecorder] Error starting recording:\", error);\n setIsRecording(false);\n }\n },\n [debug],\n );\n\n const stopRecording = useCallback(async () => {\n setIsRecording(false);\n setIsPaused(false);\n const result: AudioStreamResult =\n await ExpoAudioStreamModule.stopRecording();\n return result;\n }, []);\n\n const pauseRecording = useCallback(async () => {\n try {\n await ExpoAudioStreamModule.stopRecording();\n setIsPaused(true);\n setIsRecording(false);\n } catch (error) {\n console.error(\"[useAudioRecorder] Error pausing recording:\", error);\n }\n }, [debug]);\n\n return {\n startRecording,\n stopRecording,\n pauseRecording,\n isPaused,\n isRecording,\n duration,\n size,\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@siteed/expo-audio-stream",
3
- "version": "0.4.6",
3
+ "version": "0.5.0",
4
4
  "description": "stream audio crossplatform",
5
5
  "license": "MIT",
6
6
  "main": "build/index.js",
@@ -39,6 +39,7 @@
39
39
  "@expo/config-plugins": "^7.9.1",
40
40
  "@release-it/conventional-changelog": "^8.0.1",
41
41
  "@types/debug": "^4.1.12",
42
+ "@types/node": "^20.12.7",
42
43
  "@types/react": "^18.0.25",
43
44
  "@typescript-eslint/eslint-plugin": "^7.7.0",
44
45
  "@typescript-eslint/parser": "^7.7.0",
@@ -1,6 +1,5 @@
1
1
  import { Platform } from "expo-modules-core";
2
2
  import { useCallback, useEffect, useState } from "react";
3
- import { atob } from "react-native-quick-base64";
4
3
 
5
4
  import { addAudioEventListener } from ".";
6
5
  import {
@@ -11,8 +10,9 @@ import {
11
10
  import ExpoAudioStreamModule from "./ExpoAudioStreamModule";
12
11
 
13
12
  export interface AudioDataEvent {
14
- arrayBuffer: ArrayBuffer;
13
+ data: string | Blob;
15
14
  position: number;
15
+ size: number;
16
16
  }
17
17
  export interface UseAudioRecorderState {
18
18
  startRecording: (_: RecordingOptions) => Promise<string | null>;
@@ -69,11 +69,6 @@ export function useAudioRecorder({
69
69
  `[useAudioRecorder] Registering audio event listener`,
70
70
  onAudioStream,
71
71
  );
72
- onAudioStream?.({
73
- arrayBuffer: new ArrayBuffer(0),
74
- position: 0,
75
- }).catch(console.error);
76
- console.log(`[useAudioRecorder] Registered audio event listener`);
77
72
  }
78
73
  const subscribe = addAudioEventListener(
79
74
  async ({
@@ -93,6 +88,7 @@ export function useAudioRecorder({
93
88
  fileUri,
94
89
  deltaSize,
95
90
  totalSize,
91
+ position,
96
92
  mimeType,
97
93
  lastEmittedSize,
98
94
  streamUuid,
@@ -110,21 +106,20 @@ export function useAudioRecorder({
110
106
  );
111
107
  throw new Error("Encoded audio data is missing");
112
108
  }
113
- console.log(`encoded.length: ${encoded.length}`);
114
- const binaryData = atob(encoded);
115
- const bytes = new Uint8Array(binaryData.length);
116
- for (let i = 0; i < binaryData.length; i++) {
117
- bytes[i] = binaryData.charCodeAt(i) & 0xff; // Mask to 8 bits
118
- }
119
- const arrayBuffer = bytes.buffer;
109
+ // const binaryData = atob(encoded);
110
+ // const bytes = new Uint8Array(binaryData.length);
111
+ // for (let i = 0; i < binaryData.length; i++) {
112
+ // bytes[i] = binaryData.charCodeAt(i) & 0xff; // Mask to 8 bits
113
+ // }
114
+ // const arrayBuffer = bytes.buffer;
120
115
 
121
- if (debug) {
122
- console.log(
123
- `[useAudioRecorder] Read audio file deltaSize: ${deltaSize} vs encoded.length: ${encoded.length}`,
124
- );
125
- }
116
+ // if (debug) {
117
+ // console.log(
118
+ // `[useAudioRecorder] Read audio file position=${position} deltaSize: ${deltaSize} vs encoded.length: ${encoded.length}`,
119
+ // );
120
+ // }
126
121
 
127
- onAudioStream?.({ arrayBuffer, position });
122
+ onAudioStream?.({ data: encoded, position, size: deltaSize });
128
123
 
129
124
  // Below code is optional, used to compare encoded data to audio on file system
130
125
  // Fetch the audio data from the fileUri
@@ -149,8 +144,7 @@ export function useAudioRecorder({
149
144
  }
150
145
  } else if (buffer) {
151
146
  // Coming from web
152
- const arrayBuffer = await buffer.arrayBuffer();
153
- onAudioStream?.({ arrayBuffer, position });
147
+ onAudioStream?.({ data: buffer, position, size: deltaSize });
154
148
  }
155
149
  }
156
150
  } catch (error) {