@siteed/expo-audio-stream 1.7.2 → 1.8.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +17 -1
  2. package/README.md +6 -1
  3. package/android/src/main/java/net/siteed/audiostream/AudioFileHandler.kt +39 -0
  4. package/android/src/main/java/net/siteed/audiostream/AudioRecorderManager.kt +124 -12
  5. package/android/src/main/java/net/siteed/audiostream/RecordingConfig.kt +26 -2
  6. package/build/AudioRecorder.provider.d.ts.map +1 -1
  7. package/build/AudioRecorder.provider.js +1 -0
  8. package/build/AudioRecorder.provider.js.map +1 -1
  9. package/build/ExpoAudioStream.types.d.ts +35 -1
  10. package/build/ExpoAudioStream.types.d.ts.map +1 -1
  11. package/build/ExpoAudioStream.types.js.map +1 -1
  12. package/build/ExpoAudioStream.web.d.ts +14 -3
  13. package/build/ExpoAudioStream.web.d.ts.map +1 -1
  14. package/build/ExpoAudioStream.web.js +102 -38
  15. package/build/ExpoAudioStream.web.js.map +1 -1
  16. package/build/WebRecorder.web.d.ts +11 -2
  17. package/build/WebRecorder.web.d.ts.map +1 -1
  18. package/build/WebRecorder.web.js +178 -43
  19. package/build/WebRecorder.web.js.map +1 -1
  20. package/build/events.d.ts +6 -0
  21. package/build/events.d.ts.map +1 -1
  22. package/build/events.js.map +1 -1
  23. package/build/useAudioRecorder.d.ts +3 -2
  24. package/build/useAudioRecorder.d.ts.map +1 -1
  25. package/build/useAudioRecorder.js +46 -5
  26. package/build/useAudioRecorder.js.map +1 -1
  27. package/ios/AudioStreamManager.swift +127 -8
  28. package/ios/AudioStreamManagerDelegate.swift +8 -2
  29. package/ios/ExpoAudioStreamModule.swift +61 -46
  30. package/ios/RecordingResult.swift +2 -0
  31. package/ios/RecordingSettings.swift +63 -3
  32. package/package.json +1 -1
  33. package/src/AudioRecorder.provider.tsx +1 -0
  34. package/src/ExpoAudioStream.types.ts +38 -1
  35. package/src/ExpoAudioStream.web.ts +114 -38
  36. package/src/WebRecorder.web.ts +210 -64
  37. package/src/events.ts +7 -0
  38. package/src/useAudioRecorder.tsx +70 -8
package/CHANGELOG.md CHANGED
@@ -8,13 +8,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
  ## [Unreleased]
9
9
 
10
10
 
11
+ ## [1.8.0] - 2025-01-10
12
+ - feat(audio): implement audio compression support ([ff4e060](https://github.com/deeeed/expo-audio-stream/commit/ff4e060fef1061804c1cc0126d4344d2d50daa9a))
13
+
11
14
  ## [1.7.2] - 2025-01-07
12
15
  - fix(audio-stream): correct WAV header handling in web audio recording ([9ba7de5](https://github.com/deeeed/expo-audio-stream/commit/9ba7de5b96ca4cc937dea261c80d3fda9c99e8f4))
13
16
 
17
+
14
18
  ## [1.7.1] - 2025-01-07
15
19
  - update notification to avoid triggering new alerts (#71) ([32dcfc5](https://github.com/deeeed/expo-audio-stream/commit/32dcfc55daf3236babefc17016f329c177d466fd))
16
20
 
17
21
 
22
+
18
23
  ## [1.7.0] - 2025-01-05
19
24
  - feat(playground): enhance app configuration and build setup for production deployment (#58) ([929d443](https://github.com/deeeed/expo-audio-stream/commit/929d443145378b1430d215db5c00b13758420e2b))
20
25
  - chore(expo-audio-stream): release @siteed/expo-audio-stream@1.6.1 ([084e8ad](https://github.com/deeeed/expo-audio-stream/commit/084e8adb91da7874c9e608b55d9c7b2ffd7a8327))
@@ -25,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
25
30
 
26
31
 
27
32
 
33
+
28
34
  ## [1.6.1] - 2024-12-11
29
35
  - chore(expo-audio-stream): remove git commit step from publish script ([4a772ce](https://github.com/deeeed/expo-audio-stream/commit/4a772ce93bb7405d9b8e981f46bdf8941a71ecfe))
30
36
  - chore: more publishing automation ([3693021](https://github.com/deeeed/expo-audio-stream/commit/369302107f9dca9dddd8ae68e6214481a39976ac))
@@ -39,6 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
39
45
 
40
46
 
41
47
 
48
+
42
49
  ## [1.5.0] - 2024-12-10
43
50
  - UNPUBLISHED because of a bug in the build system
44
51
 
@@ -46,6 +53,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
46
53
 
47
54
 
48
55
 
56
+
49
57
  ## [1.4.0] - 2024-12-05
50
58
  - chore: remove unusded dependencies ([ad81dd5](https://github.com/deeeed/expo-audio-stream/commit/ad81dd560c93dd1d04995a323a4ae72d4de20f3e))
51
59
 
@@ -53,6 +61,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
53
61
 
54
62
 
55
63
 
64
+
56
65
  ## [1.3.1] - 2024-12-05
57
66
  - feat(web): implement throttling and optimize event processing (#49) ([da28765](https://github.com/deeeed/expo-audio-stream/commit/da2876524c2c9d6e0a980fde40a0197b929d8a7f))
58
67
 
@@ -60,6 +69,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
60
69
 
61
70
 
62
71
 
72
+
63
73
  ## [1.3.0] - 2024-11-28
64
74
  ### Added
65
75
  - refactor(permissions): standardize permission status response structure across platforms (#44) ([7c9c800](https://github.com/deeeed/expo-audio-stream/commit/7c9c800d83b7cea3516643371484d5e1f3b99e4c))
@@ -72,6 +82,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
72
82
 
73
83
 
74
84
 
85
+
75
86
  ## [1.2.5] - 2024-11-12
76
87
  ### Added
77
88
  - docs(license): add MIT license to all packages (6 files changed)
@@ -81,6 +92,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
81
92
 
82
93
 
83
94
 
95
+
84
96
  ## [1.2.4] - 2024-11-05
85
97
  ### Changed
86
98
  - Android minimum audio interval set to 10ms.
@@ -93,6 +105,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
93
105
 
94
106
 
95
107
 
108
+
96
109
  ## [1.2.0] - 2024-10-24
97
110
  ### Added
98
111
  - Feature: Keep device awake during recording with `keepAwake` option
@@ -105,6 +118,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
105
118
 
106
119
 
107
120
 
121
+
108
122
  ## [1.1.17] - 2024-10-21
109
123
  ### Added
110
124
  - Support bluetooth headset on ios
@@ -114,6 +128,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
114
128
 
115
129
 
116
130
 
131
+
117
132
  ## [1.0.0] - 2024-04-01
118
133
  ### Added
119
134
  - Initial release of @siteed/expo-audio-stream.
@@ -124,7 +139,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
124
139
  - Feature: Audio features extraction during recording.
125
140
  - Feature: Consistent WAV PCM recording format across all platforms.
126
141
 
127
- [unreleased]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-stream@1.7.2...HEAD
142
+ [unreleased]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-stream@1.8.0...HEAD
143
+ [1.8.0]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-stream@1.7.2...@siteed/expo-audio-stream@1.8.0
128
144
  [1.7.2]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-stream@1.7.1...@siteed/expo-audio-stream@1.7.2
129
145
  [1.7.1]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-stream@1.7.0...@siteed/expo-audio-stream@1.7.1
130
146
  [1.7.0]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-stream@1.6.1...@siteed/expo-audio-stream@1.7.0
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  <div align="center">
10
10
  <h2 align="center">
11
11
  <br />
12
- <strong>Comprehensive library designed to facilitate real-time audio processing and streaming across iOS, Android, and web platforms.
12
+ <strong>Comprehensive library designed to facilitate real-time audio processing and streaming across iOS, Android, and web platforms, with support for dual-stream recording and audio compression.
13
13
  <br />
14
14
  <br />
15
15
  <a href="https://deeeed.github.io/expo-audio-stream/playground/">
@@ -32,6 +32,11 @@
32
32
  ## Features
33
33
 
34
34
  - Real-time audio streaming across iOS, Android, and web.
35
+ - Dual-stream recording capabilities:
36
+ - Simultaneous raw PCM and compressed audio recording
37
+ - Compression formats: OPUS or AAC
38
+ - Configurable bitrate for compressed audio
39
+ - Optimized storage for both high-quality and compressed formats
35
40
  - Configurable intervals for audio buffer receipt.
36
41
  - Automated microphone permissions setup in managed Expo projects.
37
42
  - Background audio recording on iOS.
@@ -1,9 +1,11 @@
1
1
  package net.siteed.audiostream
2
2
 
3
+ import android.util.Log
3
4
  import java.io.File
4
5
  import java.io.IOException
5
6
  import java.io.OutputStream
6
7
  import java.io.RandomAccessFile
8
+ import java.util.UUID
7
9
 
8
10
  class AudioFileHandler(private val filesDir: File) {
9
11
  // Method to write WAV file header
@@ -89,4 +91,41 @@ class AudioFileHandler(private val filesDir: File) {
89
91
  it.delete()
90
92
  }
91
93
  }
94
+
95
+ fun createAudioFile(extension: String): File {
96
+ val timestamp = System.currentTimeMillis()
97
+ val uuid = UUID.randomUUID().toString()
98
+ val filename = "recording_${timestamp}_${uuid}.${extension}"
99
+
100
+ return try {
101
+ File(filesDir, filename).apply {
102
+ parentFile?.mkdirs() // Create directories if they don't exist
103
+ createNewFile() // Create the file
104
+ }
105
+ } catch (e: Exception) {
106
+ Log.e(Constants.TAG, "Failed to create audio file", e)
107
+ throw e
108
+ }
109
+ }
110
+
111
+ fun deleteFile(file: File?): Boolean {
112
+ return try {
113
+ if (file == null) {
114
+ Log.w(Constants.TAG, "Attempted to delete null file")
115
+ false
116
+ } else if (!file.exists()) {
117
+ Log.w(Constants.TAG, "File does not exist: ${file.absolutePath}")
118
+ false
119
+ } else {
120
+ val wasDeleted = file.delete()
121
+ if (!wasDeleted) {
122
+ Log.w(Constants.TAG, "Failed to delete file: ${file.absolutePath}")
123
+ }
124
+ wasDeleted
125
+ }
126
+ } catch (e: Exception) {
127
+ Log.e(Constants.TAG, "Error deleting file: ${file?.absolutePath}", e)
128
+ false
129
+ }
130
+ }
92
131
  }
@@ -45,6 +45,7 @@ class AudioRecorderManager(
45
45
  private var lastPauseTime = 0L
46
46
  private var pausedDuration = 0L
47
47
  private var lastEmittedSize = 0L
48
+ private var lastEmittedCompressedSize = 0L
48
49
  private val mainHandler = Handler(Looper.getMainLooper())
49
50
  private val audioRecordLock = Any()
50
51
  private var audioFileHandler: AudioFileHandler = AudioFileHandler(filesDir)
@@ -59,6 +60,9 @@ class AudioRecorderManager(
59
60
  private var wasWakeLockEnabled = false
60
61
  private val notificationManager = AudioNotificationManager.getInstance(context)
61
62
 
63
+ private var compressedRecorder: MediaRecorder? = null
64
+ private var compressedFile: File? = null
65
+
62
66
  companion object {
63
67
  @SuppressLint("StaticFieldLeak")
64
68
  @Volatile
@@ -117,17 +121,39 @@ class AudioRecorderManager(
117
121
 
118
122
  if (!initializeAudioRecord(promise)) return
119
123
 
124
+ if (recordingConfig.enableCompressedOutput && !initializeCompressedRecorder(
125
+ if (recordingConfig.compressedFormat == "aac") "aac" else "opus",
126
+ promise
127
+ )) return
128
+
120
129
  if (!initializeRecordingResources(audioFormatInfo.fileExtension, promise)) return
121
130
 
122
131
  if (!startRecordingProcess(promise)) return
123
132
 
124
- // Return success result
133
+ // Start compressed recording if enabled
134
+ try {
135
+ compressedRecorder?.start()
136
+ } catch (e: Exception) {
137
+ Log.e(Constants.TAG, "Failed to start compressed recording", e)
138
+ cleanup()
139
+ promise.reject("COMPRESSED_START_FAILED", "Failed to start compressed recording", e)
140
+ return
141
+ }
142
+
143
+ // Return success result with both file URIs
125
144
  val result = bundleOf(
126
145
  "fileUri" to audioFile?.toURI().toString(),
127
146
  "channels" to recordingConfig.channels,
128
147
  "bitDepth" to AudioFormatUtils.getBitDepth(recordingConfig.encoding),
129
148
  "sampleRate" to recordingConfig.sampleRate,
130
- "mimeType" to mimeType
149
+ "mimeType" to mimeType,
150
+ "compression" to if (compressedFile != null) bundleOf(
151
+ "mimeType" to if (recordingConfig.compressedFormat == "aac") "audio/aac" else "audio/opus",
152
+ "bitrate" to recordingConfig.compressedBitRate,
153
+ "format" to recordingConfig.compressedFormat,
154
+ "size" to 0,
155
+ "compressedFileUri" to compressedFile?.toURI().toString()
156
+ ) else null
131
157
  )
132
158
  promise.resolve(result)
133
159
 
@@ -458,21 +484,30 @@ class AudioRecorderManager(
458
484
  // Calculate duration based on the data size and byte rate
459
485
  val duration = if (byteRate > 0) (dataFileSize * 1000 / byteRate) else 0
460
486
 
487
+ compressedRecorder?.apply {
488
+ stop()
489
+ release()
490
+ }
491
+ compressedRecorder = null
492
+
493
+
461
494
  // Create result bundle
462
495
  val result = bundleOf(
463
496
  "fileUri" to audioFile?.toURI().toString(),
464
497
  "filename" to audioFile?.name,
465
498
  "durationMs" to duration,
466
499
  "channels" to recordingConfig.channels,
467
- "bitDepth" to when (recordingConfig.encoding) {
468
- "pcm_8bit" -> 8
469
- "pcm_16bit" -> 16
470
- "pcm_32bit" -> 32
471
- else -> 16 // Default to 16 if the encoding is not recognized
472
- },
500
+ "bitDepth" to AudioFormatUtils.getBitDepth(recordingConfig.encoding),
473
501
  "sampleRate" to recordingConfig.sampleRate,
474
502
  "size" to fileSize,
475
- "mimeType" to mimeType
503
+ "mimeType" to mimeType,
504
+ "compression" to if (compressedFile != null) bundleOf(
505
+ "size" to compressedFile?.length(),
506
+ "mimeType" to if (recordingConfig.compressedFormat == "aac") "audio/aac" else "audio/opus",
507
+ "bitrate" to recordingConfig.compressedBitRate,
508
+ "format" to recordingConfig.compressedFormat,
509
+ "compressedFileUri" to compressedFile?.toURI().toString()
510
+ ) else null
476
511
  )
477
512
  promise.resolve(result)
478
513
 
@@ -560,15 +595,27 @@ class AudioRecorderManager(
560
595
  }
561
596
 
562
597
  // "audio/opus", "audio/aac" -> getCompressedAudioDuration(audioFile)
563
- else -> 0
598
+ else -> totalRecordedTime
564
599
  }
600
+
601
+ val compressionBundle = if (recordingConfig.enableCompressedOutput) {
602
+ bundleOf(
603
+ "size" to (compressedFile?.length() ?: 0),
604
+ "mimeType" to if (recordingConfig.compressedFormat == "aac") "audio/aac" else "audio/opus",
605
+ "bitrate" to recordingConfig.compressedBitRate,
606
+ "format" to recordingConfig.compressedFormat
607
+ )
608
+ } else null
609
+
610
+
565
611
  return bundleOf(
566
612
  "durationMs" to duration,
567
613
  "isRecording" to isRecording.get(),
568
614
  "isPaused" to isPaused.get(),
569
615
  "mimeType" to mimeType,
570
616
  "size" to totalDataSize,
571
- "interval" to recordingConfig.interval
617
+ "interval" to recordingConfig.interval,
618
+ "compression" to compressionBundle
572
619
  )
573
620
  }
574
621
  }
@@ -704,6 +751,36 @@ class AudioRecorderManager(
704
751
  val positionInMs =
705
752
  (from * 1000) / (recordingConfig.sampleRate * recordingConfig.channels * (if (recordingConfig.encoding == "pcm_8bit") 8 else 16) / 8)
706
753
 
754
+ val compressionBundle = if (recordingConfig.enableCompressedOutput) {
755
+ val compressedSize = compressedFile?.length() ?: 0
756
+ val eventDataSize = compressedSize - lastEmittedCompressedSize
757
+
758
+ // Read the new compressed data
759
+ val compressedData = if (eventDataSize > 0) {
760
+ try {
761
+ compressedFile?.inputStream()?.use { input ->
762
+ input.skip(lastEmittedCompressedSize)
763
+ val buffer = ByteArray(eventDataSize.toInt())
764
+ input.read(buffer)
765
+ audioDataEncoder.encodeToBase64(buffer)
766
+ }
767
+ } catch (e: Exception) {
768
+ Log.e(Constants.TAG, "Failed to read compressed data", e)
769
+ null
770
+ }
771
+ } else null
772
+
773
+ lastEmittedCompressedSize = compressedSize
774
+
775
+ bundleOf(
776
+ "position" to positionInMs,
777
+ "fileUri" to compressedFile?.toURI().toString(),
778
+ "eventDataSize" to eventDataSize,
779
+ "totalSize" to compressedSize,
780
+ "data" to compressedData
781
+ )
782
+ } else null
783
+
707
784
  mainHandler.post {
708
785
  try {
709
786
  eventSender.sendExpoEvent(
@@ -715,7 +792,8 @@ class AudioRecorderManager(
715
792
  "position" to positionInMs,
716
793
  "mimeType" to mimeType,
717
794
  "totalSize" to fileSize,
718
- "streamUuid" to streamUuid
795
+ "streamUuid" to streamUuid,
796
+ "compression" to compressionBundle
719
797
  )
720
798
  )
721
799
  } catch (e: Exception) {
@@ -787,4 +865,38 @@ class AudioRecorderManager(
787
865
  releaseWakeLock()
788
866
  }
789
867
  }
868
+
869
+ private fun initializeCompressedRecorder(fileExtension: String, promise: Promise): Boolean {
870
+ try {
871
+ // Use the existing audioFileHandler instance
872
+ compressedFile = audioFileHandler.createAudioFile(fileExtension)
873
+
874
+ compressedRecorder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
875
+ MediaRecorder(context)
876
+ } else {
877
+ @Suppress("DEPRECATION")
878
+ MediaRecorder()
879
+ }
880
+
881
+ compressedRecorder?.apply {
882
+ setAudioSource(MediaRecorder.AudioSource.MIC)
883
+ setOutputFormat(if (recordingConfig.compressedFormat == "aac")
884
+ MediaRecorder.OutputFormat.AAC_ADTS
885
+ else MediaRecorder.OutputFormat.OGG)
886
+ setAudioEncoder(if (recordingConfig.compressedFormat == "aac")
887
+ MediaRecorder.AudioEncoder.AAC
888
+ else MediaRecorder.AudioEncoder.OPUS)
889
+ setAudioChannels(recordingConfig.channels)
890
+ setAudioSamplingRate(recordingConfig.sampleRate)
891
+ setAudioEncodingBitRate(recordingConfig.compressedBitRate)
892
+ setOutputFile(compressedFile?.absolutePath)
893
+ prepare()
894
+ }
895
+ return true
896
+ } catch (e: Exception) {
897
+ Log.e(Constants.TAG, "Failed to initialize compressed recorder", e)
898
+ promise.reject("COMPRESSED_INIT_FAILED", "Failed to initialize compressed recorder", e)
899
+ return false
900
+ }
901
+ }
790
902
  }
@@ -15,7 +15,10 @@ data class RecordingConfig(
15
15
  val showNotification: Boolean = false,
16
16
  val showWaveformInNotification: Boolean = false,
17
17
  val notification: NotificationConfig = NotificationConfig(),
18
- val features: Map<String, Boolean> = emptyMap()
18
+ val features: Map<String, Boolean> = emptyMap(),
19
+ val enableCompressedOutput: Boolean = false,
20
+ val compressedFormat: String = "opus",
21
+ val compressedBitRate: Int = 24000,
19
22
  ) {
20
23
  companion object {
21
24
  fun fromMap(options: Map<String, Any?>?): Result<Pair<RecordingConfig, AudioFormatInfo>> {
@@ -36,6 +39,24 @@ data class RecordingConfig(
36
39
  val notificationMap = options.getTypedMap<Any?>("notification") { true }
37
40
  val notificationConfig = NotificationConfig.fromMap(notificationMap)
38
41
 
42
+ // Parse compression config
43
+ val compressionMap = options.getTypedMap<Any?>("compression") { true }
44
+ val enableCompressedOutput = compressionMap["enabled"] as? Boolean ?: false
45
+ val compressedFormat = (compressionMap["format"] as? String)?.lowercase() ?: "aac"
46
+ val compressedBitRate = (compressionMap["bitrate"] as? Number)?.toInt() ?: 128000
47
+
48
+ // Validate bitrate if compression is enabled
49
+ if (enableCompressedOutput) {
50
+ when {
51
+ compressedBitRate < 8000 -> return Result.failure(
52
+ IllegalArgumentException("Bitrate must be at least 8000 bps")
53
+ )
54
+ compressedBitRate > 960000 -> return Result.failure(
55
+ IllegalArgumentException("Bitrate cannot exceed 960000 bps")
56
+ )
57
+ }
58
+ }
59
+
39
60
  // Initialize the recording configuration
40
61
  val tempRecordingConfig = RecordingConfig(
41
62
  sampleRate = options.getNumberOrDefault("sampleRate", Constants.DEFAULT_SAMPLE_RATE),
@@ -49,7 +70,10 @@ data class RecordingConfig(
49
70
  showNotification = options.getBooleanOrDefault("showNotification", false),
50
71
  showWaveformInNotification = options.getBooleanOrDefault("showWaveformInNotification", false),
51
72
  notification = notificationConfig,
52
- features = features
73
+ features = features,
74
+ enableCompressedOutput = enableCompressedOutput,
75
+ compressedFormat = compressedFormat,
76
+ compressedBitRate = compressedBitRate
53
77
  )
54
78
 
55
79
  // Validate sample rate and channels
@@ -1 +1 @@
1
- {"version":3,"file":"AudioRecorder.provider.d.ts","sourceRoot":"","sources":["../src/AudioRecorder.provider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAoC,MAAM,OAAO,CAAA;AAExD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,EAAE,qBAAqB,EAAoB,MAAM,oBAAoB,CAAA;AAuB5E,UAAU,0BAA0B;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,MAAM,CAAC,EAAE,qBAAqB,CAAA;CACjC;AAED,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,0BAA0B,CAUtE,CAAA;AAED,eAAO,MAAM,sBAAsB,6BAQlC,CAAA"}
1
+ {"version":3,"file":"AudioRecorder.provider.d.ts","sourceRoot":"","sources":["../src/AudioRecorder.provider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAoC,MAAM,OAAO,CAAA;AAExD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,EAAE,qBAAqB,EAAoB,MAAM,oBAAoB,CAAA;AAwB5E,UAAU,0BAA0B;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,MAAM,CAAC,EAAE,qBAAqB,CAAA;CACjC;AAED,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,0BAA0B,CAUtE,CAAA;AAED,eAAO,MAAM,sBAAsB,6BAQlC,CAAA"}
@@ -6,6 +6,7 @@ const initContext = {
6
6
  isPaused: false,
7
7
  durationMs: 0,
8
8
  size: 0,
9
+ compression: undefined,
9
10
  startRecording: async () => {
10
11
  throw new Error('AudioRecorderProvider not found');
11
12
  },
@@ -1 +1 @@
1
- {"version":3,"file":"AudioRecorder.provider.js","sourceRoot":"","sources":["../src/AudioRecorder.provider.tsx"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAGxD,OAAO,EAAyB,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAE5E,MAAM,WAAW,GAA0B;IACvC,WAAW,EAAE,KAAK;IAClB,QAAQ,EAAE,KAAK;IACf,UAAU,EAAE,CAAC;IACb,IAAI,EAAE,CAAC;IACP,cAAc,EAAE,KAAK,IAAI,EAAE;QACvB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IACtD,CAAC;IACD,aAAa,EAAE,KAAK,IAAI,EAAE;QACtB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IACtD,CAAC;IACD,cAAc,EAAE,KAAK,IAAI,EAAE;QACvB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IACtD,CAAC;IACD,eAAe,EAAE,KAAK,IAAI,EAAE;QACxB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IACtD,CAAC;CACJ,CAAA;AAED,MAAM,oBAAoB,GAAG,aAAa,CAAwB,WAAW,CAAC,CAAA;AAO9E,MAAM,CAAC,MAAM,qBAAqB,GAAyC,CAAC,EACxE,QAAQ,EACR,MAAM,GAAG,EAAE,GACd,EAAE,EAAE;IACD,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAA;IAC9C,OAAO,CACH,CAAC,oBAAoB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,CAChD;YAAA,CAAC,QAAQ,CACb;QAAA,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CACnC,CAAA;AACL,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,EAAE;IACvC,MAAM,OAAO,GAAG,UAAU,CAAC,oBAAoB,CAAC,CAAA;IAChD,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACX,qEAAqE,CACxE,CAAA;IACL,CAAC;IACD,OAAO,OAAO,CAAA;AAClB,CAAC,CAAA","sourcesContent":["// packages/expo-audio-stream/src/AudioRecorder.provider.tsx\nimport React, { createContext, useContext } from 'react'\n\nimport { UseAudioRecorderState } from './ExpoAudioStream.types'\nimport { UseAudioRecorderProps, useAudioRecorder } from './useAudioRecorder'\n\nconst initContext: UseAudioRecorderState = {\n isRecording: false,\n isPaused: false,\n durationMs: 0,\n size: 0,\n startRecording: async () => {\n throw new Error('AudioRecorderProvider not found')\n },\n stopRecording: async () => {\n throw new Error('AudioRecorderProvider not found')\n },\n pauseRecording: async () => {\n throw new Error('AudioRecorderProvider not found')\n },\n resumeRecording: async () => {\n throw new Error('AudioRecorderProvider not found')\n },\n}\n\nconst AudioRecorderContext = createContext<UseAudioRecorderState>(initContext)\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"]}
1
+ {"version":3,"file":"AudioRecorder.provider.js","sourceRoot":"","sources":["../src/AudioRecorder.provider.tsx"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAGxD,OAAO,EAAyB,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAE5E,MAAM,WAAW,GAA0B;IACvC,WAAW,EAAE,KAAK;IAClB,QAAQ,EAAE,KAAK;IACf,UAAU,EAAE,CAAC;IACb,IAAI,EAAE,CAAC;IACP,WAAW,EAAE,SAAS;IACtB,cAAc,EAAE,KAAK,IAAI,EAAE;QACvB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IACtD,CAAC;IACD,aAAa,EAAE,KAAK,IAAI,EAAE;QACtB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IACtD,CAAC;IACD,cAAc,EAAE,KAAK,IAAI,EAAE;QACvB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IACtD,CAAC;IACD,eAAe,EAAE,KAAK,IAAI,EAAE;QACxB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IACtD,CAAC;CACJ,CAAA;AAED,MAAM,oBAAoB,GAAG,aAAa,CAAwB,WAAW,CAAC,CAAA;AAO9E,MAAM,CAAC,MAAM,qBAAqB,GAAyC,CAAC,EACxE,QAAQ,EACR,MAAM,GAAG,EAAE,GACd,EAAE,EAAE;IACD,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAA;IAC9C,OAAO,CACH,CAAC,oBAAoB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,CAChD;YAAA,CAAC,QAAQ,CACb;QAAA,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CACnC,CAAA;AACL,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,EAAE;IACvC,MAAM,OAAO,GAAG,UAAU,CAAC,oBAAoB,CAAC,CAAA;IAChD,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACX,qEAAqE,CACxE,CAAA;IACL,CAAC;IACD,OAAO,OAAO,CAAA;AAClB,CAAC,CAAA","sourcesContent":["// packages/expo-audio-stream/src/AudioRecorder.provider.tsx\nimport React, { createContext, useContext } from 'react'\n\nimport { UseAudioRecorderState } from './ExpoAudioStream.types'\nimport { UseAudioRecorderProps, useAudioRecorder } from './useAudioRecorder'\n\nconst initContext: UseAudioRecorderState = {\n isRecording: false,\n isPaused: false,\n durationMs: 0,\n size: 0,\n compression: undefined,\n startRecording: async () => {\n throw new Error('AudioRecorderProvider not found')\n },\n stopRecording: async () => {\n throw new Error('AudioRecorderProvider not found')\n },\n pauseRecording: async () => {\n throw new Error('AudioRecorderProvider not found')\n },\n resumeRecording: async () => {\n throw new Error('AudioRecorderProvider not found')\n },\n}\n\nconst AudioRecorderContext = createContext<UseAudioRecorderState>(initContext)\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"]}
@@ -1,5 +1,11 @@
1
1
  import { AmplitudeAlgorithm, AudioAnalysis, AudioFeaturesOptions } from './AudioAnalysis/AudioAnalysis.types';
2
2
  import { AudioAnalysisEvent } from './events';
3
+ export interface CompressionInfo {
4
+ size: number;
5
+ mimeType: string;
6
+ bitrate: number;
7
+ format: string;
8
+ }
3
9
  export interface AudioStreamStatus {
4
10
  isRecording: boolean;
5
11
  isPaused: boolean;
@@ -7,6 +13,7 @@ export interface AudioStreamStatus {
7
13
  size: number;
8
14
  interval: number;
9
15
  mimeType: string;
16
+ compression?: CompressionInfo;
10
17
  }
11
18
  export interface AudioDataEvent {
12
19
  data: string | Float32Array;
@@ -14,6 +21,9 @@ export interface AudioDataEvent {
14
21
  fileUri: string;
15
22
  eventDataSize: number;
16
23
  totalSize: number;
24
+ compression?: CompressionInfo & {
25
+ data?: string | Blob;
26
+ };
17
27
  }
18
28
  export type EncodingType = 'pcm_32bit' | 'pcm_16bit' | 'pcm_8bit';
19
29
  export type SampleRate = 16000 | 44100 | 48000;
@@ -48,6 +58,9 @@ export interface AudioRecording {
48
58
  transcripts?: TranscriberData[];
49
59
  wavPCMData?: Float32Array;
50
60
  analysisData?: AudioAnalysis;
61
+ compression?: CompressionInfo & {
62
+ compressedFileUri: string;
63
+ };
51
64
  }
52
65
  export interface StartRecordingResult {
53
66
  fileUri: string;
@@ -55,6 +68,9 @@ export interface StartRecordingResult {
55
68
  channels?: number;
56
69
  bitDepth?: BitDepth;
57
70
  sampleRate?: SampleRate;
71
+ compression?: CompressionInfo & {
72
+ compressedFileUri: string;
73
+ };
58
74
  }
59
75
  export interface AudioSessionConfig {
60
76
  category?: 'Ambient' | 'SoloAmbient' | 'Playback' | 'Record' | 'PlayAndRecord' | 'MultiRoute';
@@ -80,6 +96,11 @@ export interface RecordingConfig {
80
96
  features?: AudioFeaturesOptions;
81
97
  onAudioStream?: (_: AudioDataEvent) => Promise<void>;
82
98
  onAudioAnalysis?: (_: AudioAnalysisEvent) => Promise<void>;
99
+ compression?: {
100
+ enabled: boolean;
101
+ format: 'aac' | 'opus' | 'mp3';
102
+ bitrate?: number;
103
+ };
83
104
  }
84
105
  export interface NotificationConfig {
85
106
  title?: string;
@@ -113,15 +134,28 @@ export interface WaveformConfig {
113
134
  mirror?: boolean;
114
135
  height?: number;
115
136
  }
137
+ export interface WebRecordingOptions {
138
+ /**
139
+ * Web-specific option to skip the final audio data consolidation process.
140
+ * When true, it will:
141
+ * - Skip the time-consuming process of concatenating all audio chunks
142
+ * - Return immediately with the compressed audio (if compression is enabled)
143
+ * - Improve performance when stopping large recordings
144
+ * - Useful when only the compressed audio is needed (e.g., when not using transcription)
145
+ * @default false
146
+ */
147
+ skipFinalConsolidation?: boolean;
148
+ }
116
149
  export interface UseAudioRecorderState {
117
150
  startRecording: (_: RecordingConfig) => Promise<StartRecordingResult>;
118
- stopRecording: () => Promise<AudioRecording | null>;
151
+ stopRecording: (options?: WebRecordingOptions) => Promise<AudioRecording | null>;
119
152
  pauseRecording: () => Promise<void>;
120
153
  resumeRecording: () => Promise<void>;
121
154
  isRecording: boolean;
122
155
  isPaused: boolean;
123
156
  durationMs: number;
124
157
  size: number;
158
+ compression?: CompressionInfo;
125
159
  analysisData?: AudioAnalysis;
126
160
  }
127
161
  //# sourceMappingURL=ExpoAudioStream.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoAudioStream.types.d.ts","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"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"}
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":["// packages/expo-audio-stream/src/ExpoAudioStream.types.ts\nimport {\n AmplitudeAlgorithm,\n AudioAnalysis,\n AudioFeaturesOptions,\n} from './AudioAnalysis/AudioAnalysis.types'\nimport { AudioAnalysisEvent } from './events'\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 | Float32Array\n position: number\n fileUri: string\n eventDataSize: number\n totalSize: number\n}\n\nexport type EncodingType = 'pcm_32bit' | 'pcm_16bit' | 'pcm_8bit'\nexport type SampleRate = 16000 | 44100 | 48000\nexport type BitDepth = 8 | 16 | 32\n\nexport type ConsoleLike = {\n log: (message: string, ...args: unknown[]) => void\n debug: (message: string, ...args: unknown[]) => void\n warn: (message: string, ...args: unknown[]) => void\n error: (message: string, ...args: unknown[]) => void\n}\n\nexport interface Chunk {\n text: string\n timestamp: [number, number | null]\n}\n\nexport interface TranscriberData {\n id: string\n isBusy: boolean\n text: string\n startTime: number\n endTime: number\n chunks: Chunk[]\n}\n\nexport interface AudioRecording {\n fileUri: string\n filename: string\n durationMs: number\n size: number\n mimeType: string\n channels: number\n bitDepth: BitDepth\n sampleRate: SampleRate\n transcripts?: TranscriberData[]\n wavPCMData?: Float32Array // Full PCM data for the recording in WAV format (only on web, for native use the fileUri)\n analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag\n}\n\nexport interface StartRecordingResult {\n fileUri: string\n mimeType: string\n channels?: number\n bitDepth?: BitDepth\n sampleRate?: SampleRate\n}\n\nexport interface AudioSessionConfig {\n category?:\n | 'Ambient'\n | 'SoloAmbient'\n | 'Playback'\n | 'Record'\n | 'PlayAndRecord'\n | 'MultiRoute'\n mode?:\n | 'Default'\n | 'VoiceChat'\n | 'VideoChat'\n | 'GameChat'\n | 'VideoRecording'\n | 'Measurement'\n | 'MoviePlayback'\n | 'SpokenAudio'\n categoryOptions?: (\n | 'MixWithOthers'\n | 'DuckOthers'\n | 'InterruptSpokenAudioAndMixWithOthers'\n | 'AllowBluetooth'\n | 'AllowBluetoothA2DP'\n | 'AllowAirPlay'\n | 'DefaultToSpeaker'\n )[]\n}\n\nexport interface IOSConfig {\n audioSession?: AudioSessionConfig\n}\n\nexport interface RecordingConfig {\n // Sample rate for recording (16000, 44100, or 48000 Hz)\n sampleRate?: SampleRate\n\n // Number of audio channels (1 for mono, 2 for stereo)\n channels?: 1 | 2\n\n // Encoding type for the recording (pcm_32bit, pcm_16bit, pcm_8bit)\n encoding?: EncodingType\n\n // Interval in milliseconds at which to emit recording data\n interval?: number\n\n // Keep the device awake while recording (default is false)\n keepAwake?: boolean\n\n // Show a notification during recording (default is false)\n showNotification?: boolean\n\n // Show waveform in the notification (Android only, when showNotification is true)\n showWaveformInNotification?: boolean\n\n // Configuration for the notification\n notification?: NotificationConfig\n\n // Enable audio processing (default is false)\n enableProcessing?: boolean\n\n // iOS-specific configuration\n ios?: IOSConfig\n\n // Number of data points to extract per second of audio (default is 1000)\n pointsPerSecond?: number\n\n // Algorithm to use for amplitude computation (default is \"rms\")\n algorithm?: AmplitudeAlgorithm\n\n // Feature options to extract (default is empty)\n features?: AudioFeaturesOptions\n\n // Callback function to handle audio stream\n onAudioStream?: (_: AudioDataEvent) => Promise<void>\n\n // Callback function to handle audio features extraction results\n onAudioAnalysis?: (_: AudioAnalysisEvent) => Promise<void>\n}\n\nexport interface NotificationConfig {\n // Title of the notification\n title?: string\n\n // Main text content of the notification\n text?: string\n\n // Icon to be displayed in the notification (resource name or URI)\n icon?: string\n\n // Android-specific notification configuration\n android?: {\n // Unique identifier for the notification channel\n channelId?: string\n\n // User-visible name of the notification channel\n channelName?: string\n\n // User-visible description of the notification channel\n channelDescription?: string\n\n // Unique identifier for this notification\n notificationId?: number\n\n // List of actions that can be performed from the notification\n actions?: NotificationAction[]\n\n // Configuration for the waveform visualization in the notification\n waveform?: WaveformConfig\n\n // Color of the notification LED (if device supports it)\n lightColor?: string\n\n // Priority of the notification (affects how it's displayed)\n priority?: 'min' | 'low' | 'default' | 'high' | 'max'\n\n // Accent color for the notification (used for the app icon and buttons)\n accentColor?: string\n }\n\n // iOS-specific notification configuration\n ios?: {\n // Identifier for the notification category (used for grouping similar notifications)\n categoryIdentifier?: string\n }\n}\n\nexport interface NotificationAction {\n // Display title for the action\n title: string\n\n // Unique identifier for the action\n identifier: string\n\n // Icon to be displayed for the action (Android only)\n icon?: string\n}\n\nexport interface WaveformConfig {\n color?: string // The color of the waveform (e.g., \"#FFFFFF\" for white)\n opacity?: number // Opacity of the waveform (0.0 - 1.0)\n strokeWidth?: number // Width of the waveform line (default: 1.5)\n style?: 'stroke' | 'fill' // Drawing style: \"stroke\" for outline, \"fill\" for solid\n mirror?: boolean // Whether to mirror the waveform (symmetrical display)\n height?: number // Height of the waveform view in dp (default: 64)\n}\n\nexport interface UseAudioRecorderState {\n startRecording: (_: RecordingConfig) => Promise<StartRecordingResult>\n stopRecording: () => Promise<AudioRecording | null>\n pauseRecording: () => Promise<void>\n resumeRecording: () => Promise<void>\n isRecording: boolean\n isPaused: boolean\n durationMs: number // Duration of the recording\n size: number // Size in bytes of the recorded audio\n analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag\n}\n"]}
1
+ {"version":3,"file":"ExpoAudioStream.types.js","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"","sourcesContent":["// packages/expo-audio-stream/src/ExpoAudioStream.types.ts\nimport {\n AmplitudeAlgorithm,\n AudioAnalysis,\n AudioFeaturesOptions,\n} from './AudioAnalysis/AudioAnalysis.types'\nimport { AudioAnalysisEvent } from './events'\n\nexport interface CompressionInfo {\n size: number\n mimeType: string\n bitrate: number\n format: string\n}\n\nexport interface AudioStreamStatus {\n isRecording: boolean\n isPaused: boolean\n durationMs: number\n size: number\n interval: number\n mimeType: string\n compression?: CompressionInfo\n}\n\nexport interface AudioDataEvent {\n data: string | Float32Array\n position: number\n fileUri: string\n eventDataSize: number\n totalSize: number\n compression?: CompressionInfo & {\n data?: string | Blob // Base64 (native) or Float32Array (web) encoded compressed data chunk\n }\n}\n\nexport type EncodingType = 'pcm_32bit' | 'pcm_16bit' | 'pcm_8bit'\nexport type SampleRate = 16000 | 44100 | 48000\nexport type BitDepth = 8 | 16 | 32\n\nexport type ConsoleLike = {\n log: (message: string, ...args: unknown[]) => void\n debug: (message: string, ...args: unknown[]) => void\n warn: (message: string, ...args: unknown[]) => void\n error: (message: string, ...args: unknown[]) => void\n}\n\nexport interface Chunk {\n text: string\n timestamp: [number, number | null]\n}\n\nexport interface TranscriberData {\n id: string\n isBusy: boolean\n text: string\n startTime: number\n endTime: number\n chunks: Chunk[]\n}\n\nexport interface AudioRecording {\n fileUri: string\n filename: string\n durationMs: number\n size: number\n mimeType: string\n channels: number\n bitDepth: BitDepth\n sampleRate: SampleRate\n transcripts?: TranscriberData[]\n wavPCMData?: Float32Array // Full PCM data for the recording in WAV format (only on web, for native use the fileUri)\n analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag\n compression?: CompressionInfo & {\n compressedFileUri: string\n }\n}\n\nexport interface StartRecordingResult {\n fileUri: string\n mimeType: string\n channels?: number\n bitDepth?: BitDepth\n sampleRate?: SampleRate\n compression?: CompressionInfo & {\n compressedFileUri: string\n }\n}\n\nexport interface AudioSessionConfig {\n category?:\n | 'Ambient'\n | 'SoloAmbient'\n | 'Playback'\n | 'Record'\n | 'PlayAndRecord'\n | 'MultiRoute'\n mode?:\n | 'Default'\n | 'VoiceChat'\n | 'VideoChat'\n | 'GameChat'\n | 'VideoRecording'\n | 'Measurement'\n | 'MoviePlayback'\n | 'SpokenAudio'\n categoryOptions?: (\n | 'MixWithOthers'\n | 'DuckOthers'\n | 'InterruptSpokenAudioAndMixWithOthers'\n | 'AllowBluetooth'\n | 'AllowBluetoothA2DP'\n | 'AllowAirPlay'\n | 'DefaultToSpeaker'\n )[]\n}\n\nexport interface IOSConfig {\n audioSession?: AudioSessionConfig\n}\n\nexport interface RecordingConfig {\n // Sample rate for recording (16000, 44100, or 48000 Hz)\n sampleRate?: SampleRate\n\n // Number of audio channels (1 for mono, 2 for stereo)\n channels?: 1 | 2\n\n // Encoding type for the recording (pcm_32bit, pcm_16bit, pcm_8bit)\n encoding?: EncodingType\n\n // Interval in milliseconds at which to emit recording data\n interval?: number\n\n // Keep the device awake while recording (default is false)\n keepAwake?: boolean\n\n // Show a notification during recording (default is false)\n showNotification?: boolean\n\n // Show waveform in the notification (Android only, when showNotification is true)\n showWaveformInNotification?: boolean\n\n // Configuration for the notification\n notification?: NotificationConfig\n\n // Enable audio processing (default is false)\n enableProcessing?: boolean\n\n // iOS-specific configuration\n ios?: IOSConfig\n\n // Number of data points to extract per second of audio (default is 1000)\n pointsPerSecond?: number\n\n // Algorithm to use for amplitude computation (default is \"rms\")\n algorithm?: AmplitudeAlgorithm\n\n // Feature options to extract (default is empty)\n features?: AudioFeaturesOptions\n\n // Callback function to handle audio stream\n onAudioStream?: (_: AudioDataEvent) => Promise<void>\n\n // Callback function to handle audio features extraction results\n onAudioAnalysis?: (_: AudioAnalysisEvent) => Promise<void>\n\n compression?: {\n enabled: boolean\n format: 'aac' | 'opus' | 'mp3'\n bitrate?: number\n }\n}\n\nexport interface NotificationConfig {\n // Title of the notification\n title?: string\n\n // Main text content of the notification\n text?: string\n\n // Icon to be displayed in the notification (resource name or URI)\n icon?: string\n\n // Android-specific notification configuration\n android?: {\n // Unique identifier for the notification channel\n channelId?: string\n\n // User-visible name of the notification channel\n channelName?: string\n\n // User-visible description of the notification channel\n channelDescription?: string\n\n // Unique identifier for this notification\n notificationId?: number\n\n // List of actions that can be performed from the notification\n actions?: NotificationAction[]\n\n // Configuration for the waveform visualization in the notification\n waveform?: WaveformConfig\n\n // Color of the notification LED (if device supports it)\n lightColor?: string\n\n // Priority of the notification (affects how it's displayed)\n priority?: 'min' | 'low' | 'default' | 'high' | 'max'\n\n // Accent color for the notification (used for the app icon and buttons)\n accentColor?: string\n }\n\n // iOS-specific notification configuration\n ios?: {\n // Identifier for the notification category (used for grouping similar notifications)\n categoryIdentifier?: string\n }\n}\n\nexport interface NotificationAction {\n // Display title for the action\n title: string\n\n // Unique identifier for the action\n identifier: string\n\n // Icon to be displayed for the action (Android only)\n icon?: string\n}\n\nexport interface WaveformConfig {\n color?: string // The color of the waveform (e.g., \"#FFFFFF\" for white)\n opacity?: number // Opacity of the waveform (0.0 - 1.0)\n strokeWidth?: number // Width of the waveform line (default: 1.5)\n style?: 'stroke' | 'fill' // Drawing style: \"stroke\" for outline, \"fill\" for solid\n mirror?: boolean // Whether to mirror the waveform (symmetrical display)\n height?: number // Height of the waveform view in dp (default: 64)\n}\n\nexport interface WebRecordingOptions {\n /**\n * Web-specific option to skip the final audio data consolidation process.\n * When true, it will:\n * - Skip the time-consuming process of concatenating all audio chunks\n * - Return immediately with the compressed audio (if compression is enabled)\n * - Improve performance when stopping large recordings\n * - Useful when only the compressed audio is needed (e.g., when not using transcription)\n * @default false\n */\n skipFinalConsolidation?: boolean\n}\n\nexport interface UseAudioRecorderState {\n startRecording: (_: RecordingConfig) => Promise<StartRecordingResult>\n stopRecording: (options?: WebRecordingOptions) => Promise<AudioRecording | null>\n pauseRecording: () => Promise<void>\n resumeRecording: () => Promise<void>\n isRecording: boolean\n isPaused: boolean\n durationMs: number // Duration of the recording\n size: number // Size in bytes of the recorded audio\n compression?: CompressionInfo\n analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag\n}\n"]}