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