使用AVAudioRecorder录制音频

Posted absty-guo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用AVAudioRecorder录制音频相关的知识,希望对你有一定的参考价值。

AVAudioRecorder 同AVAudioPlayer 类似,都是AVFoundation框架下的类

AVAudioRecorder 是一个录音器,可以调用方法来录制音频,使用还是比较简单的。

一、开启录音权限,并设置录音category

需要在info.plist文件中添加Privacy - Microphone Usage Description

//请求录音权限
[[AVAudiosession sharedInstance] requestRecordPermission:^(BOOL granted) {
    //yes表示用户同意
    if (granted) {
        NSError * error = nil;
        //设置录音category
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryRecord error:&error];
        if (error) {
            NSLog(@"设置录音类别失败");
        }
        [[AVAudioSession sharedInstance] setActive:YES error:&error];
        if (error) {
            NSLog(@"激活类别失败");
        }
    } else {
        NSLog(@"用户不允许录音");
    }
}];

备注:AVAudioSessionCategoryRecord 只是使用录音通道,设置了之后只能录音,不能播放音频。
也可以使用AVAudioSessionCategoryPlayAndRecord 可以一边播放一边录音,有语音唤醒的应用一般需要使用这个category

二、初始化录音器

两种初始化方法

- (nullable instancetype)initWithURL:(NSURL *)url settings:(NSDictionary<NSString *, id> *)settings error:(NSError **)outError;
- (nullable instancetype)initWithURL:(NSURL *)url format:(AVAudioFormat *)format error:(NSError **)outError;

url:指要存储音频的本地路径地址
settings/format:录制会话的设置
outError:错误描述

2.1 settings字典的所需key

音频格式设置

  • AVFormatIDKey

    格式标识符。取值为 AudioFormatID 类型

  • AVSampleRateKey

    用于定义录音的采样率。数值越小,录音质量越差,对应的录音文件越小。数值越大,录音质量越好,对应的录音文件越大。比如8000(AM广播类型的录制效果),16000,22050或者44100(CD质量的采样率)

  • AVNumberOfChannelsKey

    用于设置录音时的通道数。设置默认值1为单声道录制,设置为2意味着使用立体声录制。除非使用外设进行录制,否则应设置为1。

编码设置

  • AVEncoderAudioQualityKey

    编码质量,值为AVAudioQuality

  • AVEncoderBitRateKey

    编码比特率,值为整数

  • AVEncoderBitRatePerChannelKey

    标识每个通道的编码比特率。

注意:AVEncoderBitRateKeyAVEncoderBitRatePerChannelKey只需要设置一个

  • AVEncoderBitRateStrategyKey

    编码比特率的策略 取值为AVAudioBitRateStrategy

  • AVEncoderAudioQualityForVBRKey

    动态比特率,只和AVAudioBitRateStrategy_Variable有关 值为 AVAudioQuality

  • AVEncoderBitDepthHintKey

    编码位数(位深度)。值为8~32。这个数值越大,解析度就越高,录制和回放的声音就越真实

线性PCM音频格式设置

  • AVLinearPCMBitDepthKey

    一个NSNumber整数,指示线性PCM音频格式的位深度,值为8、16、24或32之一。

  • AVLinearPCMIsBigEndianKey

    一个布尔值,指示音频格式是大端(YES)还是小端(NO)。

  • AVLinearPCMIsFloatKey

    一个布尔值,指示音频格式是浮点(YES)还是定点(NO)。

  • AVLinearPCMIsNonInterleaved

    一个布尔值,指示音频格式是非交错(YES)还是交错(NO)。

采样率转换设置

  • AVSampleRateConverterAudioQualityKey

    音频采用率质量(录音采样质量)值为 AVAudioQuality

  • AVSampleRateConverterAlgorithmKey

    采样率转化算法, 值为 AVSampleRateConverterAlgorithm字符串

2.2 key对应的参数值

AudioFormatID音频格式,枚举类型

CF_ENUM(AudioFormatID)
{
    kAudioFormatLinearPCM               = ‘lpcm‘,
    kAudioFormatAC3                     = ‘ac-3‘,
    kAudioFormat60958AC3                = ‘cac3‘,
    kAudioFormatAppleIMA4               = ‘ima4‘,
    kAudioFormatMPEG4AAC                = ‘aac ‘,
    kAudioFormatMPEG4CELP               = ‘celp‘,
    kAudioFormatMPEG4HVXC               = ‘hvxc‘,
    kAudioFormatMPEG4TwinVQ             = ‘twvq‘,
    kAudioFormatMACE3                   = ‘MAC3‘,
    kAudioFormatMACE6                   = ‘MAC6‘,
    kAudioFormatULaw                    = ‘ulaw‘,
    kAudioFormatALaw                    = ‘alaw‘,
    kAudioFormatQDesign                 = ‘QDMC‘,
    kAudioFormatQDesign2                = ‘QDM2‘,
    kAudioFormatQUALCOMM                = ‘Qclp‘,
    kAudioFormatMPEGLayer1              = ‘.mp1‘,
    kAudioFormatMPEGLayer2              = ‘.mp2‘,
    kAudioFormatMPEGLayer3              = ‘.mp3‘,
    kAudioFormatTimeCode                = ‘time‘,
    kAudioFormatMIDIStream              = ‘midi‘,
    kAudioFormatParameterValueStream    = ‘apvs‘,
    kAudioFormatAppleLossless           = ‘alac‘,
    kAudioFormatMPEG4AAC_HE             = ‘aach‘,
    kAudioFormatMPEG4AAC_LD             = ‘aacl‘,
    kAudioFormatMPEG4AAC_ELD            = ‘aace‘,
    kAudioFormatMPEG4AAC_ELD_SBR        = ‘aacf‘,
    kAudioFormatMPEG4AAC_ELD_V2         = ‘aacg‘,
    kAudioFormatMPEG4AAC_HE_V2          = ‘aacp‘,
    kAudioFormatMPEG4AAC_Spatial        = ‘aacs‘,
    kAudioFormatMPEGD_USAC              = ‘usac‘,
    kAudioFormatAMR                     = ‘samr‘,
    kAudioFormatAMR_WB                  = ‘sawb‘,
    kAudioFormatAudible                 = ‘AUDB‘,
    kAudioFormatiLBC                    = ‘ilbc‘,
    kAudioFormatDVIIntelIMA             = 0x6D730011,
    kAudioFormatMicrosoftGSM            = 0x6D730031,
    kAudioFormatAES3                    = ‘aes3‘,
    kAudioFormatEnhancedAC3             = ‘ec-3‘,
    kAudioFormatFLAC                    = ‘flac‘,
    kAudioFormatOpus                    = ‘opus‘
};

AVAudioQuality 一个枚举属性,指定采用率转化质量

typedef NS_ENUM(NSInteger, AVAudioQuality) {
	AVAudioQualityMin    = 0,
	AVAudioQualityLow    = 0x20,
	AVAudioQualityMedium = 0x40,
	AVAudioQualityHigh   = 0x60,
	AVAudioQualityMax    = 0x7F
};

AVSampleRateConverterAlgorithm 转换算法(字符串类型)

// 使用正常的编码器比特率策略
extern NSString *const AVSampleRateConverterAlgorithm_Normal;                  

// 使用主控编码器比特率策略
extern NSString *const AVSampleRateConverterAlgorithm_Mastering;             

// 使用最小相位编码器比特率策略
extern NSString *const AVSampleRateConverterAlgorithm_MinimumPhase;    

AVAudioBitRateStrategy 比特率的策略

// 常数策略
extern NSString *const AVAudioBitRateStrategy_Constant;                                
// 长期平均值策略
extern NSString *const AVAudioBitRateStrategy_LongTermAverage;                
// 受约束的变量值策略
extern NSString *const AVAudioBitRateStrategy_VariableConstrained;  
// 变量值策略
extern NSString *const AVAudioBitRateStrategy_Variable;                                  

2.3 示例

上边的值不需要全部设置,只使用需要的就可以,例如:

NSDictionary *settings = @{
    AVSampleRateKey:[NSNumber numberWithFloat: 44100.0], // 采样率
    AVFormatIDKey:[NSNumber numberWithInt: kAudioFormatMPEG4AAC], // 音频格式
    AVNumberOfChannelsKey:[NSNumber numberWithInt: 1],  // 声道数
    AVEncoderAudioQualityKey:[NSNumber numberWithInt:AVAudioQualityMin], // 录音质量
    AVSampleRateConverterAudioQualityKey:[NSNumber numberWithInt: AVAudioQualityMin] // 录音采样质量
};

NSError *error;
_audioRecorder = [[AVAudioRecorder alloc] initWithURL:_recordURL settings:settings error:&error];

if(error) {
    NSLog(@"Ups, could not create recorder %@", error);
}

三、录音

3.1常用方法如下:

// 创建一个文件,并准备开始录制。调用record方法时,如果音频还没有准备好,程序会隐式先执行该方法。
- (BOOL)prepareToRecord;   

 // 开始或恢复录制。调用该方法时,如果音频还没有准备好,程序会隐式执行prepareToRecord方法。
- (BOOL)record;

// 在指定时间点开始或恢复录制。时间是一个绝对的时间,基于并大于设备的时间
- (BOOL)recordAtTime:(NSTimeInterval)time;  

// 录制一个指定持续时间的音频,录到指定时长后会自动停止
- (BOOL)recordForDuration:(NSTimeInterval) duration; 

// 在指定时间点开始或恢复录制,并指定录制的持续时间。
- (BOOL)recordAtTime:(NSTimeInterval)time forDuration:(NSTimeInterval) duration; 

// 暂停。
- (void)pause; 

// 停止
- (void)stop; 

// 必须先调用停止之后才能调用,调用后会删掉录制的音频文件
- (BOOL)deleteRecording;   

3.2 其他方法

获取音量(分贝)

// 是否开启分贝检测,默认是关闭的
@property(getter=isMeteringEnabled) BOOL meteringEnabled; 

// 调用更新分贝值,在调用后面两个方法前,需要先调用这个方法
- (void)updateMeters; 

// 返回给定信道的峰值功率(最大分贝)亲测,取值范围为 -160~0,但官方文档说值有可能超过0
- (float)peakPowerForChannel:(NSUInteger)channelNumber; 

// 返回给定信道的平均功率(平均分贝)
- (float)averagePowerForChannel:(NSUInteger)channelNumber; 

这里找到分贝转化的代码如下,未测试结果是否准确

[recorder updateMeters];  
//发送updateMeters消息来刷新平均和峰值功率。此计数是以对数刻度计量的,-160表示完全安静,0表示最大输入值  
float averagePower = [recorder averagePowerForChannel:0];  
float peakPower = [recorder peakPowerForChannel:0];  
//转换最高分贝值,范围是0到1。0最小,1最大。     
const double ALPHA = 0.05;        
double peakPowerForChannel = pow(10, (0.05 * peakPower));      
lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults; 

3.3 代理

/*在录制完成或停止时调用。如果recorder由于中断而停止,则不调用此方法.*/
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag;

/* 如果在编码时发生错误,将调用这个方法告诉代理*/
- (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError * __nullable)error;

// audio的interrupt打断代理不建议使用,建议使用avaudiosession的打断监听来处理。

以上是关于使用AVAudioRecorder录制音频的主要内容,如果未能解决你的问题,请参考以下文章

使用 AVAudioRecorder 录制时创建 2 秒音频文件

从 AVAudioRecorder 录制的音频中去除静音

iPhone AVAudioRecorder,AudioQueueServices,检测到声音时如何自动录制音频

在使用 AVAudioRecorder 在为导航栏设置动画的同时录制音频时发生中断时,我们如何停止并保存录制?

使用 AVAudioRecorder 录制文件,录制后无法获取文件路径

如何增加使用AVAudioRecorder录制的声音音量