@siteed/expo-audio-stream 0.4.1 → 0.4.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.
@@ -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,MAAM,EAAE,IAAI,CAAC;IACb,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,IAAI,CAAC;IAC5C,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,qBAAqB,CAmJxB"}
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,MAAM,EAAE,IAAI,CAAC;IACb,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,IAAI,CAAC;IAC5C,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,qBAAqB,CAuKxB"}
@@ -14,9 +14,19 @@ export function useAudioRecorder({ onAudioStream, debug = false, }) {
14
14
  }
15
15
  if (isRecording || isPaused) {
16
16
  const interval = setInterval(() => {
17
- const status = ExpoAudioStreamModule.status();
18
- setDuration(status.duration);
19
- setSize(status.size);
17
+ try {
18
+ if (debug)
19
+ console.log(`[useAudioRecorder] Getting status`);
20
+ const status = ExpoAudioStreamModule.status();
21
+ if (debug) {
22
+ console.log(`[useAudioRecorder] Status:`, status);
23
+ }
24
+ setDuration(status.duration);
25
+ setSize(status.size);
26
+ }
27
+ catch (error) {
28
+ console.error(`[useAudioRecorder] Error getting status:`, error);
29
+ }
20
30
  }, 1000);
21
31
  return () => clearInterval(interval);
22
32
  }
@@ -27,57 +37,67 @@ export function useAudioRecorder({ onAudioStream, debug = false, }) {
27
37
  console.log(`[useAudioRecorder] Registering audio event listener`);
28
38
  }
29
39
  const subscribe = addAudioEventListener(async ({ fileUri, deltaSize, totalSize, lastEmittedSize, position, streamUuid, encoded, mimeType, buffer, }) => {
30
- if (debug) {
31
- console.log(`[useAudioRecorder] Received audio event:`, {
32
- fileUri,
33
- deltaSize,
34
- totalSize,
35
- mimeType,
36
- lastEmittedSize,
37
- streamUuid,
38
- encodedLength: encoded?.length,
39
- });
40
- }
41
- if (deltaSize > 0) {
42
- // Coming from native ( ios / android ) otherwise buffer is set
43
- if (Platform.OS !== "web") {
44
- // Read the audio file as a base64 string for comparison
45
- try {
46
- // convert encoded string to binary data
47
- const binaryData = atob(encoded);
48
- const content = new Uint8Array(binaryData.length);
49
- for (let i = 0; i < binaryData.length; i++) {
50
- content[i] = binaryData.charCodeAt(i);
40
+ try {
41
+ if (debug) {
42
+ console.log(`[useAudioRecorder] Received audio event:`, {
43
+ fileUri,
44
+ deltaSize,
45
+ totalSize,
46
+ mimeType,
47
+ lastEmittedSize,
48
+ streamUuid,
49
+ encodedLength: encoded?.length,
50
+ });
51
+ }
52
+ if (deltaSize > 0) {
53
+ // Coming from native ( ios / android ) otherwise buffer is set
54
+ if (Platform.OS !== "web") {
55
+ // Read the audio file as a base64 string for comparison
56
+ try {
57
+ // convert encoded string to binary data
58
+ const binaryData = atob(encoded);
59
+ const content = new Uint8Array(binaryData.length);
60
+ for (let i = 0; i < binaryData.length; i++) {
61
+ content[i] = binaryData.charCodeAt(i);
62
+ }
63
+ const audioBlob = new Blob([content], { type: mimeType });
64
+ // Below code is optional, used to compare encoded data to audio on file system
65
+ // Fetch the audio data from the fileUri
66
+ // const options = {
67
+ // encoding: FileSystem.EncodingType.Base64,
68
+ // position: from,
69
+ // length: deltaSize,
70
+ // };
71
+ // const base64Content = await FileSystem.readAsStringAsync(fileUri, options);
72
+ // const binaryData = atob(base64Content);
73
+ // const content = new Uint8Array(binaryData.length);
74
+ // for (let i = 0; i < binaryData.length; i++) {
75
+ // content[i] = binaryData.charCodeAt(i);
76
+ // }
77
+ // const audioBlob = new Blob([content], { type: 'application/octet-stream' }); // Create a Blob from the byte array
78
+ // console.debug(`Read audio file (len: ${content.length}) vs ${deltaSize}`)
79
+ onAudioStream?.({ buffer: audioBlob, position });
80
+ }
81
+ catch (error) {
82
+ console.error("[useAudioRecorder] Error reading audio file:", error);
51
83
  }
52
- const audioBlob = new Blob([content], { type: mimeType });
53
- // Below code is optional, used to compare encoded data to audio on file system
54
- // Fetch the audio data from the fileUri
55
- // const options = {
56
- // encoding: FileSystem.EncodingType.Base64,
57
- // position: from,
58
- // length: deltaSize,
59
- // };
60
- // const base64Content = await FileSystem.readAsStringAsync(fileUri, options);
61
- // const binaryData = atob(base64Content);
62
- // const content = new Uint8Array(binaryData.length);
63
- // for (let i = 0; i < binaryData.length; i++) {
64
- // content[i] = binaryData.charCodeAt(i);
65
- // }
66
- // const audioBlob = new Blob([content], { type: 'application/octet-stream' }); // Create a Blob from the byte array
67
- // console.debug(`Read audio file (len: ${content.length}) vs ${deltaSize}`)
68
- onAudioStream?.({ buffer: audioBlob, position });
69
84
  }
70
- catch (error) {
71
- console.error("[useAudioRecorder] Error reading audio file:", error);
85
+ else if (buffer) {
86
+ // Coming from web
87
+ onAudioStream?.({ buffer, position });
72
88
  }
73
89
  }
74
- else if (buffer) {
75
- // Coming from web
76
- onAudioStream?.({ buffer, position });
77
- }
90
+ }
91
+ catch (error) {
92
+ console.error("[useAudioRecorder] Error processing audio event:", error);
78
93
  }
79
94
  });
80
- return () => subscribe.remove();
95
+ return () => {
96
+ if (debug) {
97
+ console.log(`[useAudioRecorder] Removing audio event listener`);
98
+ }
99
+ subscribe.remove();
100
+ };
81
101
  }, [isRecording, onAudioStream, debug]);
82
102
  const startRecording = useCallback(async (recordingOptions) => {
83
103
  setIsRecording(true);
@@ -1 +1 @@
1
- {"version":3,"file":"useAudioRecording.js","sourceRoot":"","sources":["../src/useAudioRecording.ts"],"names":[],"mappings":"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","sourcesContent":["import { decode as atob } from \"base-64\";\nimport { 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 buffer: Blob;\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) => 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 const status: AudioStreamStatus = ExpoAudioStreamModule.status();\n setDuration(status.duration);\n setSize(status.size);\n }, 1000);\n return () => clearInterval(interval);\n }\n\n return () => null;\n }, [isRecording, isPaused, debug]);\n\n useEffect(() => {\n if (debug) {\n console.log(`[useAudioRecorder] Registering 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 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 // convert encoded string to binary data\n const binaryData = atob(encoded);\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: mimeType });\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: from,\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\n onAudioStream?.({ buffer: audioBlob, position });\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?.({ buffer, position });\n }\n }\n },\n );\n return () => subscribe.remove();\n }, [isRecording, onAudioStream, debug]);\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 { decode as atob } from \"base-64\";\nimport { 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 buffer: Blob;\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) => 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 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(`[useAudioRecorder] Registering 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 // convert encoded string to binary data\n const binaryData = atob(encoded);\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: mimeType });\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: from,\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\n onAudioStream?.({ buffer: audioBlob, position });\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?.({ buffer, position });\n }\n }\n } catch (error) {\n console.error(\n \"[useAudioRecorder] Error processing audio event:\",\n error,\n );\n }\n },\n );\n return () => {\n if (debug) {\n console.log(`[useAudioRecorder] Removing audio event listener`);\n }\n subscribe.remove();\n };\n }, [isRecording, onAudioStream, debug]);\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.1",
3
+ "version": "0.4.3",
4
4
  "description": "stream audio crossplatform",
5
5
  "license": "MIT",
6
6
  "main": "build/index.js",
@@ -44,9 +44,17 @@ export function useAudioRecorder({
44
44
  }
45
45
  if (isRecording || isPaused) {
46
46
  const interval = setInterval(() => {
47
- const status: AudioStreamStatus = ExpoAudioStreamModule.status();
48
- setDuration(status.duration);
49
- setSize(status.size);
47
+ try {
48
+ if (debug) console.log(`[useAudioRecorder] Getting status`);
49
+ const status: AudioStreamStatus = ExpoAudioStreamModule.status();
50
+ if (debug) {
51
+ console.log(`[useAudioRecorder] Status:`, status);
52
+ }
53
+ setDuration(status.duration);
54
+ setSize(status.size);
55
+ } catch (error) {
56
+ console.error(`[useAudioRecorder] Error getting status:`, error);
57
+ }
50
58
  }, 1000);
51
59
  return () => clearInterval(interval);
52
60
  }
@@ -70,61 +78,73 @@ export function useAudioRecorder({
70
78
  mimeType,
71
79
  buffer,
72
80
  }) => {
73
- if (debug) {
74
- console.log(`[useAudioRecorder] Received audio event:`, {
75
- fileUri,
76
- deltaSize,
77
- totalSize,
78
- mimeType,
79
- lastEmittedSize,
80
- streamUuid,
81
- encodedLength: encoded?.length,
82
- });
83
- }
84
- if (deltaSize > 0) {
85
- // Coming from native ( ios / android ) otherwise buffer is set
86
- if (Platform.OS !== "web") {
87
- // Read the audio file as a base64 string for comparison
88
- try {
89
- // convert encoded string to binary data
90
- const binaryData = atob(encoded);
91
- const content = new Uint8Array(binaryData.length);
92
- for (let i = 0; i < binaryData.length; i++) {
93
- content[i] = binaryData.charCodeAt(i);
94
- }
95
- const audioBlob = new Blob([content], { type: mimeType });
81
+ try {
82
+ if (debug) {
83
+ console.log(`[useAudioRecorder] Received audio event:`, {
84
+ fileUri,
85
+ deltaSize,
86
+ totalSize,
87
+ mimeType,
88
+ lastEmittedSize,
89
+ streamUuid,
90
+ encodedLength: encoded?.length,
91
+ });
92
+ }
93
+ if (deltaSize > 0) {
94
+ // Coming from native ( ios / android ) otherwise buffer is set
95
+ if (Platform.OS !== "web") {
96
+ // Read the audio file as a base64 string for comparison
97
+ try {
98
+ // convert encoded string to binary data
99
+ const binaryData = atob(encoded);
100
+ const content = new Uint8Array(binaryData.length);
101
+ for (let i = 0; i < binaryData.length; i++) {
102
+ content[i] = binaryData.charCodeAt(i);
103
+ }
104
+ const audioBlob = new Blob([content], { type: mimeType });
96
105
 
97
- // Below code is optional, used to compare encoded data to audio on file system
98
- // Fetch the audio data from the fileUri
99
- // const options = {
100
- // encoding: FileSystem.EncodingType.Base64,
101
- // position: from,
102
- // length: deltaSize,
103
- // };
104
- // const base64Content = await FileSystem.readAsStringAsync(fileUri, options);
105
- // const binaryData = atob(base64Content);
106
- // const content = new Uint8Array(binaryData.length);
107
- // for (let i = 0; i < binaryData.length; i++) {
108
- // content[i] = binaryData.charCodeAt(i);
109
- // }
110
- // const audioBlob = new Blob([content], { type: 'application/octet-stream' }); // Create a Blob from the byte array
111
- // console.debug(`Read audio file (len: ${content.length}) vs ${deltaSize}`)
106
+ // Below code is optional, used to compare encoded data to audio on file system
107
+ // Fetch the audio data from the fileUri
108
+ // const options = {
109
+ // encoding: FileSystem.EncodingType.Base64,
110
+ // position: from,
111
+ // length: deltaSize,
112
+ // };
113
+ // const base64Content = await FileSystem.readAsStringAsync(fileUri, options);
114
+ // const binaryData = atob(base64Content);
115
+ // const content = new Uint8Array(binaryData.length);
116
+ // for (let i = 0; i < binaryData.length; i++) {
117
+ // content[i] = binaryData.charCodeAt(i);
118
+ // }
119
+ // const audioBlob = new Blob([content], { type: 'application/octet-stream' }); // Create a Blob from the byte array
120
+ // console.debug(`Read audio file (len: ${content.length}) vs ${deltaSize}`)
112
121
 
113
- onAudioStream?.({ buffer: audioBlob, position });
114
- } catch (error) {
115
- console.error(
116
- "[useAudioRecorder] Error reading audio file:",
117
- error,
118
- );
122
+ onAudioStream?.({ buffer: audioBlob, position });
123
+ } catch (error) {
124
+ console.error(
125
+ "[useAudioRecorder] Error reading audio file:",
126
+ error,
127
+ );
128
+ }
129
+ } else if (buffer) {
130
+ // Coming from web
131
+ onAudioStream?.({ buffer, position });
119
132
  }
120
- } else if (buffer) {
121
- // Coming from web
122
- onAudioStream?.({ buffer, position });
123
133
  }
134
+ } catch (error) {
135
+ console.error(
136
+ "[useAudioRecorder] Error processing audio event:",
137
+ error,
138
+ );
124
139
  }
125
140
  },
126
141
  );
127
- return () => subscribe.remove();
142
+ return () => {
143
+ if (debug) {
144
+ console.log(`[useAudioRecorder] Removing audio event listener`);
145
+ }
146
+ subscribe.remove();
147
+ };
128
148
  }, [isRecording, onAudioStream, debug]);
129
149
 
130
150
  const startRecording = useCallback(