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: ,
//设置录制音频的每个样点的通道数
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进行录制音频的更多相关文章
- iOS音频与视频的开发(一)-使用AVAudioPlayer播放音乐、使用AVPlayerViewController播放视频
iOS的多媒体支持非常强大,它提供了多套支持多媒体的API,无论是音频.视频的播放,还是录制,iOS都提供了多种API支持.借助于这些API的支持,iOS应用既可以查看.播放手机相册中的照片.视频,也 ...
- Android 音视频开发(二):使用 AudioRecord 采集音频数据并保存到文件
版权声明:转载请说明出处:http://www.cnblogs.com/renhui/p/7457321.html 一.AudioRecord API详解 AudioRecord是Android系统提 ...
- Android 音视频开发(二):使用 AudioRecord 采集音频PCM并保存到文件
版权声明:转载请说明出处:http://www.cnblogs.com/renhui/p/7457321.html 一.AudioRecord API详解 AudioRecord是Android系统提 ...
- html5页面怎么播放音频和视频
html5页面怎么播放音频和视频 一.总结 一句话总结:html5 音频和视频标签:(audio And video),局限是不同浏览器对音频视频的格式支持很让人头痛 1.最基础的音频和视频标签的使用 ...
- 《转》iOS音频视频初级开发
代码改变世界 Posts - 73, Articles - 0, Comments - 1539 Cnblogs Dashboard Logout HOME CONTACT GALLERY RSS ...
- Android IOS WebRTC 音视频开发总结(二九)-- 安卓噪声消除交流
Android上的音质一直被大家所困扰和诟病,这里面有很多原因, 下面是最近一位前UC同行发邮件跟我交流的一些记录,供参考,支持原创,文章来自博客园RTC.Blacker,转载请说明出处. 以下文字来 ...
- 转:Android IOS WebRTC 音视频开发总结 (系列文章集合)
随笔分类 - webrtc Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译和整理的,译 ...
- iOS开发-二维码扫描和应用跳转
iOS开发-二维码扫描和应用跳转 序言 前面我们已经调到过怎么制作二维码,在我们能够生成二维码之后,如何对二维码进行扫描呢? 在iOS7之前,大部分应用中使用的二维码扫描是第三方的扫描框架,例如Z ...
- Android IOS WebRTC 音视频开发总结(四九)-- ffmpeg介绍
本文主要介绍ffmpeg,文章来自博客园RTC.Blacker,支持原创,转载必须说明出处,个人微信公众号blacker,更多详见www.rtc.help 说明: ps1:如果直接从webrtc开始学 ...
随机推荐
- C++对象模型——Default Constructor的建构操作(第二章)
第2章 构造函数语意学 (The Semantics of Constructor) 关于C++,最常听到的一个抱怨就是,编译器背着程序猿做了太多事情.Conversion运算符就是最常被引用的 ...
- Elasticsearch 学习笔记 Elasticsearch及Elasticsearch head安装配置
一.安装与配置 1.到官网下载Elasticsearch,https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.6. ...
- MFC Month Calendar Control 控件使用
在上层软件编程中,往往须要提供一个月历控件让用户选择对应日期或者用此月历控件来强调特定的一天. MFC的 Month Calendar Control 控件自系统升级到 Windows 7 之后,对于 ...
- HashTable源代码剖析
<span style="font-size:14px;font-weight: normal;">public class Hashtable<K,V> ...
- Redis java使用
直接应用redis.clients:jedis的jar包到项目中,然后直接就可以使用,具体对五种类型的数据操作方法,可以翻代码找到. 连接到 redis 服务 实例 import redis.clie ...
- T-SQL查询进阶--变量
概述 变量对于一种语言是必不可少的一部分,当然,对于T-SQL来讲也是一样.在简单查询中,往往很少用到变量,但无论对于复杂的查询或存储过程中,变量都是必不可少的一部分. 变量的种类 在T-SQL中,变 ...
- STM32唯一身份识别ID(器件电子签名)的读取以及芯片Flash大小读取
每个STM32有一个独立的ID,这个ID可以用来: 产品唯一的身份标识的作用: ● 用来作为序列号(例如USB字符序列号或者其他的终端应用): ● 用来作为密码,在编写闪存时,将此唯一 ...
- 解决gradle多模块依赖在Idea中能运行,gradle build失败的问题。
最近需要初始化一个SpringBoot新项目遇到一个问题就是:项目中有多个子模块,使用gradle依赖管理成功. 项目结构如下: project --module1 --module2我的mo ...
- (31)java web的hibernate使用-一级缓存,二级缓存
参考:https://blog.csdn.net/miachen520/article/details/52195832 hibernate自带一级缓存 和 二级缓存 一,一级缓存: 基于Sessio ...
- BestCoder5 1001 Poor Hanamichi(hdu 4956) 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4956(它放在题库后面的格式有一点点问题啦,所以就把它粘下来,方便读者观看) 题目意思:给出一个范围 [ ...