@siteed/expo-audio-studio 2.12.1 → 2.12.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.
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
## [2.12.3] - 2025-06-07
|
|
12
|
+
### Changed
|
|
13
|
+
- refactor(expo-audio-studio): adjust audio focus request timing in AudioRecorderManager ([317367c](https://github.com/deeeed/expo-audio-stream/commit/317367cb29fa09016aa73884f2f51e9cfdee1086))
|
|
14
|
+
- chore(expo-audio-studio): release @siteed/expo-audio-studio@2.12.2 ([14db4eb](https://github.com/deeeed/expo-audio-stream/commit/14db4ebfdeb9181e82e810d61283738d41c40a1a))
|
|
15
|
+
## [2.12.2] - 2025-06-07
|
|
16
|
+
### Changed
|
|
17
|
+
- fix: audio focus strategy implementation for Android background recording (#267) ([5b7b7ed](https://github.com/deeeed/expo-audio-stream/commit/5b7b7eda86bbd65becbe6bab44a44cdf6a1fb17d))
|
|
11
18
|
## [2.12.1] - 2025-06-07
|
|
12
19
|
### Changed
|
|
13
20
|
- feat(playground): implement agent validation framework and enhance testing capabilities (#266) ([e7937e0](https://github.com/deeeed/expo-audio-stream/commit/e7937e0268f54f85ea2e0171b221f7ef29cc6248))
|
|
@@ -297,7 +304,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
297
304
|
- Feature: Audio features extraction during recording.
|
|
298
305
|
- Feature: Consistent WAV PCM recording format across all platforms.
|
|
299
306
|
|
|
300
|
-
[unreleased]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-studio@2.12.
|
|
307
|
+
[unreleased]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-studio@2.12.3...HEAD
|
|
308
|
+
[2.12.3]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-studio@2.12.2...@siteed/expo-audio-studio@2.12.3
|
|
309
|
+
[2.12.2]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-studio@2.12.1...@siteed/expo-audio-studio@2.12.2
|
|
301
310
|
[2.12.1]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-studio@2.12.0...@siteed/expo-audio-studio@2.12.1
|
|
302
311
|
[2.12.0]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-studio@2.11.0...@siteed/expo-audio-studio@2.12.0
|
|
303
312
|
[2.11.0]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-studio@2.10.6...@siteed/expo-audio-studio@2.11.0
|
|
@@ -469,49 +469,6 @@ class AudioRecorderManager(
|
|
|
469
469
|
}
|
|
470
470
|
}
|
|
471
471
|
|
|
472
|
-
@RequiresApi(Build.VERSION_CODES.O)
|
|
473
|
-
private val audioFocusCallback = object : AudioManager.OnAudioFocusChangeListener {
|
|
474
|
-
override fun onAudioFocusChange(focusChange: Int) {
|
|
475
|
-
when (focusChange) {
|
|
476
|
-
AudioManager.AUDIOFOCUS_LOSS,
|
|
477
|
-
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
|
|
478
|
-
if (_isRecording.get() && !isPaused.get()) {
|
|
479
|
-
mainHandler.post {
|
|
480
|
-
pauseRecording(object : Promise {
|
|
481
|
-
override fun resolve(value: Any?) {
|
|
482
|
-
eventSender.sendExpoEvent(Constants.RECORDING_INTERRUPTED_EVENT_NAME, bundleOf(
|
|
483
|
-
"reason" to "audioFocusLoss",
|
|
484
|
-
"isPaused" to true
|
|
485
|
-
))
|
|
486
|
-
}
|
|
487
|
-
override fun reject(code: String, message: String?, cause: Throwable?) {
|
|
488
|
-
LogUtils.e(CLASS_NAME, "Failed to pause recording on audio focus loss")
|
|
489
|
-
}
|
|
490
|
-
})
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
AudioManager.AUDIOFOCUS_GAIN -> {
|
|
495
|
-
val autoResume = if (::recordingConfig.isInitialized) recordingConfig.autoResumeAfterInterruption else false
|
|
496
|
-
if (_isRecording.get() && isPaused.get() && autoResume) {
|
|
497
|
-
mainHandler.post {
|
|
498
|
-
resumeRecording(object : Promise {
|
|
499
|
-
override fun resolve(value: Any?) {
|
|
500
|
-
eventSender.sendExpoEvent(Constants.RECORDING_INTERRUPTED_EVENT_NAME, bundleOf(
|
|
501
|
-
"reason" to "audioFocusGain",
|
|
502
|
-
"isPaused" to false
|
|
503
|
-
))
|
|
504
|
-
}
|
|
505
|
-
override fun reject(code: String, message: String?, cause: Throwable?) {
|
|
506
|
-
LogUtils.e(CLASS_NAME, "Failed to resume recording on audio focus gain")
|
|
507
|
-
}
|
|
508
|
-
})
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
472
|
|
|
516
473
|
@RequiresApi(Build.VERSION_CODES.R)
|
|
517
474
|
fun startRecording(options: Map<String, Any?>, promise: Promise) {
|
|
@@ -522,12 +479,6 @@ class AudioRecorderManager(
|
|
|
522
479
|
return
|
|
523
480
|
}
|
|
524
481
|
|
|
525
|
-
// Request audio focus - always do this right before starting
|
|
526
|
-
if (!requestAudioFocus()) {
|
|
527
|
-
promise.reject("AUDIO_FOCUS_ERROR", "Failed to obtain audio focus", null)
|
|
528
|
-
return
|
|
529
|
-
}
|
|
530
|
-
|
|
531
482
|
// If already prepared, we can skip initialization
|
|
532
483
|
if (!isPrepared) {
|
|
533
484
|
LogUtils.d(CLASS_NAME, "Not prepared, preparing recording first")
|
|
@@ -542,7 +493,7 @@ class AudioRecorderManager(
|
|
|
542
493
|
// Check permissions
|
|
543
494
|
if (!checkPermissions(options, promise)) return
|
|
544
495
|
|
|
545
|
-
// Parse recording configuration
|
|
496
|
+
// Parse recording configuration FIRST
|
|
546
497
|
val configResult = RecordingConfig.fromMap(options)
|
|
547
498
|
if (configResult.isFailure) {
|
|
548
499
|
promise.reject(
|
|
@@ -557,6 +508,12 @@ class AudioRecorderManager(
|
|
|
557
508
|
|
|
558
509
|
recordingConfig = tempRecordingConfig
|
|
559
510
|
|
|
511
|
+
// Request audio focus AFTER config is parsed so strategy is correct
|
|
512
|
+
if (!requestAudioFocus()) {
|
|
513
|
+
promise.reject("AUDIO_FOCUS_ERROR", "Failed to obtain audio focus", null)
|
|
514
|
+
return
|
|
515
|
+
}
|
|
516
|
+
|
|
560
517
|
// Store device-related settings
|
|
561
518
|
selectedDeviceId = recordingConfig.deviceId
|
|
562
519
|
deviceDisconnectionBehavior = recordingConfig.deviceDisconnectionBehavior ?: "pause"
|
|
@@ -589,6 +546,12 @@ class AudioRecorderManager(
|
|
|
589
546
|
?: deviceDisconnectionBehavior
|
|
590
547
|
?: "pause"
|
|
591
548
|
}
|
|
549
|
+
|
|
550
|
+
// Request audio focus with current config
|
|
551
|
+
if (!requestAudioFocus()) {
|
|
552
|
+
promise.reject("AUDIO_FOCUS_ERROR", "Failed to obtain audio focus", null)
|
|
553
|
+
return
|
|
554
|
+
}
|
|
592
555
|
}
|
|
593
556
|
|
|
594
557
|
if (!startRecordingProcess(promise)) return
|
|
@@ -1753,17 +1716,23 @@ class AudioRecorderManager(
|
|
|
1753
1716
|
private fun getAudioFocusStrategy(): String {
|
|
1754
1717
|
// Use explicit strategy if provided
|
|
1755
1718
|
if (::recordingConfig.isInitialized) {
|
|
1756
|
-
recordingConfig.audioFocusStrategy?.let {
|
|
1719
|
+
recordingConfig.audioFocusStrategy?.let {
|
|
1720
|
+
LogUtils.d(CLASS_NAME, "Using explicit audio focus strategy: $it")
|
|
1721
|
+
return it
|
|
1722
|
+
}
|
|
1757
1723
|
|
|
1758
1724
|
// Smart defaults based on other config
|
|
1759
|
-
|
|
1725
|
+
val defaultStrategy = if (recordingConfig.keepAwake && enableBackgroundAudio) {
|
|
1760
1726
|
"background"
|
|
1761
1727
|
} else {
|
|
1762
1728
|
"interactive"
|
|
1763
1729
|
}
|
|
1730
|
+
LogUtils.d(CLASS_NAME, "Using default audio focus strategy: $defaultStrategy (keepAwake=${recordingConfig.keepAwake}, enableBackgroundAudio=$enableBackgroundAudio)")
|
|
1731
|
+
return defaultStrategy
|
|
1764
1732
|
}
|
|
1765
1733
|
|
|
1766
1734
|
// Default strategy if recordingConfig is not initialized
|
|
1735
|
+
LogUtils.d(CLASS_NAME, "Using fallback audio focus strategy: interactive")
|
|
1767
1736
|
return "interactive"
|
|
1768
1737
|
}
|
|
1769
1738
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@siteed/expo-audio-studio",
|
|
3
|
-
"version": "2.12.
|
|
3
|
+
"version": "2.12.3",
|
|
4
4
|
"description": "Comprehensive audio processing library for React Native and Expo with recording, analysis, visualization, and streaming capabilities across iOS, Android, and web",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "commonjs",
|