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)
}