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 = @"錄音被打斷…… 結束 可以恢復錄音了";
        }
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容