使用AVAudioRecorder录制声音(Swift)

时间:2021-05-03 18:19:06
AVAudioRecorder看字面意思就知道是音频录制,当我们实例化该类对象,我们可以称该实例对象为音频录制者,该对象有录制音频的能力,使用音频录制者我们能够做以下几件事情:

1:可以进行音频录制,一直到用户停止录制
2:录制具体的时间
3
:暂停和恢复录制
4:我们能够使用等级测量获取音频的输入等级数据

为了合理配置AVAudioSession用于录制操作,可以参考AVAudioSession Class Reference 和AVAudioSessionDelegate Protocol Reference.


录音实现步骤:

     1:导入AVFoundation框架,因为我们需要AVAudioSession、AVAudioRecorder、AVAudioPlayer等类
     2:创建会话session,调用AVAudioSession的类方法+(id)sharedInstance;返回一个单例实例
     3:请求用户授权进行录音,如果用户同意那么调用setCategory设置音频会话分类,本例中实现录音和播放等功能,所以会话类型选择AVAudioSessionCategoryPlayAndRecord,否则提示用户进行设置
     4:实例化一个音频录制者AVAudioRecorder,指定录音保存的路径并且设置录音相关属性,注意因为录音机必须知道录音文件的格式、采样率、通道数、每个采样点的位数等信息,但是也并不是所有的信息都必须设置,通常只需要几个常用设置。 AVAudioRecorder为我们提供了settings属性字典用于设置相关信息。关于录音设置详见帮助文档中的 AV Foundation Audio Settings Constants
     5:根据需求可以设置 AVAudioRecorder的代理来监听录制情况。然后 调用音频录制者的prepareToRecord(),准备录制音频
     6:最后根据按钮触发录制,停止,播放等基本功能,注意在播放部分我们将使用AVAudioPlayer获取本地存储文件进行播放操作,并且可以设置代理监听播放的情况。

下面简单的实现录音功能,包括,开始录制,停止录制,暂停录制,恢复录制,开始播放,暂停播放等。在Main.storyboard添加6个按钮分别对应功能:

class ViewController: UIViewController {
    
    //audioRecorder和audioPlayer,一个用于录音,一个用于播放
    var audioRecorder:AVAudioRecorder!
    var audioPlayer:AVAudioPlayer!
    
    //获取音频会话单例
    let audioSession = AVAudioSession.sharedInstance()
    var isAllowed:Bool = false
    
    //定义音频的编码参数
    let recordSettings = [AVSampleRateKey : NSNumber(float: Float(44100.0)),//声音采样率
                          AVFormatIDKey : NSNumber(int: Int32(kAudioFormatMPEG4AAC)),//编码格式
                          AVNumberOfChannelsKey : NSNumber(int: 1),//采集音轨
                          AVEncoderAudioQualityKey : NSNumber(int: Int32(AVAudioQuality.Medium.rawValue))]//音频质量

    
    override func viewDidLoad() {
        super.viewDidLoad()
        //首先要判断是否允许访问麦克风
        audioSession.requestRecordPermission { (allowed) in
            if !allowed{
                let alertView = UIAlertView(title: "无法访问您的麦克风" , message: "请到设置 -> 隐私 -> 麦克风 ,打开访问权限", delegate: nil, cancelButtonTitle: "取消", otherButtonTitles: "好的")
                alertView.show()
                self.isAllowed = false
            }else{
                self.isAllowed = true
            }
        }
        
        if self.isAllowed{
            do {
                try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
                //初始化实例
                try audioRecorder = AVAudioRecorder(URL: self.directoryURL()!,settings: recordSettings)
                audioRecorder.delegate = self
                //准备录音
                audioRecorder.prepareToRecord()
            } catch let error as NSError{
                print(error)
            }
        }
    }
    
    func directoryURL() -> NSURL? {
        //定义并构建一个url来保存音频,音频文件名为ddMMyyyyHHmmss.caf,根据时间来设置存储文件名
        let currentDateTime = NSDate()
        let formatter = NSDateFormatter()
        formatter.dateFormat = "ddMMyyyyHHmmss"
        //以下2种格式都可以
        //let recordingName = formatter.stringFromDate(currentDateTime)+".caf"
        let recordingName = formatter.stringFromDate(currentDateTime)+".m4a"
        
        let fileManager = NSFileManager.defaultManager()
        let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
        let documentDirectory = urls[0] as NSURL
        let soundURL = documentDirectory.URLByAppendingPathComponent(recordingName)
        return soundURL
    }
    
    //开始录音
    @IBAction func startRecord(sender: AnyObject) {
        //如果正在播放,先停止播放
        if let audioPlayer = audioPlayer where audioPlayer.playing {
           audioPlayer.stop()
        }
        //是否正在录音,如果没有,开始录音
        if !audioRecorder.recording {
            do {
                try audioSession.setActive(true)
                audioRecorder.record()
             }catch let error as NSError{
                print(error)
            }
        }
    }
    
    //停止录音
    @IBAction func stopRecord(sender: AnyObject) {
        if audioRecorder.recording{
            audioRecorder.stop()
            do {
                try audioSession.setActive(false)
            } catch let error as NSError{
                print(error)
            }
        }
    }
    
    //开始播放
    @IBAction func startPlaying(sender: AnyObject) {
        if (!audioRecorder.recording){
            do {
                //创建音频播放器AVAudioPlayer,用于在录音完成之后播放录音
                let url:NSURL? = audioRecorder.url
                if let url = url{
                    try audioPlayer = AVAudioPlayer(contentsOfURL: url)
                    audioPlayer.delegate = self
                    audioPlayer.play()
                }
            } catch let error as NSError{
                print(error)
            }
        }
    }
    
     //暂停播放
    @IBAction func pausePlaying(sender: AnyObject) {
        if let audioPlayer = audioPlayer where audioPlayer.playing{
            if (!audioRecorder.recording){
                audioPlayer.pause()
            }
        }
    }
    
    //暂停录制
    @IBAction func pauseRecoder(sender: AnyObject) {
        if audioRecorder.recording{
           audioRecorder.pause()
        }
    }
    
    //恢复录制,恢复录音只需要再次调用record,AVAudioSession会帮助你记录上次录音位置并追加录音
    @IBAction func resumeRecoder(sender: AnyObject) {
        if (!audioRecorder.recording){
            self.startRecord(sender)
        }
    }
}

extension ViewController:AVAudioRecorderDelegate{
    func audioRecorderDidFinishRecording(recorder: AVAudioRecorder, successfully flag: Bool) {
        if flag{
            if #available(iOS 8.0, *) {
                let alert = UIAlertController(title: "Recorder",
                                              message: "Finished Recording",
                                              preferredStyle: .Alert)
                alert.addAction(UIAlertAction(title: "OK!", style: .Default, handler: {action in
                    print("OK was tapped")
                }))
                self.presentViewController(alert, animated:true, completion:nil)
            } else {
                // Fallback on earlier versions
            }
        }
    }
}

extension ViewController:AVAudioPlayerDelegate{
    func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) {
        if flag{ print("播放完成!") }
    }
}

Audio Session会话类型:
 
AVAudioSessionCategoryAmbient后台播放类型,会和其它音乐混合的音频类型。这个类别用于音频比较次要的应用,应用的音频会和其他应用的音频实现混音,关闭屏幕或者静音开关打开时音频将静音.
 
AVAudioSessionCategorySoloAmbient:默认类型,后台播放类型,其它音乐会停止播放,默认类别。这个类别非常像AVAudioSessionCategoryAmbient类别,除了会停止其他程序的音频回放。
 
AVAudioSessionCategoryPlayback这个类别会静止其他应用的音频回放。你可以使用AVAudioPlayerprepareToPlayplay方法,在你的应用中播放声音。主UI界面会照常工作。这时,即使屏幕被锁定或者设备为静音模式,音频回放都会继续。
 
AVAudioSessionCategoryRecord录音时使用。这会停止其他应用的声音并让你的应用也不能初始化音频回放(比如AVAudioPlayer)。在这种模式下,你只能进行录音。使用这个类别,调用AVAudioPlayerprepareToPlay会返回true,但是调用play方法将返回false。主UI界面会照常工作。这时,即使你的设备屏幕被用户锁定了,应用的录音仍会继续。而且用户必须授权允许录制。
 
AVAudioSessionCategoryPlayAndRecord录音并需要播放时使用。这个类别允许你的应用中同时进行声音的播放和录制。当你的声音录制或播放开始后,其他应用的声音播放将会停止。主UI界面会照常工作。这时,即使屏幕被锁定或者设备为静音模式,音频回放和录制都会继续。用户必须授权允许录制( Recording Requires User Permission
 
AVAudioSessionCategoryAudioProcessing这个类别用于音频处理,比如编码解码时/不播放音频/未录音时使用。设置了这种模式,你在应用中就不能播放和录制任何声音。调用AVAPlayerprepareToPlayplay方法都将返回false。其他应用的音频也会在此模式下停止。
 
AVAudioSessionCategoryMultiRoute这个类别可以实现同时可以有多种输出,例如:usb和耳机同时输出,但并非所有输入输出方式均支持.输入方式仅包括:AVAudioSessionPortUSBAudio/AVAudioSessionPortHeadsetMic AVAudioSessionPortBuiltInMic;输出仅包括:AVAudioSessionPortUSBAudio /AVAudioSessionPortLineOut /AVAudioSessionPortHeadphones /AVAudioSessionPortHDMI AVAudioSessionPortBuiltInSpeaker