iOS-音频-AVAudioSession

1. AVAudioSession 概述

最近一年一直在作IPC Camera的iOS客户端开发。和音频打交道,必需要弄清楚 AVAudioSession。 先看下苹果的官方图: html

Audio Session

能够看到AVAudioSession就是用来管理多个APP对音频硬件设备(麦克风,扬声器)的资源使用。ios

举例一下AVAudioSession能够作这些事情bash

  • 设置本身的APP是否和其余APP音频同时存在,仍是中断其余APP声音
  • 在手机调到静音模式下,本身的APP音频是否能够播放出声音
  • 电话或者其余APP中断本身APP的音频的事件处理
  • 指定音频输入和输出的设备(好比是听筒输出声音,仍是扬声器输出声音)
  • 是否支持录音,录音同时是否支持音频播放

2. AVAudioSession Category

AVAudioSession的接口比较简单。APP启动的时候会自动帮激活AVAudioSession,固然咱们能够手动激活代码以下。session

//导入头文件
    #import <AVFoundation/AVFoundation.h>

    //AVAudioSession是一个单例类
    AVAudioSession *session = [AVAudioSession sharedInstance];
    //AVAudioSessionCategorySoloAmbient是系统默认的category
    [session setCategory:AVAudioSessionCategorySoloAmbient error:nil];
    //激活AVAudioSession
    [session setActive:YES error:nil];
复制代码

能够看到设置session这里有两个参数,category和options Category iOS下目前有七种,每种Category都对应是否支持下面四种能力app

  • Interrupts non-mixable apps audio:是否打断不支持混音播放的APP
  • Silenced by the Silent switch:是否会响应手机静音键开关
  • Supports audio input:是否支持音频录制
  • Supports audio output:是否支持音频播放

下面用图表来直观的看下每种category具体的能力集ide

Category 是否容许音频播放/录音 是否打断其余不支持混音APP 是否会被静音键或锁屏键静音
AVAudioSessionCategoryAmbient 只支持播放
AVAudioSessionCategoryAudioProcessing 不支持播放,不支持录制
AVAudioSessionCategoryMultiRoute 支持播放,支持录制
AVAudioSessionCategoryPlayAndRecord 支持播放,支持录制 默认YES,能够重写为NO
AVAudioSessionCategoryPlayback 只支持播放 默认YES,能够重写为NO
AVAudioSessionCategoryRecord 只支持录制 否(锁屏下仍可录制)
AVAudioSessionCategorySoloAmbient 只支持播放
  • AVAudioSessionCategoryAmbient,只支持音频播放。这个 Category,音频会被静音键和锁屏键静音。而且不会打断其余应用的音频播放。ui

  • AVAudioSessionCategorySoloAmbient,这个是系统默认使用的 Category,只支持音频播放。音频会被静音键和锁屏键静音。和AVAudioSessionCategoryAmbient不一样的是,这个会打断其余应用的音频播放spa

  • AVAudioSessionCategoryPlayback,只支持音频播放。你的音频不会被静音键和锁屏键静音。适用于音频是主要功能的APP,像网易云这些音乐app,锁屏后依然能够播放。code

须要注意一下,选择支持在静音键切到静音状态以及锁屏键切到锁屏状态下仍然能够播放音频 Category 时,必须在应用中开启支持后台音频功能,详见 UIBackgroundModescdn

  • AVAudioSessionCategoryRecord,只支持音频录制。不支持播放。
  • AVAudioSessionCategoryPlayAndRecord,支持音频播放和录制。音频的输入和输出不须要同步进行,也能够同步进行。须要音频通话类应用,可使用这个 Category。
  • AVAudioSessionCategoryAudioProcessing,只支持本地音频编解码处理。不支持播放和录制。
  • AVAudioSessionCategoryMultiRoute,支持音频播放和录制。容许多条音频流的同步输入和输出。(好比USB链接外部扬声器输出音频,蓝牙耳机同时播放另外一路音频这种特殊需求)

咱们也能够经过AVAudioSession的属性来读取当前设备支持的Category

@property(readonly) NSArray<NSString *> *availableCategories;
复制代码

这样能够保证设备兼容性。

设置Category的代码示例以下

NSError *setCategoryError = nil;
BOOL isSuccess = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&setCategoryError];
if (!success) { 
    //这里能够读取setCategoryError.localizedDescription查看错误缘由
}
复制代码

3. AVAudioSession Mode&&Options

刚刚介绍的Category定义了七种主场景,实际开发需求中有时候须要对Category进行微调整,咱们发现这个接口还有两个参数Mode和Options。

/* set session category and mode with options */
- (BOOL)setCategory:(NSString *)category mode:(NSString *)mode options:(AVAudioSessionCategoryOptions)options error:(NSError **)outError API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0));
复制代码

AVAudioSession Mode

咱们经过读取下面这条属性获取当前设备支持的Mode

@property(readonly) NSArray<NSString *> *availableModes;
复制代码

iOS下有七种mode来定制咱们的Category行为

模式 兼容的 Category 场景
AVAudioSessionModeDefault All 默认模式
AVAudioSessionModeVoiceChat AVAudioSessionCategoryPlayAndRecord VoIP
AVAudioSessionModeGameChat AVAudioSessionCategoryPlayAndRecord 游戏录制,GKVoiceChat自动设置
AVAudioSessionModeVideoRecording AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord 录制视频
AVAudioSessionModeMoviePlayback AVAudioSessionCategoryPlayback 视频播放
AVAudioSessionModeMeasurement AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayback 最小系统
AVAudioSessionModeVideoChat AVAudioSessionCategoryPlayAndRecord 视频通话

下面逐一介绍下每一个Mode

  • AVAudioSessionModeDefault,默认模式,与全部的 Category 兼容

  • AVAudioSessionModeVoiceChat,适用于VoIP 类型的应用。只能是 AVAudioSessionCategoryPlayAndRecord Category下。在这个模式系统会自动配置AVAudioSessionCategoryOptionAllowBluetooth 这个选项。系统会自动选择最佳的内置麦克风组合支持语音聊天。

  • AVAudioSessionModeVideoChat,用于视频聊天类型应用,只能是 AVAudioSessionCategoryPlayAndRecord Category下。适在这个模式系统会自动配置 AVAudioSessionCategoryOptionAllowBluetooth 和 AVAudioSessionCategoryOptionDefaultToSpeaker 选项。系统会自动选择最佳的内置麦克风组合支持视频聊天。

  • AVAudioSessionModeGameChat,适用于游戏类应用。使用 GKVoiceChat 对象的应用会自动设置这个模式和 AVAudioSessionCategoryPlayAndRecord Category。实际参数和AVAudioSessionModeVideoChat一致

  • AVAudioSessionModeVideoRecording,适用于使用摄像头采集视频的应用。只能是 AVAudioSessionCategoryPlayAndRecord 和 AVAudioSessionCategoryRecord 这两个 Category下。这个模式搭配 AVCaptureSession API 结合来用能够更好地控制音视频的输入输出路径。(例如,设置 automaticallyConfiguresApplicationAudioSession 属性,系统会自动选择最佳输出路径。

  • AVAudioSessionModeMeasurement,最小化系统。只用于 AVAudioSessionCategoryPlayAndRecord、AVAudioSessionCategoryRecord、AVAudioSessionCategoryPlayback 这几种 Category。

  • AVAudioSessionModeMoviePlayback,适用于播放视频的应用。只用于 AVAudioSessionCategoryPlayback 这个Category。

AVAudioSession Options

咱们还可使用options去微调Category行为,以下表

Option Option功能说明 兼容的 Category
AVAudioSessionCategoryOptionMixWithOthers 支持和其余APP音频 mix AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryPlayback AVAudioSessionCategoryMultiRoute
AVAudioSessionCategoryOptionDuckOthers 系统智能调低其余APP音频音量 AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryPlayback AVAudioSessionCategoryMultiRoute
AVAudioSessionCategoryOptionAllowBluetooth 支持蓝牙音频输入 AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayAndRecord
AVAudioSessionCategoryOptionDefaultToSpeaker 设置默认输出音频到扬声器 AVAudioSessionCategoryPlayAndRecord

调优咱们的Category

经过Category和合适的Mode和Options的搭配咱们能够调优出咱们的效果,下面举两个应用场景:

用太高德地图的都知道,在后台播放QQ音乐的时候,若是导航语音出来,QQ音乐不会中止,而是被智能压低和混音,等导航语音播报完后,QQ音乐正常播放,这里咱们须要后台播放音乐,因此Category使用AVAudioSessionCategoryPlayback,须要混音和智能压低其余APP音量,因此Options选用 AVAudioSessionCategoryOptionMixWithOthers和AVAudioSessionCategoryOptionDuckOthers

代码示例以下

BOOL isSuccess = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers | AVAudioSessionCategoryOptionDuckOthers error:&setCategoryError];
复制代码

又或者我但愿AVAudioSessionCategoryPlayAndRecord这个Category默认的音频由扬声器播放,那么能够调用这个接口去调整Category

- (BOOL)setCategory:(NSString *)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError
复制代码

经过选择合适和Category,mode和options,就能够调优音频的输入输出,来知足平常开发需求(须要注意的是Category,mode,option是搭配使用的,而不是简单组合,也就是说某种Category支持某些mode和option,从上面的表中也能够看出这一点)

4. 音频中断处理

其余APP或者电话会中断咱们的APP音频,因此相应的咱们要作出处理。 咱们能够经过监听AVAudioSessionInterruptionNotification这个key获取音频中断事件

回调回来Userinfo有键值

  • AVAudioSessionInterruptionTypeKey: 取值AVAudioSessionInterruptionTypeBegan表示中断开始 取值AVAudioSessionInterruptionTypeEnded表示中断结束

中断开始:咱们须要作的是保存好播放状态,上下文,更新用户界面等 中断结束:咱们要作的是恢复好状态和上下文,更新用户界面,根据需求准备好以后选择是否激活咱们session。

选择不一样的音频播放技术,处理中断方式也有差异,具体以下:

  • System Sound Services:使用 System Sound Services 播发音频,系统会自动处理,不受APP控制,当中断发生时,音频播放会静音,当中断结束后,音频播放会恢复。

  • AV Foundation framework:AVAudioPlayer 类和 AVAudioRecorder 类提供了中断开始和结束的 Delegate 回调方法来处理中断。中断发生,系统会自动中止播放,须要作的是记录播放时间等状态,更新用户界面,等中断结束后,再次调用播放方法,系统会自动激活session。

  • Audio Queue Services, I/O audio unit:使用aduio unit这些技术须要处理中断,须要作的是记录播放或者录制的位置,中断结束后本身恢复audio session。

  • OpenAL:使用 OpenAL 播放时,一样须要本身监听中断。管理 OpenAL上下文,用户中断结束后恢复audio session。

须要注意的是:1. 有中断开始事件,不必定对应有中断结束事件,因此须要在用户进入前台,点击UI操做的时候,须要保存好播放状态和对Audio Session管理,以便不影响APP的音频功能。2.音频资源竞争上,必定是电话优先。3. AVAudioSession一样能够监听外设音频状态,好比耳机拔入拔出。这里不作累述

5. AVAudioSession总结

AVAudioSession的做用就是管理音频这一惟一硬件资源的分配,经过调优合适的AVAudioSession来适配咱们的APP对于音频的功能需求。切换音频场景时候,须要相应的切换AVAudioSession。

参考文献:Audio Session Programming Guide

相关文章
相关标签/搜索