iOS多媒体音频(下)-录音及其播放的实例

上一篇中总结了iOS中音效和音频播放的最基本使用方法,其中音频的播放控制是使用AVFoundation.framework框架中的AVAudioPlayer播放器对象来实现的,而这里音频的录制则是使用了同样框架下的一个叫AVAudioRecorder的录音机对象来实现,这两个类的用法流程非常类似,类的属性和方法也类似,例如:播放器中需要获取音频文件的url,而录音机要在沙盒中Docuemnt目录下创建一个音频文件路径url;

播放器有isPlaying变量判断是否正在播放,录音机中有isRecording变量表示是否正在录制;currentTime在播放器中表示播放时间,在录音机中则表示录音时间;播放器通过prepareToPlay方法加载文件到缓冲区,录音机通过prepareToRecord创建缓冲区;播放音频有play方法,音频录制有record方法,另外都有pause暂停方法和stop停止方法等等,具体可直接打开两个类的头文件详细了解。

这里实现最基本的录音流程以及录音过程的控制,并通过之前使用的AVAudioPlayer来播放录制好的音频。注意iOS录制的音频为caf格式,如果需要通用化可以通过lame等插件将caf格式音频转成mp3格式。

录音

这里实现开始录音,暂停,继续以及停止录音。

创建文件目录

iOS沙盒内胡要有三个目录:Documents目录,tmp目录以及Library目录,其中Documents目录用来存放用户的应用程序数据,需要定期备份的数据要放在这里,和plist文件存储一样,我们要找到存放文件的路径,然后在该路径下放一个我们的文件,因此要自定义一个带后缀的文件名,将获得的路径和文件名拼在一起记得到我们的文件的绝对路径:

// 文件名
#define fileName_caf @"demoRecord.caf"
// 录音文件绝对路径
@property (nonatomic, copy) NSString *filepathCaf;

// 获取沙盒Document文件路径
NSString *sandBoxPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
// 拼接录音文件绝对路径
_filepathCaf = [sandBoxPath stringByAppendingPathComponent:fileName_caf];

创建音频会话

录音前要创建一个音频会话,同时要设置录音类型,提供的类型有以下几种:

  • AVF_EXPORT NSString *const AVAudioSessionCategoryAmbient; // 用于录制背景声音,像雨声、汽车引擎发动噪音等,可和其他音乐混合
  • AVF_EXPORT NSString *const AVAudioSessionCategorySoloAmbient; // 也是背景声音,但其他音乐会被强制停止
  • AVF_EXPORT NSString *const AVAudioSessionCategoryPlayback; // 音轨
  • AVF_EXPORT NSString *const AVAudioSessionCategoryRecord; // 录音
  • AVF_EXPORT NSString *const AVAudioSessionCategoryPlayAndRecord; // 录音和回放
  • AVF_EXPORT NSString *const AVAudioSessionCategoryAudioProcessing; // 用于底层硬件编码信号处理等
  • AVF_EXPORT NSString *const AVAudioSessionCategoryMultiRoute; // 内置硬件相关,iOS 6.0以上可用

常用的是AVAudioSessionCategoryPlayAndRecord类型,便于录音后播放。

// 创建音频会话
AVAudioSession *audioSession=[AVAudioSession sharedInstance];
// 设置录音类别(这里选用录音后可回放录音类型)
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[audioSession setActive:YES error:nil];

录音设置

录音前要根据需要对录音进行一些相应的基本设置,例如录音格式(LinearPCM)、采样率、通道数等等,设置保存在一个字典内并作为初始化录音机的一个参数。

// 录音设置
-(NSDictionary *)getAudioSetting{
  // LinearPCM 是iOS的一种无损编码格式,但是体积较为庞大
  // 录音设置信息字典
  NSMutableDictionary *recordSettings = [[NSMutableDictionary alloc] init];
  // 录音格式
  [recordSettings setValue :@(kAudioFormatLinearPCM) forKey: AVFormatIDKey];
  // 采样率
  [recordSettings setValue :@11025.0 forKey: AVSampleRateKey];
  // 通道数(双通道)
  [recordSettings setValue :@2 forKey: AVNumberOfChannelsKey];
  // 每个采样点位数(有8、16、24、32)
  [recordSettings setValue :@16 forKey: AVLinearPCMBitDepthKey];
  // 采用浮点采样
  [recordSettings setValue:@YES forKey:AVLinearPCMIsFloatKey];
  // 音频质量
  [recordSettings setValue:@(AVAudioQualityMedium) forKey:AVEncoderAudioQualityKey];
  // 其他可选的设置
  // ... ...

  return recordSettings;
}

创建录音机对象

录音机对象的创建主要是利用上面的保存路径和录音设置进行初始化得到:

// 懒加载录音机对象get方法
- (AVAudioRecorder *)audioRecorder {
  if (!_audioRecorder) {
    // 保存录音文件的路径url
    NSURL *url = [NSURL URLWithString:_filepathCaf];
    // 创建录音格式设置setting
    NSDictionary *setting = [self getAudioSetting];
    // error
    NSError *error=nil;

    _audioRecorder = [[AVAudioRecorder alloc]initWithURL:url settings:setting error:&error];
    _audioRecorder.delegate = self;
    _audioRecorder.meteringEnabled = YES;// 监控声波
    if (error) {
      NSLog(@"创建录音机对象时发生错误,错误信息:%@",error.localizedDescription);
      return nil;
    }
  }
  return _audioRecorder;
}

录音控制方法

录音过程控制主要是开始录音、暂停、继续和停止录音,其中开始录音和继续录音都是record方法。

// 开始录音或者继续录音
- (IBAction)startOrResumeRecord {
  // 注意调用audiorecorder的get方法
  if (![self.audioRecorder isRecording]) {
    // 如果该路径下的音频文件录制过则删除
    [self deleteRecord];
    // 开始录音,会取得用户使用麦克风的同意
    [_audioRecorder record];
  }
}

// 录音暂停
- (IBAction)pauseRecord {
  if (_audioRecorder) {
    [_audioRecorder pause];
  }
}

// 结束录音
- (IBAction)stopRecord {
  [_audioRecorder stop];
}

录音播放

录音的播放很简单,就是之前AVAudioPlayer音频播放的简单应用,播放的路径即我们录音时创建好的音频路径。但这里注意为了保证每次都播放最新录制的音频,播放器的get方法要每次重新创建初始化。

// audioPlayer懒加载getter方法
- (AVAudioPlayer *)audioPlayer {
  _audioRecorder = NULL; // 每次都创建新的播放器,删除旧的

  // 资源路径
  NSURL *url = [NSURL fileURLWithPath:_filepathCaf];

  // 初始化播放器,注意这里的Url参数只能为本地文件路径,不支持HTTP Url
  NSError *error = nil;
  _audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];

  //设置播放器属性
  _audioPlayer.numberOfLoops = 0;// 不循环
  _audioPlayer.delegate = self;
  _audioPlayer.volume = 0.5; // 音量
  [_audioPlayer prepareToPlay];// 加载音频文件到缓存【这个函数在调用play函数时会自动调用】

  if(error){
    NSLog(@"初始化播放器过程发生错误,错误信息:%@",error.localizedDescription);
    return nil;
  }

  return _audioPlayer;
}

// 播放录制好的音频
- (IBAction)playRecordedAudio {
  // 没有文件不播放
  if (![[NSFileManager defaultManager] fileExistsAtPath:self.filepathCaf]) return;
  // 播放最新的录音
  [self.audioPlayer play];
}

完整源码和Demo下载

//
// ViewController.m
// IOSRecorderDemo
//
// Created by Xinhou Jiang on 29/12/16.
// Copyright © 2016年 Xinhou Jiang. All rights reserved.
//

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>

// 文件名
#define fileName_caf @"demoRecord.caf"

@interface ViewController ()

// 录音文件绝对路径
@property (nonatomic, copy) NSString *filepathCaf;
// 录音机对象
@property (nonatomic, strong) AVAudioRecorder *audioRecorder;
// 播放器对象,和上一章音频播放的方法相同,只不过这里简单播放即可
@property (nonatomic, strong) AVAudioPlayer *audioPlayer;
// 用一个processview显示声波波动情况
@property (nonatomic, weak) IBOutlet UIProgressView *processView;
// 用一个label显示录制时间
@property (nonatomic, weak) IBOutlet UILabel *recordTime;
// UI刷新监听器
@property (nonatomic, strong) NSTimer *timer;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  // 初始化工作
  [self initData];
}

// 初始化
- (void)initData {
  // 获取沙盒Document文件路径
  NSString *sandBoxPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
  // 拼接录音文件绝对路径
  _filepathCaf = [sandBoxPath stringByAppendingPathComponent:fileName_caf];

  // 1.创建音频会话
  AVAudioSession *audioSession=[AVAudioSession sharedInstance];
  // 设置录音类别(这里选用录音后可回放录音类型)
  [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
  [audioSession setActive:YES error:nil];

  // 2.开启定时器
  [self timer];
}

#pragma mark -录音设置工具函数
// 懒加载录音机对象get方法
- (AVAudioRecorder *)audioRecorder {
  if (!_audioRecorder) {
    // 保存录音文件的路径url
    NSURL *url = [NSURL URLWithString:_filepathCaf];
    // 创建录音格式设置setting
    NSDictionary *setting = [self getAudioSetting];
    // error
    NSError *error=nil;

    _audioRecorder = [[AVAudioRecorder alloc]initWithURL:url settings:setting error:&error];
    _audioRecorder.delegate = self;
    _audioRecorder.meteringEnabled = YES;// 监控声波
    if (error) {
      NSLog(@"创建录音机对象时发生错误,错误信息:%@",error.localizedDescription);
      return nil;
    }
  }
  return _audioRecorder;
}

// audioPlayer懒加载getter方法
- (AVAudioPlayer *)audioPlayer {
  _audioRecorder = NULL; // 每次都创建新的播放器,删除旧的

  // 资源路径
  NSURL *url = [NSURL fileURLWithPath:_filepathCaf];

  // 初始化播放器,注意这里的Url参数只能为本地文件路径,不支持HTTP Url
  NSError *error = nil;
  _audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];

  //设置播放器属性
  _audioPlayer.numberOfLoops = 0;// 不循环
  _audioPlayer.delegate = self;
  _audioPlayer.volume = 0.5; // 音量
  [_audioPlayer prepareToPlay];// 加载音频文件到缓存【这个函数在调用play函数时会自动调用】

  if(error){
    NSLog(@"初始化播放器过程发生错误,错误信息:%@",error.localizedDescription);
    return nil;
  }

  return _audioPlayer;
}

// 计时器get方法
- (NSTimer *)timer {
  if (!_timer) {
    _timer = [NSTimer scheduledTimerWithTimeInterval:0.1f repeats:YES block:^(NSTimer * _Nonnull timer) {
      if(_audioRecorder) {
        // 1.更新录音时间,单位秒
        int curInterval = [_audioRecorder currentTime];
        _recordTime.text = [NSString stringWithFormat:@"%02d:%02d",curInterval/60,curInterval%60];
        // 2.声波显示
        //更新声波值
        [self.audioRecorder updateMeters];
        //第一个通道的音频,音频强度范围:[-160~0],这里调整到0~160
        float power = [self.audioRecorder averagePowerForChannel:0] + 160;
        [_processView setProgress:power/160.0];
      }
    }];
  }
  return _timer;
}

// 录音设置
-(NSDictionary *)getAudioSetting{
  // LinearPCM 是iOS的一种无损编码格式,但是体积较为庞大
  // 录音设置信息字典
  NSMutableDictionary *recordSettings = [[NSMutableDictionary alloc] init];
  // 录音格式
  [recordSettings setValue :@(kAudioFormatLinearPCM) forKey: AVFormatIDKey];
  // 采样率
  [recordSettings setValue :@11025.0 forKey: AVSampleRateKey];
  // 通道数(双通道)
  [recordSettings setValue :@2 forKey: AVNumberOfChannelsKey];
  // 每个采样点位数(有8、16、24、32)
  [recordSettings setValue :@16 forKey: AVLinearPCMBitDepthKey];
  // 采用浮点采样
  [recordSettings setValue:@YES forKey:AVLinearPCMIsFloatKey];
  // 音频质量
  [recordSettings setValue:@(AVAudioQualityMedium) forKey:AVEncoderAudioQualityKey];
  // 其他可选的设置
  // ... ...

  return recordSettings;
}

// 删除filepathCaf路径下的音频文件
-(void)deleteRecord{
  NSFileManager* fileManager=[NSFileManager defaultManager];
  if ([[NSFileManager defaultManager] fileExistsAtPath:self.filepathCaf]) {
    // 文件已经存在
    if ([fileManager removeItemAtPath:self.filepathCaf error:nil]) {
      NSLog(@"删除成功");
    }else {
      NSLog(@"删除失败");
    }
  }else {
    return; // 文件不存在无需删除
  }
}

#pragma mark -录音流程控制函数
// 开始录音或者继续录音
- (IBAction)startOrResumeRecord {
  // 注意调用audiorecorder的get方法
  if (![self.audioRecorder isRecording]) {
    // 如果该路径下的音频文件录制过则删除
    [self deleteRecord];
    // 开始录音,会取得用户使用麦克风的同意
    [_audioRecorder record];
  }
}

// 录音暂停
- (IBAction)pauseRecord {
  if (_audioRecorder) {
    [_audioRecorder pause];
  }
}

// 结束录音
- (IBAction)stopRecord {
  [_audioRecorder stop];
}

#pragma mark -录音播放
// 播放录制好的音频
- (IBAction)playRecordedAudio {
  // 没有文件不播放
  if (![[NSFileManager defaultManager] fileExistsAtPath:self.filepathCaf]) return;
  // 播放最新的录音
  [self.audioPlayer play];
}

@end

Demo下载:demo

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • iOS开发中音频工具类的封装以及音乐播放器的细节控制

    一.控制器间数据传递 两个控制器之间数据的传递 第一种方法: 复制代码 代码如下: self.parentViewController.music=self.music[indexPath.row]; 不能满足 第二种做法:把整个数组传递给它 第三种做法:设置一个数据源,设置播放控制器的数据源是这个控制器.self.parentViewController.dataSource=self;好处:没有耦合性,任何实现了协议的可以作为数据源. 第四种做法:把整个项目会使用到的音频资源交给一个工具类去

  • 浅析iOS中视频播放的几种方案

    1.AVPlayer (1) 优缺点 优点:可以自定义 UI, 进行控制 缺点:单纯的播放,没有控制 UI(进度,暂停,播放等按钮),而且如果要显示播放界面, 需要借助AVPlayerLayer, 添加图层到需要展示的图层上 (2)实现远程视频播放 实现播放功能(只有声音) 1.导入框架 #import <AVFoundation/AVFoundation.h> 2.通过远程 URL 创建 AVPlayer 对象 NSURL *remoteURL = [NSURL URLWithString:

  • iOS App中实现播放音效和音乐功能的简单示例

    播放音效 iOS开发过程中可能会遇到播放音效的功能 其实很简单,iOS已经提供了一个框架直接负责播放音效 AudioToolbox.framework 新建项目  TestWeChatSounds 给新建的项目导入AudioToolbox.framework 导入成功之后如下图 项目目录如下 接下来我们给项目中添加几个caf格式的音效文件 接下来 我们打开 项目默认生成的ViewController中添加代码 导入 AudioToolbox 复制代码 代码如下: #import <AudioTo

  • 讲解iOS开发中对音效和音乐播放的简单实现

    音效的播放 一.简单介绍 简单来说,音频可以分为2种 (1)音效 又称"短音频",通常在程序中的播放时长为1~2秒 在应用程序中起到点缀效果,提升整体用户体验 (2)音乐 比如游戏中的"背景音乐",一般播放时间较长 框架:播放音频需要用到AVFoundation.framework框架 二.音效的播放 1.获得音效文件的路径 复制代码 代码如下: NSURL *url = [[NSBundle mainBundle] URLForResource:@"m_

  • 详解iOS App中调用AVAudioPlayer播放音频文件的用法

    要给工程中添加音频,首先要导入音频的框架 AVFoundation.framework 然后新建一个类继承于UIViewController, 我这里就叫FirstVC. 首先在 AppDelegate.m中初始化根视图 复制代码 代码如下: #import "AppDelegate.h" #import "FirstVC.h" @implementation AppDelegate - (void)dealloc {     [_window release];

  • IOS开发实现录音功能

    导入框架: #import <AVFoundation/AVFoundation.h> 声明全局变量: @interface ViewController ()<AVAudioRecorderDelegate> { AVAudioRecorder *audioRecorder; } @end 在ViewDidLoad中: UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; button.frame = C

  • iOS实时录音和播放功能

    需求:最近公司需要做一个楼宇对讲的功能:门口机(连接WIFI)拨号对室内机(对应的WIFI)的设备进行呼叫,室内机收到呼叫之后将对收到的数据进行UDP广播的转发,手机(连接对应的WIFI)收到视频流之后,实时的展示视频数据(手机可以接听,挂断,手机接听之后,室内机不展示视频,只是进行转发.) 简单点说就是手机客户端需要做一个类似于直播平台的软件,可以实时的展示视频,实时的播放接收到的声音数据,并且实时将手机麦克风收到的声音回传给室内机,室内机负责转发给门口机. 这篇文章介绍iOS怎么进行实时的录

  • 实例解析iOS中音乐播放器应用开发的基本要点

    一.调整项目的结构,导入必要的素材 调整后的项目结构如下: 二.新建两个控制器 (1)新建一个控制器,用于展示音乐文件列表界面,其继承自UITableViewController (2)新建一个控制器,用于展示播放界面,其继承自UIViewController (3)在storyboard中,把之前的控制器删除,换上一个导航控制器,设置tableViewController与之前新建的控制器类进行关联 三.音乐文件列表控制器中基本界面的搭建 (1)新建一个音乐文件的模型 根据plist文件建立模

  • 详解iOS应用中播放本地视频以及选取本地音频的组件用法

    MPMoviePlayerControlle播放本地视频 MPMoviePlayerControlle与AVAudioPlayer有点类似,前者播放视频,后者播放音频,不过也有很大不同,MPMoviePlayerController 可以直接通过远程URL初始化,而AVAudioPlayer则不可以.不过大体上用起来感觉差不多.废话少说进入体验. 格式支持:MOV.MP4.M4V.与3GP等格式,还支持多种音频格式. 首先你得引入 MediaPlayer.framework.然后在使用到MPMo

  • iOS实现录音转码MP3及转码BASE64上传示例

    iOS 录音转码MP3及转码BASE64上传 一,开始录音 NSLog(@"开始录音"); [self startRecord]; - (void)startRecord { //删除上次生成的文件,保留最新文件 NSFileManager *fileManager = [NSFileManager defaultManager]; if ([NSTemporaryDirectory() stringByAppendingString:@"myselfRecord.mp3&q

随机推荐