iOS音频录制

音频会话(Audio Session)

音频会话是应用程序和操作系统之间的中间人。应用程序不需要具体知道怎样和音频硬件交互的细节,只需要把所需的音频行为委托给音频会话管理即可。

  • 音频会话分类(Audio Session Category)
    AV Foundation把音频行为分成了七类。各个分类有着不同的作用,因此各个分类用在不同的功能场景。
音频分类_1.jpg

以上七个分类能够满足大部分的需求,但是开发者也可以通过使用选项(options)和模式(modes)自定义,增强和修改原有的分类功能。

配置音频会话

AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *error = nil;
// 音频会话分类(catehory)和模式(mode)一起决定了应用要使用音频的方式,也可以说是定制音频的行为。通常在激活音频会话之前设置分类和模式。也可以在激活音频会话时设置分类和模式,但是这样会立即路由(route)。
 // 如果分类设置成功,但会也是,反则返回no
if([audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&error]){
      // 配置成功
 }else{
      // 配置失败
  }

音频录制

AV Foundation提供了AVAudioRecorder类,用于从内置麦克风或者外置音频设备录制音频。

创建AVAudioRecorder需要提供以下数据信息:

  • 录制的音频要存放的位置,也就是本地URL。
  • 音频格式、采样率、声道等配置信息,这些信息使用字典保存。
  • NSError指针,用于捕捉初始化时可能出现的错误。

创建和准备AudioRecorder对象:

+(instancetype)audioRecordertoPrepare:(NSString *)audioName error:(NSError *)error{
    NSString *audioDirectory =  ;
    if(audioDirectory){
        NSString *audioPath = ;
        NSDictionary *audioSettings = @{AVFormatIDKey:@(kAudioFormatMPEG4AAC),
                                       AVSampleRateKey:@22050.0f,
                                       AVNumberOfChannelsKey:@1
                                       };
        AVAudioRecorder *audioRecorder = [[AVAudioRecorder alloc] initWithURL:audioURL settings:audioSettings error:&error];
        // prepareToRecord方法根据URL创建文件,并且执行底层Audio Queue初始化的必要过程,将录制启动时的延迟降到最低。
        if([audioRecorder prepareToRecord]){
            return audioRecorder;
        }
    }
    return nil;
}
  1. 音频格式
    kAudioFormatMPEG4AAC压缩格式能在显著减小文件的同时,保证音频的质量。同时Android也支持aac音频格式。
  2. 采样率
    采样率越高,文件越大,质量越好,反之,文件小,质量相对差一些,但是低于普通的音频,人耳并不能明显的分辨出好坏。最终选取哪一种采样率,由我们的耳朵来判断。建议使用标准的采样率,8000、16000、22050、44100。
  3. 通道数
    AVNumberOfChannelsKey用于指定记录音频的通道数。1为单声道,2为立体声。除非使用外部硬件进行录制,否则通常使用单声道录制。
  4. 其他配置
    在AV Foundation Audio Session Settings Constants中查看完整的键列表。

音频录制控制

  • 启动、恢复音频录制

[AVAudioRecorder record];
```

  • 暂停音频录制
    [AVAudioRecorder pause];
    
  • 结束录制
[AVAudioRecorder stop];
  • 删除录制的音频文件,删除之前必须先停止录制
    [self.audioRecorder deleteRecording];

录制和删除录制文件方法返回布尔值,如果操作成功,返回YES,操作失败返回NO,所以在实际的开发中,还应该考虑操作失败状态的处理,给用户以友好的提示。

同时AVAudioRecorder也提供了AVAdudioRecorderDelegate协议,用于接收音频录制完成、音频录制过程发生错误的事件。虽然也有定义音频录制过程被中断的方法,但是已经弃用。所以要监听诸如系统来电,闹钟响铃,Facetime……导致的音频录制终端事件,使用AVAudioSession通知代替。

AVAudioDelegate定义的接口:

@optional 

/* 录制完成或者调用stop时,回调用这个方法。但是如果是系统中断录音,则不会调用这个方法。 */
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag;

/* 在录制时出现错误时调用这个代理方法 */
- (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError * __nullable)error;

#if TARGET_OS_IPHONE

/* AVAudioRecorder INTERRUPTION NOTIFICATIONS 已废弃 - 使用 AVAudioSession 替代. */

/* audioRecorderBeginInterruption: is called when the audio session has been interrupted while the recorder was recording. The recorded file will be closed. */
- (void)audioRecorderBeginInterruption:(AVAudioRecorder *)recorder NS_DEPRECATED_IOS(2_2, 8_0);

/* audioRecorderEndInterruption:withOptions: is called when the audio session interruption has ended and this recorder had been interrupted while recording. */
/* Currently the only flag is AVAudioSessionInterruptionFlags_ShouldResume. */
- (void)audioRecorderEndInterruption:(AVAudioRecorder *)recorder withOptions:(NSUInteger)flags NS_DEPRECATED_IOS(6_0, 8_0);

- (void)audioRecorderEndInterruption:(AVAudioRecorder *)recorder withFlags:(NSUInteger)flags NS_DEPRECATED_IOS(4_0, 6_0);

/* audioRecorderEndInterruption: is called when the preferred method, audioRecorderEndInterruption:withFlags:, is not implemented. */
- (void)audioRecorderEndInterruption:(AVAudioRecorder *)recorder NS_DEPRECATED_IOS(2_2, 6_0);

AVAudioSession通知

/** 注册音频录制中断通知 */
 NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
                    [notificationCenter addObserver:self selector:@selector(handleNotification:) name:AVAudioSessionInterruptionNotification object:nil];

// 接收录制中断事件通知,并处理相关事件
-(void)handleNotification:(NSNotification *)notification{
    NSArray *allKeys = notification.userInfo.allKeys;
    // 判断事件类型
    if([allKeys containsObject:AVAudioSessionInterruptionTypeKey]){
        AVAudioSessionInterruptionType audioInterruptionType = [[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] integerValue];
        switch (audioInterruptionType) {
            case AVAudioSessionInterruptionTypeBegan:
                self.statusLabel.text = @"录音被打断…… 开始";
                break;
            case AVAudioSessionInterruptionTypeEnded:
                self.statusLabel.text = @"录音被打断…… 结束";
                break;
        }
    }
    // 判断中断的音频录制是否可恢复录制
    if([allKeys containsObject:AVAudioSessionInterruptionOptionKey]){
        AVAudioSessionInterruptionOptions shouldResume = [[notification.userInfo valueForKey:AVAudioSessionInterruptionOptionKey] integerValue];
        if(shouldResume){
            self.statusLabel.text = @"录音被打断…… 结束 可以恢复录音了";
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容