(一)AVFoundation 之 AVAudioSession 学习笔记

本文详细介绍了AVAudioSession的使用,包括如何管理音频资源、设置Category、Mode和Options以优化音频体验,处理音频中断,以及音频路由的选择。通过具体案例展示了如何在不同场景下调整音频设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、 AVAudioSession 概述

先看苹果官方图

从上图可以看出AVAudioSession 就是用来管理多个App 对音频硬件设备(麦克风、扬声器)的资源的使用.

举例一下AVAudioSession可以做的事情

  • 设置自己的App是否和其他的App音频同时存在,还是中断其他的app声音.
  • 在手机调到静音模式下,自己的App音频是否可以播放出声音.
  • 电话或者其他App中断自己的App的音频的事件处理.
  • 指定音频输入和输出的设备(比如是听筒输出声音,还是扬声器输出声音)
  • 是否支持录音,录音同时是否支持音频播放.


二、AVAudioSession Category

AVAudioSession 的接口比较简单,在App启动的时候会自动帮助激活AVAudioSession, 我们也可以手动激活并做一些偏好设置,代码如下:

/**
 激活AVAudioSession
 */
-(void)activeAVAudioSession{
    // AVAudioSession 是一个单例
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    
//    AVAudioSessionCategorySoloAmbient 是系统默认的category
    [audioSession setCategory:AVAudioSessionCategorySoloAmbient error:nil];
    // 激活AVAudioSession
    [audioSession setActive:YES error:nil];
}

//    你可以先通过 这个属性来查看当前设备支持的Category 这样可以保证设备的兼容性
//    NSArray *categorys = [[AVAudioSession sharedInstance] availableCategories];
//    NSLog(@"categorys : %@",categorys);

** AVAudioSessionCategory 就是用来告诉 iOS我们将会采用怎样的方式在系统中使用音频信号, 目前有7种,具体含义如下:**

//1
//此类别适合于“玩”风格的应用程序,例如用户在iPod音频上播放的虚拟钢琴。
//当您使用此类别时,来自其他应用程序的音频与音频混合。
//屏幕锁定和静音开关会打断(关闭)当前音频
AVF_EXPORT NSString *const AVAudioSessionCategoryAmbient;

//2 
//当您使用此类别时,来自其他应用程序的音频会被打断(关闭)。
//屏幕锁定和静音开关会打断(关闭)当前音频
AVF_EXPORT NSString *const AVAudioSessionCategorySoloAmbient;

//3
// 当使用该类别时应用程序音频不会因为静音键开关或锁幕而打断。
// 这个类别的设计就是为了防止其他app的音频与当前的app的音频发生混合
AVF_EXPORT NSString *const AVAudioSessionCategoryPlayback;

//4
// 当开始录音时就其它的音频会停止播放音频,当锁屏时会继续录音
AVF_EXPORT NSString *const AVAudioSessionCategoryRecord;

//5
//此类别不会因为锁屏和静音键而中断。
//这个类别适用于同时播放和录音,也适用于录音和回放。
// 如果希望确保应用程序正在录制时不播放诸如Messages警报之类的声音,请使用AVAudioSessionCategoryRecord类别。
AVF_EXPORT NSString *const AVAudioSessionCategoryPlayAndRecord;

//6 
// 这个类别会停止掉其它正在播放的音频和正在录制的音频
// 当程序退到后台时正在处理的音频会被停止掉,你需要申请额外的后台处理时间
AVF_EXPORT NSString *const AVAudioSessionCategoryAudioProcessing

//7
//支持音频播放和录制。允许多条音频流的同步输入和输出。
//(比如USB连接外部扬声器输出音频,蓝牙耳机同时播放另一路音频这种特殊需求)
AVF_EXPORT NSString *const AVAudioSessionCategoryMultiRoute


三、AVAudioSession Mode&&Options

我们可以在激活AVAudioSession 时,指定Category是为了告诉系统我们将会以怎样的方式使用音频信息(即我们音频的应用场景是什么),但实际开发过程中只设置Category 可能还不足以瞒住我们的需求,这时我们就可以通过设置AVAudioSession 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));

在iOS 中主要有一下几种 AVAudioSession Mode

//1
// 默认就是这种mode,
//兼容所有的Category 
// 在具有多于一个内置麦克风的设备上,使用主麦克风。
AVF_EXPORT NSString *const AVAudioSessionModeDefault NS_AVAILABLE_IOS(5_0);

//2
//主要适用于VoIP 类型的应用(网络电话)
//当使用该模式时设备的音调均衡被优化为语音。
// 注意1: 这种模式需要设置category为 AVAudioSessionCategoryPlayAndRecord 
//注意2:在这个模式系统会自动配置AVAudioSessionCategoryOptionAllowBluetooth 这个选项
AVF_EXPORT NSString *const AVAudioSessionModeVoiceChat NS_AVAILABLE_IOS(5_0);


//3
//用于视频聊天类型应用
//只能兼容 AVAudioSessionCategoryPlayAndRecord 。
//系统会自动配置 AVAudioSessionCategoryOptionAllowBluetooth 和 
//AVAudioSessionCategoryOptionDefaultToSpeaker 选项。
AVF_EXPORT NSString *const AVAudioSessionModeVideoChat NS_AVAILABLE_IOS(7_0);


//4
//适用于游戏类应用。
//实际参数和AVAudioSessionModeVideoChat一致
AVF_EXPORT NSString *const AVAudioSessionModeGameChat NS_AVAILABLE_IOS(5_0);


//5
// 用于使用摄像头采集视频的应用。
//只能兼容 AVAudioSessionCategoryPlayAndRecord 和 AVAudioSessionCategoryRecord
AVF_EXPORT NSString *const AVAudioSessionModeVideoRecording NS_AVAILABLE_IOS(5_0);

//6
//最小化系统
//只能兼容 AVAudioSessionCategoryPlayAndRecord、AVAudioSessionCategoryRecord
AVF_EXPORT NSString *const AVAudioSessionModeMeasurement NS_AVAILABLE_IOS(5_0);

//7
//适用于播放视频的应用。
//只能兼容AVAudioSessionCategoryPlayback 。
AVF_EXPORT NSString *const AVAudioSessionModeMoviePlayback NS_AVAILABLE_IOS(6_0);

我们还可以使用AVAudioSessionOptions 来微调Category的行为,具体的如下:

//1
// 支持和其它App音频的混合
// 兼容的Category有:
// AVAudioSessionCategoryPlayAndRecord 
// AVAudioSessionCategoryPlayback
// AVAudioSessionCategoryMultiRoute
AVAudioSessionCategoryOptionMixWithOthers


//2
//系统智能调低其他APP音频音量
// 兼容的Category 有
//AVAudioSessionCategoryPlayAndRecord 
//AVAudioSessionCategoryPlayback //AVAudioSessionCategoryMultiRoute
AVAudioSessionCategoryOptionDuckOthers

//3
//允许iOS通过蓝牙音频设备来播放我们App的声音。
// 兼容的Category 有 
//AVAudioSessionCategoryRecord 
//AVAudioSessionCategoryPlayAndRecord
AVAudioSessionCategoryOptionAllowBluetooth

//4
//设置默认输出音频到扬声器
// 兼容的Category 有 
//AVAudioSessionCategoryPlayAndRecord
AVAudioSessionCategoryOptionDefaultToSpeaker


四、调优我们的Category

通过给AVAudioSession 设置Category ** 属性,我们告诉系统音频信号将要应用的场景是什么.比如: 当前App音频是否和其它App音频混合, 是否打断其它App的音频,静音或退到后台音频是否被打断, 以及我们是用来播放的还是用来录制的或者播放和录制混合等等,这些只是个大的方向.我们还可以设置AVAudioSessionMode** 来进一步限制我们的应用场景,比如:我们主要应用场景是网络电话,是语音聊天,是游戏类型吗,还是一般的通用应用场景等等,甚至我们还可以通过设置AVAudioSessionOptions参数告诉系统更详细的应用场景,比如: 是否支持蓝牙输出, 是否默认扬声器输出,是否在播放时降低其他音频的声音,是否允许和其他音频混合等等.

通过Category和合适的Mode和Options的搭配我们可以调优出我们的效果,下面举两个应用场景:

  • 用过高德地图的都知道,在后台播放QQ音乐的时候,如果导航语音出来,QQ音乐不会停止,而是被智能压低和混音,等导航语音播报完后,QQ音乐正常播放
    (1)这里我们需要后台播放音乐,所以Category使用AVAudioSessionCategoryPlayback
    (2)需要混音和智能压低其他APP音量,所以Options选用 AVAudioSessionCategoryOptionMixWithOthers和AVAudioSessionCategoryOptionDuckOthers**

代码示例如下:

    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    NSError *err = nil;
    [audioSession setCategory:AVAudioSessionCategoryPlayback
                  withOptions:AVAudioSessionCategoryOptionMixWithOthers |
                              AVAudioSessionCategoryOptionDuckOthers
                        error:&err];

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



五、音频中断处理
  • AVAudioSessionInterruptionTypeKey:

    其他App 或电话会中断我们的App 音频,所以相应的我们要做出对应的处理.
    我们可以通过监听 AVAudioSessionInterruptionNotification 获取中断事件.

    回调回来的UserInfo 有键值:
    AVAudioSessionInterruptionTypeBegan表示中断开始
    AVAudioSessionInterruptionTypeEnded表示中断结束

    中断开始: 我们需要做的是保存好播放状态, 上下文, 更新用户的界面
    中断结束: 我们要做的是恢复好状态和上下文,更新用户界面, 根据需求准备好之后选择是否激活我们的Session

选择不同的音频播放技术,处理中断的方式也有差别,具体如下:

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

  • AVFoundation Framework: AVAudioPlayer 类和 AVAudioRecorder 类提供了中断开始和结束的Delegate 回调方法来处理中断.
    (1) 中断发生, 系统会自动停止播放,需要做的是记录播放时间等状态,更新用户界面
    (2)中断结束后,再次调用播放方法,系统会自动激活session.

  • OpenAL : 使用OpenAL 播放时,同样需要自己监听中断.管理OpenAL上下文,中户中断结束后恢复audio session

需要注意的是:
1.有中断开始事件,但不一定有对应的中断结束事件,所以需要在用户进入前台,点击UI操作时,需要保存好播放状态和对应的Audio Session管理,以便不影响App 的音频功能.
2. 音频资源的竞争上,一定是电话优先.
3. AVAudionSession同样可以监听外设音频状态,比如耳机拔出和插入状态.



六、Audio Route (音频路由的选择)

当你的iphone 接有多个外接音频设备时(耳机, 蓝牙耳机等), AudioSession 遵循 last-in wins 的原则来选择外接设备.即 声音将会被导入最后接入的设备.

当没有介接入任何音频设备时, 一般情况下声音会默认从扬声器出来,但有一个例外的情况在playAndRecord这个Category下,听筒会成为默认的输出设备 如果你想要改变这个行为,你可以提供MPVolumeView来让用户切换到扬声器,也可以通过 overrideOutputAudioPort 方法来programmingly 切换到扬声器,也可以修改categoryOption为AVAudioSessionCategoryOptionDefaultToSpeaker

  • playAndRecord 下切换到扬声器
    除了让用户手动切换,你也可以通过以下2种方式在程序里面切换
    (1) 修改AVAudioSession 的category 方式

    [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord 
    		  withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker 
    				error:&error];
    

    (2)OverrideOutputAudioPort:

    [audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker
     								error:&error];
    

    关于这两种方式切换扬声器的方法的说明:
    (1) 使用AVAudioSessionPortOverride 方式要更为快捷一些
    (2) 使用这2中方式切换扬声器的前提是 category 被设置为AVAudioSessionCategoryPlayAndRecord
    (3) 上面2种方式只是临时的切换,任何路由改变或中断将导致音频被路由回其正常路径,遵循last-in wins 的规则。

    具体解释可以参看苹果的这篇文章



七、 总结

AVAudioSession 的作用就是管理音频这一唯一的的硬件资源分配,通过调优合适的AVAudioSession来适配我们的App对音频功能需求.切换音频场景时,需要相应的切换AVAudioSession

参考文章1 iOS 音频-AVAudioSession
参考文章2 (AudioSession详解 Category选择)
参考文章3《AV Foundation 开发秘籍》 也不错
参考文章4 苹果官方文档
参考文章5 AVAudioSession bluetooth

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值