IOS:AVAudioSession 不工作

Posted

技术标签:

【中文标题】IOS:AVAudioSession 不工作【英文标题】:IOS: AVAudioSession not working 【发布时间】:2018-08-10 17:45:42 【问题描述】:

我正在尝试使用 AVAudiosession,但它抛出了这个运行时错误: [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields:Unknown selected data source for Port Speaker (type Speaker)。如果它有帮助,我正在尝试只录制音频,并监控当前的分贝。我将类别设置为AVAudioSessionCategoryRecord,将模式设置为AVAudioSessionModeMeasurement。 这是代码:

class ViewController: UIViewController 

    let captureSession = AVCaptureSession()
    var recording = false;
    var ready = false;

    let audioSession = AVAudioSession.sharedInstance()

    @IBOutlet public weak var dBLabel: UILabel!

    func alert(title: String, message: String = "", handler: ((UIAlertAction) -> Swift.Void)? = nil) -> Void 
        var usedMessage: String
        if(message.characters.count < 1) 
            usedMessage = title;
         else 
            usedMessage = message;
        
        let alert = UIAlertController(title: title, message: usedMessage, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Default action"), style: .default, handler: handler))
        self.present(alert, animated: true, completion: nil)
    

    override func viewDidLoad() 
        super.viewDidLoad()
    

    func checkPermission()
    
        switch AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeAudio)
        
        case .authorized:
            NSLog("Authorized for Microphone Use")

        case .notDetermined:
            AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeAudio, completionHandler:  granted in
                self.checkPermission()
            )

        case .denied:
            let alert = UIAlertController(title: "Denied Access to Microphone", message: "You denied access to the microphone, please enable access in settings", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "Go to Settings", style: .default, handler:  _ in
                guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else 
                    return
                

                if UIApplication.shared.canOpenURL(settingsUrl) 
                    UIApplication.shared.open(settingsUrl, completionHandler:  (success) in
                    )
                
            ))
            alert.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: "Cancel"), style: .cancel, handler: nil))
            self.present(alert, animated: true, completion: nil)


        case .restricted:
            alert(title: "Restricted",message: "You cannot enable the microphone, so you cannot use the app", handler:  _ in
                NSLog("The \"OK\" alert occured.")
            )
        
    

    @IBAction func toggleRecord(_ sender: UIButton) 
        if(!ready)
        return

        NSLog("Toggled Recording")
        recording = !recording;
        if(recording)
        
            sender.setImage(UIImage(named: "MicIconHighlighted.png"), for: .normal)
            sender.setImage(UIImage(named: "MicIconHighlightedSelected.png"), for: .highlighted)
            //captureSession.startRunning()
            do
            
                try audioSession.setActive(true)
             catch 
                NSLog("Activating AudioSession Failed")
            
         else 
            sender.setImage(UIImage(named: "MicIcon.png"), for: .normal)
            sender.setImage(UIImage(named: "MicIconSelected.png"), for: .highlighted)
            //captureSession.stopRunning()
            do
            
                try audioSession.setActive(false)
             catch 
                NSLog("Deactivating AudioSession Failed")
            
        
    

    override func viewDidAppear(_ animated: Bool) 
        super.viewDidAppear(animated)
        checkPermission()
        do
        
            try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
         catch 
            NSLog("Setting category on AudioSession failed")
        

        do
        
            try audioSession.setMode(AVAudioSessionModeMeasurement)
         catch 
            NSLog("Setting mode on AudioSession failed")
        

        do
        
            try audioSession.overrideOutputAudioPort(AVAudioSessionPortOverride.speaker)
         catch 
            NSLog("Failed Setting Audio Output Data Source")
        


        //NSLog("debug info: \(audioSession.outputDataSources!.count)");

        /*captureSession.beginConfiguration()
        let audioDeviceInput: AVCaptureDeviceInput
        let audioDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio)
        if(audioDevice != nil && (audioDevice?.isConnected)!) 
            NSLog("Audio Device Name: \(audioDevice!.localizedName)")
         else 
            NSLog("AVCapture Device default audio device failed or device not connected")
        

        do 
            audioDeviceInput = try AVCaptureDeviceInput(device: audioDevice)
         catch 
            alert(title: "Failed to create Capture Device",message: "Failed to create Capture Device", handler: nil)
            return
        

        if(captureSession.canAddInput(audioDeviceInput))
        
            captureSession.addInput(audioDeviceInput)
         else 
            alert(title: "Failed to Add Input",message: "Failed to add Audio Input Device", handler: nil)
        

        let audioOutput = AVCaptureAudioDataOutput()
        var audioRecorder = AVAudioRecorder()
        audioRecorder.
        var audioQueue = DispatchQueue(label: "audioqueue", attributes: .concurrent)
        audioOutput.setSampleBufferDelegate(AudioOutputSampleBufferDelegate(vc: self), queue: audioQueue)
        NSLog("Current Queue: \(audioOutput.sampleBufferCallbackQueue.description)")
        if(captureSession.canAddOutput(audioOutput))
        
            captureSession.addOutput(audioOutput)
            captureSession.commitConfiguration()
         else 
        alert(title: "Failed to Add Output",message: "Failed to add Audio Output Device", handler: nil)
        */

        ready = true
    

    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    

【问题讨论】:

如果您在设置 AVAudioSession 参数的位置共享代码会很有帮助 我更新了它以包含类别和模式 尝试将 AVAudioSessionCategoryRecord 更改为 AVAudioSessionCategoryPlayAndRecord 它仍然给出那个错误。问题是,我设置了它(使用上面的设置)并将其设置为活动状态,但除此之外我什么也不做。我什至不需要播放功能。我也尝试使用 AVCaptureSession,它给出了同样的错误 我在 iOS 12 官方版本和 XCode 10 官方版本中看到了同样的错误。关于如何修复它的任何意见? 【参考方案1】:

AVAudioSession 在 Swift 4.2 中有一些变化

在 viewDidAppear() 下,试试这个:

    // Prepare Audio Session
    self.audioSession = AVAudioSession.sharedInstance()

    try audioSession.setCategory(AVAudioSession.Category.playAndRecord, mode: .measurement, options: .defaultToSpeaker)
    try audioSession.setActive(true, options: .notifyOthersOnDeactivation)

当我在 Xcode 10 中将语言转换为 Swift 4.2 时,它对我有用 你可以去...

编辑、转换、到当前的 Swift 语法...

【讨论】:

太棒了。这对我有用。我仍然收到错误消息:“AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port Speaker (type: Speaker)”。但是在添加 try audioSession.setActive(false, options: .notifyOthersOnDeactivation) 之后,audiosession 被正确停用,任何其他 audioSession 恢复播放。【参考方案2】:

在 viewWillAppear() 中粘贴 AVAudioSession 有一些变化,更正了 Swift 5.0 的语法 声明 var recordingSession: AVAudioSession!

recordingSession = AVAudioSession.sharedInstance()
        do 
            try recordingSession.setCategory(.playAndRecord, mode: .spokenAudio, options: .defaultToSpeaker)
            try recordingSession.setActive(true, options: .notifyOthersOnDeactivation)
            recordingSession.requestRecordPermission()  [unowned self] allowed in
                DispatchQueue.main.async 
                    if allowed 
                        self.loadRecorder()
                     else 
                        // failed to record!
                    
                
            
         catch 
            // failed to record!
        `

【讨论】:

以上是关于IOS:AVAudioSession 不工作的主要内容,如果未能解决你的问题,请参考以下文章

ios开发之--AVAudioPlayer制作了一款播放器,耳机有声音,扬声器没声音

AVAudioSession.requestRecordPermission 不显示对话框

AVAudioSession 无法在 iOS 7 上播放

iOS 音频-AVAudioSession

iOS - 后台的 AVAudioSession 路由更改通知

iOS- 关于AVAudioSession的使用——后台播放音乐