首页 > 解决方案 > 在 iOS Playground 上使用 AVFoundation 的 Recorder,但是 recorder.record() 总是返回 false

问题描述

无论如何在iOS Playground上使用录音机?运行时,它要求我允许使用我的麦克风,并且录音机实例似乎工作,但是,我不能使用 record() 函数。我当前的环境是 iOS 12.1.4 和 Swift 4.2。

import UIKit
import PlaygroundSupport
import AVFoundation

class VolumnMeterViewController : UIViewController, AVAudioRecorderDelegate {

    let temporaryDirectoryToKeepRecords = FileManager.default.temporaryDirectory
    var recordButton = UIButton()
    let backgroundView = UIView()
    var recordNumber = 1

    //    var recordingSession: AVAudioSession!
    var recorder: AVAudioRecorder!

    override func loadView() {

        backgroundView.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)

        recordButton.setTitle("Record", for: [])
        recordButton.setTitleColor(#colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1), for: [])
        recordButton.addTarget(self, action: #selector(recordButtonTapped), for: .touchUpInside)
        recordButton.translatesAutoresizingMaskIntoConstraints = false
        backgroundView.addSubview(recordButton)

        temporaryDirectoryToKeepRecords

        self.view = backgroundView

        NSLayoutConstraint.activate([
            recordButton.widthAnchor.constraint(equalToConstant: 200),
            recordButton.heightAnchor.constraint(equalToConstant: 60),
            recordButton.centerXAnchor.constraint(equalTo: backgroundView.centerXAnchor),
            recordButton.centerYAnchor.constraint(equalTo: backgroundView.centerYAnchor)
            ])
    }

    @objc func recordButtonTapped() {
        if recorder == nil {

            recordNumber += 1

            let recordFileName = temporaryDirectoryToKeepRecords.appendingPathComponent("record\(recordNumber).m4a")

            recordButton.setTitle("Stop", for: [])
            let settings = [AVFormatIDKey: Int(kAudioFormatMPEG4AAC), AVSampleRateKey: 44100, AVNumberOfChannelsKey: 1, AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue]

            do {
                let recorder = try AVAudioRecorder(url: recordFileName, settings: settings)

                // ❗️❗️❗️ Here's the problem. It always return false, assuming to be true.
                recorder.record()
            } catch {
                print(error)
            }
        } else {
            recordButton.setTitle("Record", for: [])
            recorder.stop()
            recorder = nil
        }
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = VolumnMeterViewController()

或者有没有办法不通过录音来跟踪麦克风音量,而只是实时检测,而不存储录音文件?非常感谢!

标签: iosswiftavfoundationswift-playgroundavaudiorecorder

解决方案


这终于是 iOS Playground 的工作代码了,非常感谢 AtulParmar!

import UIKit
import PlaygroundSupport
import AVFoundation

class VolumnMeterViewController : UIViewController, AVAudioRecorderDelegate {

    var recordingSession: AVAudioSession!
    let temporaryDirectoryToKeepRecords = FileManager.default.temporaryDirectory
    var recordButton = UIButton()
    let backgroundView = UIView()
    var playButton = UIButton()
    var recordNumber = 1
    var player: AVAudioPlayer!
    var recorder: AVAudioRecorder!

    override func loadView() {

        backgroundView.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)

        recordButton.setTitle("Start Recording", for: [])
        recordButton.setTitleColor(#colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1), for: [])
        recordButton.addTarget(self, action: #selector(recordButtonTapped), for: .touchUpInside)
        recordButton.translatesAutoresizingMaskIntoConstraints = false
        backgroundView.addSubview(recordButton)

        playButton.setTitle("Play Record", for: [])
        playButton.setTitleColor(#colorLiteral(red: 0.2196078449, green: 0.007843137719, blue: 0.8549019694, alpha: 1), for: [])
        playButton.addTarget(self, action: #selector(playButtonTapped), for: .touchUpInside)
        playButton.translatesAutoresizingMaskIntoConstraints = false
        backgroundView.addSubview(playButton)

        self.view = backgroundView

        NSLayoutConstraint.activate([
            recordButton.widthAnchor.constraint(equalToConstant: 200),
            recordButton.heightAnchor.constraint(equalToConstant: 60),
            recordButton.centerXAnchor.constraint(equalTo: backgroundView.centerXAnchor),
            recordButton.centerYAnchor.constraint(equalTo: backgroundView.centerYAnchor, constant: -50),

            playButton.widthAnchor.constraint(equalToConstant: 200),
            playButton.heightAnchor.constraint(equalToConstant: 60),
            playButton.centerXAnchor.constraint(equalTo: backgroundView.centerXAnchor),
            playButton.centerYAnchor.constraint(equalTo: backgroundView.centerYAnchor, constant: 50)
            ])
    }

    @objc func recordButtonTapped() {
        if recorder == nil {
            recordNumber += 1

            let recordFileName = temporaryDirectoryToKeepRecords.appendingPathComponent("record\(recordNumber).m4a")

            recordButton.setTitle("Stop Rocording", for: [])
            let settings = [AVFormatIDKey: Int(kAudioFormatMPEG4AAC), AVSampleRateKey: 44100, AVNumberOfChannelsKey: 1, AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue]
            recordingSession = AVAudioSession.sharedInstance()
            do {

                try recordingSession.setCategory(.playAndRecord, mode: .default)
                try recordingSession.setActive(true, options: [])
                recorder = try AVAudioRecorder(url: recordFileName, settings: settings)
                recorder.record()
            } catch {
                print(error)
            }
        } else {
            recordButton.setTitle("Start Recording", for: [])
            recorder.stop()
            recorder = nil
        }
    }

    @objc func playButtonTapped() {
        if player == nil {
            let recordFileName = temporaryDirectoryToKeepRecords.appendingPathComponent("record\(recordNumber).m4a")
            do {
                try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
                try AVAudioSession.sharedInstance().setActive(true)
                player = try AVAudioPlayer(contentsOf: recordFileName)
                player.play()
                playButton.setTitle("Stop Playing", for: [])
            } catch let error {
                print(error)
            }
        } else {
            player = nil
            playButton.setTitle("Play Record", for: [])
        }
    }
}

// Present the view controller in the Live View window
PlaygroundPage.current.liveView = VolumnMeterViewController()

推荐阅读