阅读 215

iOS13-Swift5如何制作录音功能AVAudioRecorder和AVAudioSession

1-info.plist开启话筒权限

2-代码

复制并全部替换掉原ViewController.swift文件中的代码即可,解决思路参照注释。

import UIKit
import AVFoundation

class ViewController: UIViewController {
    
    // MARK: 属性
    // button也可从storyboard上拉IBOutlet过来
    private var recordButton: UIButton = {
        let btn = UIButton()
        btn.setTitle("开始录音", for: .normal)
        btn.titleLabel?.font = .preferredFont(forTextStyle: .title1)
        btn.translatesAutoresizingMaskIntoConstraints = false
        return btn
    }()
    private var recordingSession: AVAudioSession!
    private var audioRecorder: AVAudioRecorder!
    
    // MARK: 生命周期
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // MARK: 配置Session+申请权限
        recordingSession = AVAudioSession.sharedInstance()
        
        do {
            try recordingSession.setCategory(.playAndRecord, mode: .default)
            try recordingSession.setActive(true)
            recordingSession.requestRecordPermission() { [weak self] allowed in
                DispatchQueue.main.async {
                    if allowed {
                        // MARK: 创建录制按钮
                        self?.loadRecordingUI()
                    } else {
                        print("用户未允许")
                    }
                }
            }
        } catch {
            print("展示一些提示用户的UI")
        }
    }
     
}
// MARK: - UI
extension ViewController{
    private func loadRecordingUI() {
        view.addSubview(recordButton)
        recordButton.addTarget(self, action: #selector(recordTapped(_:)), for: .touchUpInside)
        setLayout()
    }
    private func setLayout(){
        recordButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        recordButton.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    }
}

// MARK: - 监听
extension ViewController{
    @objc private func recordTapped(_ btn: UIButton){
        // 最开始audioRecorder为nil,开始录音,audioRecorder变成有值,btn标题变成‘停止录音’
        // 再次按按钮会进入else
        if audioRecorder == nil {
            startRecording()
        } else {
            finishRecording(success: true)
        }
    }
}

// MARK: - 录音
extension ViewController{
    private func startRecording() {
        // MARK: 1-配置录音保存的地址
        let audioFilename = getDocumentsDirectory().appendingPathComponent("recording.m4a")
        
        // MARK: 2-一些配置
        let settings = [
            AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
            AVSampleRateKey: 12000,
            AVNumberOfChannelsKey: 1,
            AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
        ]
        
        do {
            audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings)
            audioRecorder.delegate = self
            
            // MARK: 3-开始录音
            audioRecorder.record()
            
            recordButton.setTitle("停止录音", for: .normal)
        } catch {
            finishRecording(success: false)
        }
    }
    
    // 1-用户按下按钮停止录音和2-录音失败都调用此函数,分别传入truefalse
    private func finishRecording(success: Bool) {
        audioRecorder.stop()
        audioRecorder = nil

        if success {// 用户按下按钮停止录音的情况
            recordButton.setTitle("录音成功,继续录音", for: .normal)
        } else {// 录音失败的情况
            recordButton.setTitle("录音失败,继续录音", for: .normal)
        }
    }
}

// MARK: - AVAudioRecorderDelegate
extension ViewController: AVAudioRecorderDelegate{
    // 录音意外中断(手机来电等)的时候
    func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
        if !flag {
            finishRecording(success: false)
        }
    }
}

// MARK: - 辅助函数
func getDocumentsDirectory() -> URL {
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    return paths[0]
}
复制代码

3-真机测试

真机上运行并录音后,打开Xcode菜单栏中的Windows--Devices and Simulators,选中App,点击下方齿轮,选择Download Container:

得到一个xcappdata后缀的文件,右击-->显示包内容,得到App的沙盒文件夹,找到刚刚录音的文件,播放即可:

以上。