webRTC, audio failed with AURemoteIO.cpp:1679 AUIOClient_StartIO failed

119 views Asked by At

Using webRTC in Swift class containing the push to talk functionalities from live streaming video, sometimes the audio didn't work (no sound) a fail message received:

"AURemoteIO.cpp:1679 AUIOClient_StartIO failed"

But when the streaming is launched without sound and set the app in background after that put it in the foreground the audio working well.

I have all authorization in plist file (camera, microphone), my code configuration is like that:

class WebRTCManager: NSObject {
    
    private  let peerConnectionFactory: RTCPeerConnectionFactory = {
        RTCInitializeSSL()
        
        let videoEncoderFactory = RTCVideoEncoderFactoryH264()
        let videoDecoderFactory = RTCVideoDecoderFactoryH264()
        return RTCPeerConnectionFactory(encoderFactory: videoEncoderFactory, decoderFactory: videoDecoderFactory)
    }()
    
    private var peerConnection: RTCPeerConnection?
    private var audioSource: RTCAudioSource?
    private var audioTrack: RTCAudioTrack?
    private var audioSender: RTCRtpSender?
    private var localStream: RTCMediaStream?
    
    private var remoteStream: RTCMediaStream?
    private var dataChannel: RTCDataChannel?
    private var remoteDataChannel: RTCDataChannel?
    private let audioQueue = DispatchQueue(label: "audio")
    private let rtcAudioSession =  RTCAudioSession.sharedInstance()
    var socket: WebSocket!
    
    public private(set) var isConnected: Bool = false
    
    // enableMicrophone
    override init( ) {
        super.init()
        
        let audioConstraints = RTCMediaConstraints(mandatoryConstraints: nil, optionalConstraints: nil)
        self.audioSource = self.peerConnectionFactory.audioSource(with: audioConstraints)
        self.audioTrack  = self.peerConnectionFactory.audioTrack(with: self.audioSource!, trackId: "audio0")
        self.localStream = self.peerConnectionFactory.mediaStream(withStreamId: "stream")
        localStream!.addAudioTrack(self.audioTrack!)
    }
    
    deinit {
        self.peerConnection = nil
        self.socket = nil
    }
    
    func reset(){
        self.peerConnection = nil
        self.socket = nil
    }
    
    func initLive(socketURL:String) {
        
        self.socket = WebSocket(url: URL(string: socketURL)!)
        self.socket.delegate = self
        self.socket.connect()
    }
    
    // MARK: Connect
    func connect(onSuccess: @escaping (RTCSessionDescription) -> Void){
        setupPeerConnection()
        
    }
    
    func createAndConnectSocket(socketURL:String){
        self.socket = WebSocket(url: URL(string: socketURL)!)
        self.socket.delegate = self
        self.socket.connect()
    }
    
    // MARK: - setupPeerConnection
    private func setupPeerConnection() {
        let rtcConf = RTCConfiguration()
        rtcConf.sdpSemantics = .unifiedPlan
        
        rtcConf.iceServers = [ RTCIceServer(urlStrings: ["turn:" + self.coturnHost + ":" + String(self.coturnPort)] ,username: self.userName ,credential: self.password )]
          
        let mediaConstraints = RTCMediaConstraints.init(mandatoryConstraints: nil, optionalConstraints: nil)
        self.peerConnection = self.peerConnectionFactory.peerConnection(with: rtcConf, constraints: mediaConstraints, delegate: nil)
        self.peerConnection?.delegate = self
        
        for track in localStream!.audioTracks {
            audioSender = peerConnection?.add(audioTrack!, streamIds: [localStream!.streamId])
        }
    }
    
    // MARK: Fonctionnalité Push to Talk
    
    func pushToTalk(isPressed: Bool) {
        self.audioTrack?.isEnabled = isPressed
    }
    
    // MARK: the speaker function
    
    func setSpeaker(isOn: Bool) {
        audioQueue.async { [weak self] in
            guard let self = self else {
                return
            }
            
            self.rtcAudioSession.lockForConfiguration()
            
            do {
                try self.rtcAudioSession.setCategory(AVAudioSession.Category.playAndRecord.rawValue)
                
                if isOn {
                    try self.rtcAudioSession.overrideOutputAudioPort(.speaker)
                    try self.rtcAudioSession.setActive(true)
                } else {
                    try self.rtcAudioSession.overrideOutputAudioPort(.none)
                }
            } catch let error {
                debugPrint("Error setting AVAudioSession category: \(error)")
            }
            self.rtcAudioSession.unlockForConfiguration()
        }
    }
    
}

// MARK: - PeerConnection Delegates

extension WebRTCManager : RTCPeerConnectionDelegate {
    
    func peerConnection(_ peerConnection: RTCPeerConnection, didAdd stream: RTCMediaStream) {
        print("liveWRTC--did add stream")
        self.remoteStream = stream
        
        if let track = stream.videoTracks.first {
            print("liveWRTC--video track faund")
            track.add(remoteRenderView!)
        }
        
        if let audioTrack = stream.audioTracks.first{
            print("WebRTCManager: liveWRTC--audio track faund")
            
        }
    }
    
    func peerConnection(_ peerConnection: RTCPeerConnection, didRemove stream: RTCMediaStream) {
    }
    
    func peerConnection(_ peerConnection: RTCPeerConnection, didOpen dataChannel: RTCDataChannel) {
        self.remoteDataChannel = dataChannel
        
    }
    
    func peerConnection(_ peerConnection: RTCPeerConnection, didRemove candidates: [RTCIceCandidate]) {
        //peerConnection
    }
    
    func peerConnectionShouldNegotiate(_ peerConnection: RTCPeerConnection){
        //peerConnectionShouldNegotiate
    }
    
    func peerConnection(_ peerConnection: RTCPeerConnection, didChange newState: RTCIceGatheringState) {
        //peerConnection   
        }
    }
}

==> when the streaming is connected I add these two instructions:

if (liveStreamingStatus == .connected){
    WebRTCManager.setSpeaker(isOn: true)
    WebRTCManager.pushToTalk(isPressed: false)
}
0

There are 0 answers