使用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
标识每个通道的编码比特率。
注意:
AVEncoderBitRateKey
和AVEncoderBitRatePerChannelKey
只需要设置一个
-
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的打断监听来处理。