周二. 5月 30th, 2023

程序目标:实现录音以及播放功能
开发平台:Xcode 10
语言:swift
目标平台: iOS 12

实现步骤:

1. 首先建立一个single view 的iOS应用,在storyboard上添加三个按钮,”Start”, “Stop”, “Play”,分别对应app要实现的开始录音,结束录音和播放音频的操作UI

2. 获取语音授权

首先在Info.plist中找到Information Property List,点击添加在下拉菜单中选择Privacy – Microphone Usage Description,然后在value中随意输入向用户询问许可时的文字。
下面的代码用于获取用户对麦克风的授权

func checkAuthoriztion(){
    status = AVCaptureDevice.authorizationStatus(for: AVMediaType.audio)
    if (status == .notDetermined){
        print("Not determined")
    }
    if (status == .restricted)
    {
        print("restricted")
    }
    if (status == .denied){
        print("denied")
    }
    if (status == .authorized){
        print("Authorized")
        return
    }
    // 获取麦克风权限
    AVCaptureDevice.requestAccess(for: AVMediaType.audio, completionHandler: { (granted: Bool) -> Void in
        if(granted){
            //受限制
            self.status = AVAuthorizationStatus.restricted
            exit(0)
        }
    })
}

3. 在ViewController类中添加这三个按钮对应的响应代码:

3.1 开始录音

@IBAction func startRecord(_ sender: UIButton) {
    checkAuthoriztion()
    let session = AVAudioSession.sharedInstance()
    //设置session类型
    do {
        try session.setCategory(AVAudioSession.Category.playAndRecord)
    } catch let err{
        print("设置类型失败:\(err.localizedDescription)")
    }
    //设置session动作
    do {
        try session.setActive(true)
    } catch let err {
        print("初始化动作失败:\(err.localizedDescription)")
    }
    //录音设置,注意,后面需要转换成NSNumber,如果不转换,你会发现,无法录制音频文件,我猜测是因为底层还是用OC写的原因
    let recordSetting: [String: Any] = [AVSampleRateKey: NSNumber(value: 16000),//采样率
        AVFormatIDKey: NSNumber(value: kAudioFormatLinearPCM),//音频格式
        AVLinearPCMBitDepthKey: NSNumber(value: 16),//采样位数
        AVNumberOfChannelsKey: NSNumber(value: 1),//通道数
        AVEncoderAudioQualityKey: NSNumber(value: AVAudioQuality.min.rawValue)//录音质量
    ];
    //开始录音
    do {
        let url = URL(fileURLWithPath: file_path!)
        recorder = try AVAudioRecorder(url: url, settings: recordSetting)
        recorder!.prepareToRecord()
        recorder!.record()
        print("开始录音")
    } catch let err {
        print("录音失败:\(err.localizedDescription)")
    }
}

3.2 结束录音

@IBAction func stopRecord(_ sender: UIButton) {
    //结束录音
    if let recorder = self.recorder {
        if recorder.isRecording {
            print("正在录音,马上结束它,文件保存到了:\(file_path!)")
        }else {
            print("没有录音,但是依然结束它")
        }
        recorder.stop()
        self.recorder = nil
    }else {
        print("没有初始化")
    }
}

3.3 播放录音文件

@IBAction func play(_ sender: UIButton) {
    //播放
    do {
        player = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: file_path!))
        print("歌曲长度:\(player!.duration)")
        player!.play()
    } catch let err {
        print("播放失败:\(err.localizedDescription)")
    }
}

4. 实时显示录音分贝

在故事板添加Label控件,设置定时器,实时显示录音时的分贝值

// 初始化一个Timer类型的定时器,并触发定时更新分贝值的函数
func startTimer() 
{
    timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateMeter), userInfo: nil, repeats: true)
    timer!.fire()
}

func stoptTimer()
{
    if timer != nil {
    timer!.invalidate() //销毁timer
    timer = nil
    }
}

//更新分贝值的函数
@objc func updateMeter()
{
    recorder?.updateMeters()
    audioLevel = (recorder?.averagePower(forChannel: 0))!
    level.text = String(audioLevel)
}

完整代码(ViewController.swift)

import Foundation
import AVFoundation
import UIKit

class ViewController: UIViewController  {
    var status: AVAuthorizationStatus!
    var recorder: AVAudioRecorder?
    var player: AVAudioPlayer?
    let file_path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first?.appending("/record.wav")
    @IBOutlet weak var Start: UIButton!
    @IBOutlet weak var Stop: UIButton!
    @IBOutlet weak var Play: UIButton!
    @IBOutlet weak var level: UILabel!
    var audioLevel: Float = 0.0
    var timer: Timer?

    func checkAuthoriztion(){
        status = AVCaptureDevice.authorizationStatus(for: AVMediaType.audio)
        if (status == .notDetermined){
            print("Not determined")
        }
        if (status == .restricted)
        {
            print("restricted")
        }
        if (status == .denied){
            print("denied")
        }
        if (status == .authorized){
            print("Authorized")
            return
        }
        // 获取麦克风权限
        AVCaptureDevice.requestAccess(for: AVMediaType.audio, completionHandler: { (granted: Bool) -> Void in
            if(granted){
            //受限制
                self.status = AVAuthorizationStatus.restricted
                exit(0)
            }
        })

    }

    func startTimer()
    {
        timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateMeter), userInfo: nil, repeats: true)
        timer!.fire()
    }

    func stoptTimer()
    {
        if timer != nil {
        timer!.invalidate() //销毁timer
        timer = nil
        }
    }

    @objc func updateMeter()
    {
        recorder?.updateMeters()
        audioLevel = (recorder?.averagePower(forChannel: 0))!
        level.text = String(audioLevel)
    }


    @IBAction func startRecord(_ sender: UIButton) {
        checkAuthoriztion()
        let session = AVAudioSession.sharedInstance()
    //设置session类型
        do {
            try session.setCategory(AVAudioSession.Category.playAndRecord)
        } catch let err{
            print("设置类型失败:\(err.localizedDescription)")
        }
    //设置session动作
        do {
            try session.setActive(true)
        } catch let err {
            print("初始化动作失败:\(err.localizedDescription)")
        }
    //录音设置,注意,后面需要转换成NSNumber,如果不转换,你会发现,无法录制音频文件,我猜测是因为底层还是用OC写的原因
        let recordSetting: [String: Any] = [AVSampleRateKey: NSNumber(value: 16000),//采样率
        AVFormatIDKey: NSNumber(value: kAudioFormatLinearPCM),//音频格式
        AVLinearPCMBitDepthKey: NSNumber(value: 16),//采样位数
        AVNumberOfChannelsKey: NSNumber(value: 1),//通道数
        AVEncoderAudioQualityKey: NSNumber(value: AVAudioQuality.min.rawValue)//录音质量
        ];
    //开始录音
        do {
            let url = URL(fileURLWithPath: file_path!)
            recorder = try AVAudioRecorder(url: url, settings: recordSetting)
            recorder!.isMeteringEnabled = true
            recorder!.prepareToRecord()
            recorder!.record()
            startTimer()
            print("开始录音")
            } 
        catch let err {
            print("录音失败:\(err.localizedDescription)")
        }
    }


    @IBAction func stopRecord(_ sender: UIButton) {
    //结束录音
    if let recorder = self.recorder {
        if recorder.isRecording {
         print("正在录音,马上结束它,文件保存到了:\(file_path!)")
        }else {
            print("没有录音,但是依然结束它")
        }
        recorder.stop()
        stoptTimer()
        self.recorder = nil
        }else {
            print("没有初始化")
        }
    }

    @IBAction func play(_ sender: UIButton) {
    //播放
        do {
            player = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: file_path!))
            print("歌曲长度:\(player!.duration)")
            player!.play()
        } 
        catch let err {
            print("播放失败:\(err.localizedDescription)")
        }
    }

}
   
 摸鱼堡版权所有丨如未注明,均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明转自:http://moyubao.net/coder/972/

发表评论

邮箱地址不会被公开。