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进行录制视频
运行效果图: