From 0ad2e52499c7f4d76bf4c72ca4d5ae1645f87415 Mon Sep 17 00:00:00 2001 From: Craig Martin Date: Mon, 9 Oct 2023 16:27:29 -0400 Subject: [PATCH] Fix: iOS - audio does not work with headphones (#3284) * Fix: Make AVAudioSession.Category.playAndRecord opt-in * Fix: Call configureAudio when audioOutput is changed * Update CHANGELOG.md --- CHANGELOG.md | 1 + ios/Video/Features/RCTPlayerOperations.swift | 6 +++--- ios/Video/RCTVideo.swift | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f09b85ce..2e794cdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Changelog ## Next +- iOS: Fix audio session category when not using the audioOutput prop - All: add built-in typescript support [#3266](https://github.com/react-native-video/react-native-video/pull/3266) - iOS, Android: expose playback functions to ref [#3245](https://github.com/react-native-video/react-native-video/pull/3245) - Windows: fix build error from over-specified SDK version [#3246](https://github.com/react-native-video/react-native-video/pull/3246) diff --git a/ios/Video/Features/RCTPlayerOperations.swift b/ios/Video/Features/RCTPlayerOperations.swift index 6f2fc93c..6e82e2e7 100644 --- a/ios/Video/Features/RCTPlayerOperations.swift +++ b/ios/Video/Features/RCTPlayerOperations.swift @@ -191,13 +191,13 @@ enum RCTPlayerOperations { } } - static func configureAudio(ignoreSilentSwitch:String, mixWithOthers:String) { + static func configureAudio(ignoreSilentSwitch:String, mixWithOthers:String, audioOutput:String) { let audioSession:AVAudioSession! = AVAudioSession.sharedInstance() var category:AVAudioSession.Category? = nil var options:AVAudioSession.CategoryOptions? = nil if (ignoreSilentSwitch == "ignore") { - category = AVAudioSession.Category.playAndRecord + category = audioOutput == "earpiece" ? AVAudioSession.Category.playAndRecord : AVAudioSession.Category.playback } else if (ignoreSilentSwitch == "obey") { category = AVAudioSession.Category.ambient } @@ -221,7 +221,7 @@ enum RCTPlayerOperations { if #available(iOS 16.0, *) { do { debugPrint("[RCTPlayerOperations] Reseting AVAudioSession category to playAndRecord with defaultToSpeaker options.") - try audioSession.setCategory(AVAudioSession.Category.playAndRecord, options: AVAudioSession.CategoryOptions.defaultToSpeaker) + try audioSession.setCategory(audioOutput == "earpiece" ? AVAudioSession.Category.playAndRecord : AVAudioSession.Category.playback, options: AVAudioSession.CategoryOptions.defaultToSpeaker) } catch { debugPrint("[RCTPlayerOperations] Reseting AVAudioSession category and options problem. Error: \(error).") } diff --git a/ios/Video/RCTVideo.swift b/ios/Video/RCTVideo.swift index 5bf977d2..43b4e573 100644 --- a/ios/Video/RCTVideo.swift +++ b/ios/Video/RCTVideo.swift @@ -488,7 +488,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH @objc func setIgnoreSilentSwitch(_ ignoreSilentSwitch:String?) { _ignoreSilentSwitch = ignoreSilentSwitch - RCTPlayerOperations.configureAudio(ignoreSilentSwitch:_ignoreSilentSwitch, mixWithOthers:_mixWithOthers) + RCTPlayerOperations.configureAudio(ignoreSilentSwitch:_ignoreSilentSwitch, mixWithOthers:_mixWithOthers, audioOutput:_audioOutput) applyModifiers() } @@ -510,7 +510,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH _player?.rate = 0.0 } } else { - RCTPlayerOperations.configureAudio(ignoreSilentSwitch:_ignoreSilentSwitch, mixWithOthers:_mixWithOthers) + RCTPlayerOperations.configureAudio(ignoreSilentSwitch:_ignoreSilentSwitch, mixWithOthers:_mixWithOthers, audioOutput:_audioOutput) if _adPlaying { #if USE_GOOGLE_IMA @@ -583,6 +583,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH @objc func setAudioOutput(_ audioOutput:String) { _audioOutput = audioOutput + RCTPlayerOperations.configureAudio(ignoreSilentSwitch:_ignoreSilentSwitch, mixWithOthers:_mixWithOthers, audioOutput:_audioOutput) do { if audioOutput == "speaker" { #if os(iOS)