twilio / video-quickstart-ios

Twilio Video Quickstart for iOS
https://www.twilio.com/docs/api/video
MIT License
457 stars 177 forks source link

Audio playing via receiver speaker instead of loudspeaker #631

Closed mukesh-ebpearls closed 2 years ago

mukesh-ebpearls commented 2 years ago

TwilioVideo SDK v4.4.0 via cocoapods

In my App i've used TwilioVideoSDK to implement a video call and i need to play dialing tone on callers side after the voip notification is sent successfully till the remote user joins the room or call is ended.

I've also implemented toggling on and off the loudspeaker functionality by implementing the block initializer provided by DefaultAudioDevice inside SDK like this

audioDevice = DefaultAudioDevice(block: { [weak self] in
                guard let self = self else { return }
                do {
                    DefaultAudioDevice.DefaultAVAudioSessionConfigurationBlock()

                    let audioSession = AVAudioSession.sharedInstance()
                    try audioSession.setCategory(.playAndRecord, mode: .videoChat, options: [.defaultToSpeaker, .allowBluetooth])
                    switch self.loudspeakerState { 
                    case .on:
                        try audioSession.setMode(.videoChat)
                        try audioSession.overrideOutputAudioPort(.speaker)
                        self.loudSpeakerStateChangePublisher.send(true)
                        self.logTwilio("audio mode changed to video chat")
                    case .off:
                        try audioSession.setMode(.voiceChat)
                        try audioSession.overrideOutputAudioPort(.none)
                        self.loudSpeakerStateChangePublisher.send(false)
                        self.logTwilio("audio mode changed to voice chat")
                    }

                    try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
                } catch let error as NSError {
                    self.logTwilio("Fail: \(error.localizedDescription)")
                }
            })

            TwilioVideoSDK.audioDevice = audioDevice!

// loudspeaker state is variable i initialize on my singleton class for twilio implementation to keep track of state if user tries to toggle it while ongoing call. i toggle this state and invoke audioDevice.block and it toggles the speaker as expected

i play dailing tone with function

func playRingingSound() {
        stopPlaying()
        do {
            if let soundURL = Bundle.main.url(forResource: "ringback", withExtension: "wav") {
                audioPlayer = try AVAudioPlayer(contentsOf: soundURL)
                audioPlayer?.prepareToPlay()
                audioPlayer?.numberOfLoops = -1
                audioPlayer?.play()
            }
        } catch {
            debugPrint("Something wrong with the player or session: \(error.localizedDescription)")
        }
    }

and stop the playing of tone if call is ended by user or times out with function

func stopPlaying() {
        audioPlayer?.stop()
        audioPlayer = nil
    }

the issue is that first time i initiate the call the dialing tone plays from loudspeaker as expected but after i end the call and initiate the second call dialing tone is played through receiver speaker.

I'm not toggling loudspeaker to receiver in between the calls but still the issue exists. is there anything i'm missing? should i disable TwilioSDK audio device before playing the dialing sound?

mukesh-ebpearls commented 2 years ago

also I'm never reinitializing audioDevice. it's set when i setup the singleton class the first time.

mukesh-ebpearls commented 2 years ago

i'm going to file his issue inside twilio-video-ios. closing this issue.

link to the new issue link to issue in twilio-video-ios