• iOS音频与视频的开发(二)- 使用AVAudioRecorder进行录制音频


    1、使用AVAudioRecorder录制视频

      AVAudioRecorder与AVAudioPlayer类似,它们都属于AVFoundation的类。AVAudioRecorder的功能类似于一个录音器,使用AVAudioRecorder录制音频十分简单,当程序控制AVAudioRecorder对象创建完成之后,可以调用AVAudioRecorder的如下方法进行录制。

      1、prepareToRecord:准备开始录制。调用record方法时,如果音频还没有准备好,程序会隐式先执行该方法。

      2、record:开始或恢复录制。调用该方法是,如果音频还没有准备好,程序会隐式执行prepareToRecord方法。

      3、recordAtTime:在指定时间点开始或恢复录制。

      4、record(atTime time: TimeInterval, forDuration duration: TimeInterval) -> Bool 在指定时间点开始或恢复录制,并指定录制的持续时间。

      5、pause:暂停。stop:停止

      6、prepareToPlay:准备开始播放。如果play方法没有准备好时,会隐式先执行该方法。

      使用AVAudioRecorder录制视频的步骤如下:

      1、创建AVAudioRecorder对象。在创建AVAudioRecorder对象之前,先准备一个Dictionary对象,该对象中封装了音频的相关设置信息。

    //创建字典,用于保存录制属性
            let recordSettings:[String:Any] = [
                //设置录制音频的格式
                AVFormatIDKey:kAudioFormatAppleLossless,
                AVEncoderAudioQualityKey: AVAudioQuality.max.rawValue,
                AVEncoderBitRateKey: 32000,
                 //设置录制音频的每个样点的通道数
                AVNumberOfChannelsKey: 2,
                //设置录制音频的采样率
                AVSampleRateKey: 44100.0
            ]

      2、如果需要监听录制完成、录制被中断的事件,则应该为AVAudioRecorder对象设置delegate对象,delegate对象需要实现AVAudioRecorderDelegate协议。

    func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
            print("录制完成")
            stopBtn.isEnabled = false
            playBtn.isEnabled = true
            recordBtn.setTitle("录制", for: .normal)
            //弹窗选择
            let alert = UIAlertController(title: "录制", message: "录制完成", preferredStyle:.alert)
            alert.addAction(UIAlertAction(title: "保存", style: .default, handler: {[unowned self] _ in
                self.recorder = nil
            }))
            alert.addAction(UIAlertAction(title: "删除", style:.default, handler: { [unowned self] _ in
                self.recorder.deleteRecording()
            }))
            self.present(alert, animated: true, completion: nil)
        }
        
        func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder,
                                              error: Error?) {
            print("(#function)")
            
            if let e = error {
                print("(e.localizedDescription)")
            }
        }

      3、调用AVAudioRecorder对象的record方法录制视频。

      案例代码:

    import UIKit
    import AVFoundation
    import AVKit
    class NAPublishViewController : UIViewController {
        var recorder : AVAudioRecorder!
        var player : AVAudioPlayer!
        
        var meterTimer : Timer!
        var soundFileUrl : URL!
        
        lazy var recordBtn : UIButton = {
            let recordBtn = UIButton()
            recordBtn.setTitle("录音", for: .normal)
            recordBtn.setTitleColor(.black, for: .normal)
            recordBtn.addTarget(self, action: #selector(recordAction(sender:)), for: .touchUpInside)
            return recordBtn
        }()
        
        lazy var stopBtn : UIButton = {
            let stopBtn = UIButton()
            stopBtn.setTitle("停止", for: .normal)
            stopBtn.setTitleColor(.black, for: .normal)
            stopBtn.addTarget(self, action:#selector(stopBtnAction(sender:)) , for: .touchUpInside)
            return stopBtn
        }()
        
        lazy var playBtn : UIButton = {
            let playBtn = UIButton()
            playBtn.setTitle("播放", for: .normal)
            playBtn.setTitleColor(.black, for: .normal)
            playBtn.addTarget(self , action: #selector(playBtnAction(sender:)), for: .touchUpInside)
            return playBtn
        }()
    
        lazy var statusLabel : UILabel = {
            let statusLabel = UILabel()
            statusLabel.text = "00:00"
            statusLabel.textColor = .black
            return statusLabel
        }()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            setSubViewsConstraints()
            
            stopBtn.isEnabled = false
            playBtn.isEnabled = false
            
            setSessionPlayback()
            
        }
        
        @objc func playBtnAction(sender:UIButton) -> Void {
            var url: URL?
            if self.recorder != nil {
                url = self.recorder.url
            } else {
                url = self.soundFileUrl!
            }
            print("playing (String(describing: url))")
            
            do {
                self.player = try AVAudioPlayer(contentsOf: url!)
                stopBtn.isEnabled = true
                player.delegate = self
                player.prepareToPlay()
                player.volume = 1.0
                player.play()
            } catch {
                self.player = nil
                print(error.localizedDescription)
            }
        }
        
        @objc func stopBtnAction(sender:UIButton) -> Void {
            recorder?.stop()
            player?.stop()
            
            meterTimer.invalidate()
            recordBtn.setTitle("录音", for: .normal)
            let session = AVAudioSession.sharedInstance()
            do {
                try session.setActive(false)
                playBtn.isEnabled = true
                stopBtn.isEnabled = false
                recordBtn.isEnabled = true
            } catch  {
                print(error.localizedDescription)
            }
        }
        
        @objc func recordAction(sender:UIButton) -> Void {
            if player != nil && player.isPlaying {
                print("stopping")
                player.stop()
            }
            
            if recorder == nil {
                recordBtn.setTitle("暂停", for: .normal)
                playBtn.isEnabled = false
                stopBtn.isEnabled = true
                recordWithPermission(true)
                return
            }
            
            if recorder != nil && recorder.isRecording {
                recorder.pause()
                recordBtn.setTitle("继续", for: .normal)
            } else {
                recordBtn.setTitle("暂停", for: .normal)
                playBtn.isEnabled = false
                stopBtn.isEnabled = true
                recordWithPermission(false)
            }
            
        }
        
        func recordWithPermission(_ setup: Bool) {
            AVAudioSession.sharedInstance().requestRecordPermission { (granted) in
                if granted {
                    DispatchQueue.main.async {
                        self.setSessionPlayAndRecord()
                        
                        if setup {
                            self.setupRecorder()
                        }
                        self.recorder.record()
                        
                        self.meterTimer = Timer.scheduledTimer(timeInterval: 0.1,
                                                               target: self,
                                                               selector: #selector(self.updateAudioMeter(_:)),
                                                               userInfo: nil,
                                                               repeats: true)
                    }
                } else {
                    print("Permission to record not granted")
                }
            }
            
            if  AVAudioSession.sharedInstance().recordPermission == .denied {
                print("permission denied")
            }
        }
        
        func setupRecorder() {
            let format = DateFormatter()
            format.dateFormat="yyyy-MM-dd-HH-mm-ss"
            let currentFileName = "recording-(format.string(from: Date())).m4a"
            print(currentFileName)
            //获取沙盒文件目录
            let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
            //拼接路径
            self.soundFileUrl = documentsDirectory.appendingPathComponent(currentFileName)
            print("writing to soundfile url: '(soundFileUrl!)'")
            
            if FileManager.default.fileExists(atPath: soundFileUrl.absoluteString) {
                print("soundfile (soundFileUrl.absoluteString) 存在")
            }
            
            //创建字典,用于保存录制属性
            let recordSettings:[String:Any] = [
                //设置录制音频的格式
                AVFormatIDKey:kAudioFormatAppleLossless,
                AVEncoderAudioQualityKey: AVAudioQuality.max.rawValue,
                AVEncoderBitRateKey: 32000,
                 //设置录制音频的每个样点的通道数
                AVNumberOfChannelsKey: 2,
                //设置录制音频的采样率
                AVSampleRateKey: 44100.0
            ]
            
            do {
                recorder = try AVAudioRecorder(url: soundFileUrl, settings: recordSettings)
                recorder.delegate = self
                recorder.isMeteringEnabled = true
                recorder.prepareToRecord()
            } catch {
                recorder = nil
                print(error.localizedDescription)
            }
            
        }
        func setSessionPlayAndRecord() {
            //获取当前应用的音频会话
            let session = AVAudioSession.sharedInstance()
            do {
                //设置音频类别,PlayAndRecord - 这说明当前音频会话既可播放,又可录制
                try session.setCategory(AVAudioSession.Category.playAndRecord, options: AVAudioSession.CategoryOptions.defaultToSpeaker)
            } catch {
                print(error.localizedDescription)
            }
            
            do {
                try session.setActive(true)
            } catch {
                print(error.localizedDescription)
            }
        }
        
        func setSessionPlayback()  {
            //获取当前应用的音频会话
            let session = AVAudioSession.sharedInstance()
            
            do {
                //设置音频类别
                try session.setCategory(AVAudioSession.Category.playback, options: AVAudioSession.CategoryOptions.defaultToSpeaker)
            } catch {
                print("不能设置session category")
                print(error.localizedDescription)
            }
            
            do {
                //激活当前应用的音频会话
                try session.setActive(true, options: AVAudioSession.SetActiveOptions.notifyOthersOnDeactivation)
            } catch  {
                print("不能设置session active")
                print(error.localizedDescription)
            }
        }
        
        @objc func updateAudioMeter(_ timer: Timer) {
            
            if let recorder = self.recorder {
                if recorder.isRecording {
                    let min = Int(recorder.currentTime / 60)
                    let sec = Int(recorder.currentTime.truncatingRemainder(dividingBy: 60))
                    let s = String(format: "%02d:%02d", min, sec)
                    statusLabel.text = s
                    recorder.updateMeters()
                }
            }
        }
        
        func setSubViewsConstraints() -> Void {
            view.addSubview(recordBtn)
            recordBtn.snp.makeConstraints { (make) in
                make.left.width.height.equalTo(50)
                make.top.equalTo(100)
            }
            
            view.addSubview(stopBtn)
            stopBtn.snp.makeConstraints { (make) in
                make.centerX.equalToSuperview()
                make.width.height.equalTo(50)
                make.top.equalTo(100)
            }
            
            view.addSubview(playBtn)
            playBtn.snp.makeConstraints { (make) in
                make.right.equalTo(-50)
                make.width.height.equalTo(50)
                make.top.equalTo(100)
            }
            
            view.addSubview(statusLabel)
            statusLabel.snp.makeConstraints { (make) in
                make.centerX.equalToSuperview()
                make.width.height.equalTo(50)
                make.top.equalTo(stopBtn.snp_bottom).offset(30)
                
            }
        }
        
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            recorder = nil
            player = nil
        }
    }
    
    extension NAPublishViewController : AVAudioRecorderDelegate {
        
        func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
            print("录制完成")
            stopBtn.isEnabled = false
            playBtn.isEnabled = true
            recordBtn.setTitle("录制", for: .normal)
            //弹窗选择
            let alert = UIAlertController(title: "录制", message: "录制完成", preferredStyle:.alert)
            alert.addAction(UIAlertAction(title: "保存", style: .default, handler: {[unowned self] _ in
                self.recorder = nil
            }))
            alert.addAction(UIAlertAction(title: "删除", style:.default, handler: { [unowned self] _ in
                self.recorder.deleteRecording()
            }))
            self.present(alert, animated: true, completion: nil)
        }
        
        func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder,
                                              error: Error?) {
            print("(#function)")
            
            if let e = error {
                print("(e.localizedDescription)")
            }
        }
    }
    
    
    extension NAPublishViewController : AVAudioPlayerDelegate {
        func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
    
            recordBtn.isEnabled = true
            stopBtn.isEnabled = false
        }
        
        func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?) {
            print("(#function)")
            
            if let e = error {
                print("(e.localizedDescription)")
            }
            
        }
    }
    使用AVAudioRecorder进行录制视频

       运行效果图: 

  • 相关阅读:
    接口开发
    操作Excel
    操作mongodb
    sys模块
    操作redis
    操作数据库
    日志生成、发送邮件
    Codeforces Round #487 (Div. 2)
    bitset学习
    Training for 分块&莫队
  • 原文地址:https://www.cnblogs.com/xjf125/p/10922541.html
Copyright © 2020-2023  润新知