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: 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进行录制视频

  运行效果图:

原文地址:https://www.cnblogs.com/xjf125/p/10922541.html

时间: 2024-10-13 09:47:14

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

android基础---->音频和视频的使用

Android 在播放音频和视频方面也是做了相当不错的支持,它提供了一套较为完整的API,使得开发者可以很轻松地编写出一个简易的音频或视频播放器.今天我们开始android中音频和视频使用的学习. 目录导航 音频的播放 视频的播放 友情链接 音频的播放 项目结构如下:一个简单的读取sd卡上的音频或者视频资源的应用 在Android 中播放音频文件一般都是使用MediaPlayer 类来实现的,它对多种格式的音频文件提供了非常全面的控制方法,从而使得播放音乐的工作变得十分简单. 一. 初始化音频的

Android IOS WebRTC 音视频开发总结(二九)

Android上的音质一直被大家所困扰和诟病,这里面有很多原因, 下面是最近一位前UC同行发邮件跟我交流的一些记录,供参考,支持原创,文章来自博客园RTC.Blacker,转载请说明出处. 以下文字来自邮件,为便于阅读和理解,略有整理: "Blacker,您好,本人一直从事音视频算法的处理与研究,包括H264视频,语音抑制,回音消除,噪音处理等分支.最近已经转向webrtc了,对webrtc也算是相对熟悉了.不过我在利用webrtc模块来开发时,遇到了一个音频采集的问题.不知道你是否遇到了,你们

iOS音视频项目开发(跨平台)

苹果手机带动了IOS的火热,一大堆开发人员在捣鼓IOS平台的开发,相信大家也使用过QQ的语音视频对话功能,但是不知道大家有没有试过自己来开发一个基于IOS平台的音视频即时通讯的应用,这个应用必须能够做到跨平台.现在介绍两种方法使用IOS与其他平台的音视频通话. 首先就是使用一个跨平台的音视频通讯平台即可,这是作为非专业技术人员也可以做到的,下面就先介绍第一种:只需三个条件: 1.手机有网络连接: 2.有AnyChat for iOS SDK: 3.对方PC或手机有以上条件. AnyChat音视频

即时通讯 iOS音视频技术开发

随着iOS的强势面世,伴随着其出色的应用,一大堆开发人员在捣鼓IOS平台的开发,而基于iOS的音视频二次开发应用也为更多的程序员猛攻猛打.相信大家也使用过QQ的语音视频对话功能,但是不知道大家有没有试过自己来开发一个基于IOS平台的音视频即时通讯的应用,这个应用必须能够做到跨平台 支持iOS平台设备上的音频即时通讯应用开发 提供Objective-C语言API接口,开放示例源代码 集成H.264.AAC.AMR等编解码技术 封装音视频的采集.编解码.传输.显示和播放等模块 支持Android.W

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

随笔分类 - webrtc Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:blackerteam 或 webrtcorgcn). callstats是一家做实时通讯性能测阅读全文 posted @ 2016-07-22 08:24

iOS音视频SDK开发技术解决方案

随着iOS的强势面世,伴随着其出色的应用,一大堆开发人员在捣鼓IOS平台的开发,而基于iOS的音视频二次开发应用也为更多的程序员猛攻猛打.相信大家也使用过QQ的语音视频对话功能,但是不知道大家有没有试过自己来开发一个基于IOS平台的音视频即时通讯的应用,这个应用必须能够做到跨平台 ·                      支持iOS平台设备上的音频即时通讯应用开发 ·                      提供Objective-C语言API接口,开放示例源代码 ·           

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

iOS开发-二维码扫描和应用跳转 序言 前面我们已经调到过怎么制作二维码,在我们能够生成二维码之后,如何对二维码进行扫描呢? 在iOS7之前,大部分应用中使用的二维码扫描是第三方的扫描框架,例如ZXing或者ZBar.使用时集成麻烦,出错也不方便调试.在iOS7之后,苹果自身提供了二维码的扫描功能,从效率上来说,原生的二维码远高于这些第三方框架.本文讲解如何使用原生框架实现二维码扫描功能,并且进行扫描后的项目跳转.ps:本期的源代码会在文章结尾给出链接 扫描相关类 二维码扫描需要获取摄像头并读取

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

本文主要介绍ffmpeg,文章来自博客园RTC.Blacker,支持原创,转载必须说明出处,个人微信公众号blacker,更多详见www.rtc.help 说明: ps1:如果直接从webrtc开始学习音视频,你可能没听过ffmpeg,也不需要用到,但随着个人能力提升,你会发现这套东西确实很有用. 就我目前接触到的音视频企业,还没有碰到过没用过ffmpeg的(视频厂商都会对用户上传的视频文件做转码,因为他们的客户端在播放的时候需要根据不同客户端的网络带宽适配不同分辨率,或做些自定义开发),由此可

Android IOS WebRTC 音视频开发总结(二三)

本文主要介绍如何测试基于浏览器和手机的视频通话程序,转载请说明出处,文章来自博客园RTC.Blacker. 因为https://apprtc.appspot.com访问不了,不少想测试视频通话的人有点失望,所以将自己的开发程序提供给大家测试,详细说明如下: 一. 演示注意事项 1.1. 附件说明 1.1.1. 如需通过手机APP进行测试,请先去附件里面下载相应的apk.        1.1.2. iOS因涉及越狱暂未提供安装程序,如有特别需要请单独跟我联系. 1.2. 测试地址 1.1.1.