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: ,
//设置录制音频的每个样点的通道数
AVNumberOfChannelsKey: ,
//设置录制音频的采样率
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)[]
//拼接路径
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: ,
//设置录制音频的每个样点的通道数
AVNumberOfChannelsKey: ,
//设置录制音频的采样率
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 / )
let sec = Int(recorder.currentTime.truncatingRemainder(dividingBy: ))
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()
make.top.equalTo()
} view.addSubview(stopBtn)
stopBtn.snp.makeConstraints { (make) in
make.centerX.equalToSuperview()
make.width.height.equalTo()
make.top.equalTo()
} view.addSubview(playBtn)
playBtn.snp.makeConstraints { (make) in
make.right.equalTo(-)
make.width.height.equalTo()
make.top.equalTo()
} view.addSubview(statusLabel)
statusLabel.snp.makeConstraints { (make) in
make.centerX.equalToSuperview()
make.width.height.equalTo()
make.top.equalTo(stopBtn.snp_bottom).offset() }
} 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进行录制视频

  运行效果图:

iOS音频与视频的开发(二)- 使用AVAudioRecorder进行录制音频的更多相关文章

  1. iOS音频与视频的开发(一)-使用AVAudioPlayer播放音乐、使用AVPlayerViewController播放视频

    iOS的多媒体支持非常强大,它提供了多套支持多媒体的API,无论是音频.视频的播放,还是录制,iOS都提供了多种API支持.借助于这些API的支持,iOS应用既可以查看.播放手机相册中的照片.视频,也 ...

  2. Android 音视频开发(二):使用 AudioRecord 采集音频数据并保存到文件

    版权声明:转载请说明出处:http://www.cnblogs.com/renhui/p/7457321.html 一.AudioRecord API详解 AudioRecord是Android系统提 ...

  3. Android 音视频开发(二):使用 AudioRecord 采集音频PCM并保存到文件

    版权声明:转载请说明出处:http://www.cnblogs.com/renhui/p/7457321.html 一.AudioRecord API详解 AudioRecord是Android系统提 ...

  4. html5页面怎么播放音频和视频

    html5页面怎么播放音频和视频 一.总结 一句话总结:html5 音频和视频标签:(audio And video),局限是不同浏览器对音频视频的格式支持很让人头痛 1.最基础的音频和视频标签的使用 ...

  5. 《转》iOS音频视频初级开发

    代码改变世界 Posts - 73, Articles - 0, Comments - 1539 Cnblogs Dashboard Logout HOME CONTACT GALLERY RSS   ...

  6. Android IOS WebRTC 音视频开发总结(二九)-- 安卓噪声消除交流

    Android上的音质一直被大家所困扰和诟病,这里面有很多原因, 下面是最近一位前UC同行发邮件跟我交流的一些记录,供参考,支持原创,文章来自博客园RTC.Blacker,转载请说明出处. 以下文字来 ...

  7. 转:Android IOS WebRTC 音视频开发总结 (系列文章集合)

    随笔分类 - webrtc   Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译和整理的,译 ...

  8. iOS开发-二维码扫描和应用跳转

    iOS开发-二维码扫描和应用跳转   序言 前面我们已经调到过怎么制作二维码,在我们能够生成二维码之后,如何对二维码进行扫描呢? 在iOS7之前,大部分应用中使用的二维码扫描是第三方的扫描框架,例如Z ...

  9. Android IOS WebRTC 音视频开发总结(四九)-- ffmpeg介绍

    本文主要介绍ffmpeg,文章来自博客园RTC.Blacker,支持原创,转载必须说明出处,个人微信公众号blacker,更多详见www.rtc.help 说明: ps1:如果直接从webrtc开始学 ...

随机推荐

  1. WPF MVVM UI分离之《交互与数据分离》 基础才是重中之重~delegate里的Invoke和BeginInvoke 将不确定变为确定系列~目录(“机器最能证明一切”) 爱上MVC3系列~全局异常处理与异常日志 基础才是重中之重~lock和monitor的区别 将不确定变成确定~我想监视我的对象,如果是某个值,就叫另一些方法自动运行 将不确定变成确定~LINQ DBML模型可以对

    WPF MVVM UI分离之<交互与数据分离>   在我们使用WPF过程中,不可避免并且超级喜欢使用MVVM框架. 那么,使用MVVM的出发点是视觉与业务逻辑分离,即UI与数据分离 诸如下 ...

  2. js中创建html标签、加入select下默认的option的value和text、删除select元素节点下全部的OPTION节点

    <pre name="code" class="java"> jsp 中的下拉框标签: <s:select name="sjx&qu ...

  3. iOS Webview 与 app交互

    有时候我们在内嵌的webview中希望点击一个链接之后,触发iOS原生事件,而不是webview内页面跳转(因为webview的跳转很生硬,而ajax+js模拟则不如原生segue平滑). 有时候我们 ...

  4. android 编程小技巧(持续中)

    first:     Intent跳转一般存用于Activity类,可是若要在非activity类里跳转的话,解决方法是在startActivity(intent)前加mContext即上下文,终于为 ...

  5. 1987年国际C语言混乱代码大赛获奖的一行代码

    macb() ? lpcbyu(&gbcq/_\021%ocq\012\0_=w(gbcq)/_dak._=}_ugb_[0q60)s+ 这是CoolShell博主之前做了一个非常有意思的在线 ...

  6. Mac OS用vmvare安装多节点kubernetes

    参考网址 https://kubernetes.io/docs/setup/ 1.安装vmvare 2.下载ubuntu镜像(可以不要界面,可以下载server版大约900M,否则下载desktop版 ...

  7. Writing a Discard Server

    Netty.docs: User guide for 4.x https://netty.io/wiki/user-guide-for-4.x.html

  8. golang-----golang sync.WaitGroup解决goroutine同步

    go提供了sync包和channel来解决协程同步和通讯.新手对channel通道操作起来更容易产生死锁,如果时缓冲的channel还要考虑channel放入和取出数据的速率问题. 从字面就可以理解, ...

  9. YTU 2452: 麦克劳林用于函数求值

    2452: 麦克劳林用于函数求值 时间限制: 1 Sec  内存限制: 128 MB 提交: 18  解决: 12 题目描述 泰勒公式是一个用函数在某点的信息描述其附近取值的公式.如果函数足够光滑的话 ...

  10. Html5--6-46 渐变效果

    Html5--6-46 渐变效果 学习要点 掌握线性渐变和径向渐变的使用 线性渐变: 属性:linear-gradinet(开始位置 角度,起始颜色,终止颜色 ) 开始位置:渐变开始的位置,属性值可以 ...