我使用Webrtc和Callkit打电话。当应用程序是前台时,一切正常工作,但如果屏幕被锁定,我回答呼叫音频只在我这边工作(我可以听到音频,但我的声音没有发送)。
当用户进入应用程序时,一切都是固定的。
所有后台设置和功能都设置正确。
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>fetch</string>
<string>remote-notification</string>
<string>voip</string>
</array>
我尝试使用RTCAdioSession和AVAudioSession配置音频,但在这两种情况下都是一样的。
解决方法:我将mediastream放入RTPeerConnection,现在我将添加RTCMediaStreamTracks
请注意,我分享我的代码,它将满足我的需要,我分享以供参考。您需要根据需要进行更改。
当您收到voip通知时,创建webrtc处理类的新事件,并将这两行代码添加到代码块,因为从voip通知启用音频会话失败
RTCAudioSession.sharedInstance().useManualAudio = true
RTCAudioSession.sharedInstance().isAudioEnabled = false
双接收法;
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
let state = UIApplication.shared.applicationState
if(payload.dictionaryPayload["hangup"] == nil && state != .active
){
Globals.voipPayload = payload.dictionaryPayload as! [String:Any] // I pass parameters to Webrtc handler via Global singleton to create answer according to sdp sent by payload.
RTCAudioSession.sharedInstance().useManualAudio = true
RTCAudioSession.sharedInstance().isAudioEnabled = false
Globals.sipGateway = SipGateway() // my Webrtc and Janus gateway handler class
Globals.sipGateway?.configureCredentials(true) // I check janus gateway credentials stored in Shared preferences and initiate websocket connection and create peerconnection
to my janus gateway which is signaling server for my environment
initProvider() //Crating callkit provider
self.update.remoteHandle = CXHandle(type: .generic, value:String(describing: payload.dictionaryPayload["caller_id"]!))
Globals.callId = UUID()
let state = UIApplication.shared.applicationState
Globals.provider.reportNewIncomingCall(with:Globals.callId , update: self.update, completion: { error in
})
}
}
func initProvider(){
let config = CXProviderConfiguration(localizedName: "ulakBEL")
config.iconTemplateImageData = UIImage(named: "ulakbel")!.pngData()
config.ringtoneSound = "ringtone.caf"
// config.includesCallsInRecents = false;
config.supportsVideo = false
Globals.provider = CXProvider(configuration:config )
Globals.provider.setDelegate(self, queue: nil)
update = CXCallUpdate()
update.hasVideo = false
update.supportsDTMF = true
}
修改您的didActivate和didDeActive委托函数,如下所示,
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
print("CallManager didActivate")
RTCAudioSession.sharedInstance().audioSessionDidActivate(audioSession)
RTCAudioSession.sharedInstance().isAudioEnabled = true
// self.callDelegate?.callIsAnswered()
}
func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
print("CallManager didDeactivate")
RTCAudioSession.sharedInstance().audioSessionDidDeactivate(audioSession)
RTCAudioSession.sharedInstance().isAudioEnabled = false
}
在Webrtc处理程序类中,配置媒体发送器和audiosession
private func createPeerConnection(webRTCCallbacks:PluginHandleWebRTCCallbacksDelegate) {
let rtcConfig = RTCConfiguration.init()
rtcConfig.iceServers = server.iceServers
rtcConfig.bundlePolicy = RTCBundlePolicy.maxBundle
rtcConfig.rtcpMuxPolicy = RTCRtcpMuxPolicy.require
rtcConfig.continualGatheringPolicy = .gatherContinually
rtcConfig.sdpSemantics = .planB
let constraints = RTCMediaConstraints(mandatoryConstraints: nil,
optionalConstraints: ["DtlsSrtpKeyAgreement":kRTCMediaConstraintsValueTrue])
pc = sessionFactory.peerConnection(with: rtcConfig, constraints: constraints, delegate: nil)
self.createMediaSenders()
self.configureAudioSession()
if webRTCCallbacks.getJsep() != nil{
handleRemoteJsep(webrtcCallbacks: webRTCCallbacks)
}
}
媒体发送者;
private func createMediaSenders() {
let streamId = "stream"
// Audio
let audioTrack = self.createAudioTrack()
self.pc.add(audioTrack, streamIds: [streamId])
// Video
/* let videoTrack = self.createVideoTrack()
self.localVideoTrack = videoTrack
self.peerConnection.add(videoTrack, streamIds: [streamId])
self.remoteVideoTrack = self.peerConnection.transceivers.first { $0.mediaType == .video }?.receiver.track as? RTCVideoTrack
// Data
if let dataChannel = createDataChannel() {
dataChannel.delegate = self
self.localDataChannel = dataChannel
}*/
}
private func createAudioTrack() -> RTCAudioTrack {
let audioConstrains = RTCMediaConstraints(mandatoryConstraints: nil, optionalConstraints: nil)
let audioSource = sessionFactory.audioSource(with: audioConstrains)
let audioTrack = sessionFactory.audioTrack(with: audioSource, trackId: "audio0")
return audioTrack
}
音频会议;
private func configureAudioSession() {
self.rtcAudioSession.lockForConfiguration()
do {
try self.rtcAudioSession.setCategory(AVAudioSession.Category.playAndRecord.rawValue)
try self.rtcAudioSession.setMode(AVAudioSession.Mode.voiceChat.rawValue)
} catch let error {
debugPrint("Error changeing AVAudioSession category: \(error)")
}
self.rtcAudioSession.unlockForConfiguration()
}
请考虑,因为我工作的回调和委托代码包括委托和回调块。
供参考您也可以在此链接查看示例
我在使用带有WebRTC的Callkit进行VOIP呼叫时,在从锁屏接听呼叫时,遇到了音频问题。 一般功能: 我的应用程序在启动时激活audio会话。对于进线量,SDP报价 如果应用程序在前台,它工作正常。 但是,当手机被锁定,用户从锁屏接听电话时,流被交换,但在用户自己进入应用程序之前,两端都没有音频。 当用户进入应用程序时,两端的音频都会激活。 所有后台设置和功能都设置正确。 我还提到了苹果员
我在这里尝试了许多解决方案,但没有人奏效。WebRTC工作正常,我在设备锁定时接听电话时处于连接状态,解锁后音频打开,视频启动。当屏幕保持锁定状态时,我如何只能获得音频? 我已启用RTCAdioSession,并在呼叫停止时将其禁用。 当设备第一次解锁时,它工作得很好,当我把它锁回去时,我得到了音频。但是第一次,当我接听来自CallKit的电话时,它不起作用。它只在设备解锁后才开始工作。
我试图让callkit在传入呼叫时与webrtc一起工作,但当我从锁定屏幕接收呼叫并接受它时,在我以前台模式运行应用程序之前,不会有声音。我已配置audiosession向RTCAudoSession发送通知,但它不起作用。你有解决办法吗?
是否可以从iPhone的内置麦克风接收音频输入,并同时通过蓝牙耳机播放该音频? 我的目标是始终使用内置麦克风作为输入设备,即使输出设备是耳机,因为在我的用例中内置麦克风更方便。 当输出设备是有线耳机时,我知道如何实现我的目标,就像iPhone附带的那种。我只需插入有线耳机,并调用以下方法: 通过调用上述方法,输入设备将从有线耳机的麦克风切换到iPhone的内置麦克风,而输出设备不受影响,因此iPh
问题内容: 我正在尝试通过Apples Multipeer Connectivity框架将音频从麦克风流式传输到另一个iPhone。为了进行音频捕获和回放,我使用了AVAudioEngine。 我通过在输入上安装一个抽头来从麦克风接收数据,由此我得到了AVAudioPCMBuffer,然后将其转换为UInt8数组,然后将其流式传输到另一部电话。 但是,当我将数组转换回AVAudioPCMBuffe
我正在使用Android API的语音识别。 我成功地遵循了以下教程:http://code4reference.com/2012/07/tutorial-android-voice-refactionation/#comment-335