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. 最小公倍数(Least Common Multiple)

    最小公倍数=两个数的乘积/两个数的最大公约数. 接上篇求最大公约数方法,最小公倍数的代码例如以下: public class LCM { //最小公倍数=两数乘积/最大公约数 public stati ...

  2. 基于bootstrap_登陆页面

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. VMWare 14 Workstation Pro 下载与安装

    1.双击安装运行 2.下一步 3.接受 下一步 4.自定义安装路径,下一步 5.下一步,取消勾选加入vmware客户体验 6.下一步 7.安装 8.安装中 9.完成 10.点击许可证安装 输入:FF3 ...

  4. 解决asp.net mvc UpdateModel更新对象后出现null问题的方法

    在用asp.net mvc 4.0做项目的时候遇到的这种情况:情况分析:“在填写表单的时候,有一些表单没有填写,留空,然后直接post 提交表单,action中用UpdateModel 来更新mode ...

  5. c++string 输入换行符

    string 一次只能输入一行,不含换行符.可以自己添加换行符 和输入行数.例如:#include <iostream>#include <string>using names ...

  6. Codeforces Round #426 (Div. 2) D. The Bakery 线段树优化DP

    D. The Bakery   Some time ago Slastyona the Sweetmaid decided to open her own bakery! She bought req ...

  7. 【ACdream】1157 Segments cdq分治

    Segments   Problem Description 由3钟类型操作:1)D L R(1 <= L <= R <= 1000000000) 增加一条线段[L,R]2)C i ...

  8. (C)字节对齐#pragma pack()

    1. 为什么要进行对齐 对于结构体,编译器会自动进行成员变量对齐处理,是为了提高运算效率. 缺省情况下是自然对齐方式. 2. 自然对齐 即默认对齐,按照结构体的成员中size最大的成员进行对齐. 例: ...

  9. WPF之Binding深入探讨 转载:http://blog.csdn.net/fwj380891124/article/details/8107646

    1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在存储.逻辑和界面三层之间流通,所以站在数据的角度上来看,这三层都很重要.但算法在3层中的分布是不均匀的,对于一个3层结构的 ...

  10. bzoj 1657 Mooo 奶牛的歌声 —— 单调栈

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1657 单调栈水题. 代码如下: #include<iostream> #incl ...