高能音视频iOS进阶

IOS你不知道的音频细节,音频会话AVAudioSession

2018-07-19  本文已影响590人  幻水_HS

名称

音频会话

解释

设置程序的音频环境,告知系统的音频行为用途。管理多个app对音频硬件的资源分配。通过主场景、模式、细节选项的设置可以使app在音频方面更加人性化。

疑问

有人说,我写音乐播放的时候没有考虑这个都能播放,这个有啥用?当你想要做的更人性化时就该考虑下这点,比如说插耳机、拔耳机的逻辑,是否控制后台播放,是否让当前app的声音高于其他app的声音等。

理论

音频会话场景分类设置:

说明:以下分类并不是一个应用只能使用一个分类,可以根据场景来切换不同的分类。

1、主场景分类;

主场景Category 描述 可与其他app共享混合播放 是否可播放 是否可录音 静音按钮或者锁屏按钮点击后是否会停止静音 是否可在后台运行
AVAudioSessionCategoryAmbient 背景声音,可以与其他音乐混合,用于以非语音为主的应用 可混合 可播放 不可录音 会静音 不可运行
AVAudioSessionCategorySoloAmbient 默认分类,背景声音 不可混合 可播放 不可录音 会静音 不可运行
AVAudioSessionCategoryPlayback 用于播放音乐,用于以语音为主的应用 不可混合 可播放 不可录音 不会静音 可运行(另说明)
AVAudioSessionCategoryRecord 用于录音,除了来电铃声、闹钟、日历提醒等系统声音外其他声音都不会被播放,只执行录音 不可混合 不可播放 可录音 不会静音(锁屏仍可录制) 可运行
AVAudioSessionCategoryPlayAndRecord 用于播放和录音同时存在时,只有它允许修改默许音频播放设备:听筒还是外放,在该Category下声音的默认出口为听筒或者耳机。 默认不引起 可播放 可录音 不会静音 可运行
AVAudioSessionCategoryMultiRoute 多种输入输出,例如可以耳机、USB设备同时播放 不可混合 可播放 可录音 不会静音 可运行
AVAudioSessionCategoryAudioProcessing 硬件解码音频 不支持 不可播放 不可录音 不会静音 不可运行,可请求更多时间完成处理

说明:当使用AVAudioSessionCategoryPlayback分类时,要想实现后台播放,需要在Info.plist文件里添加Required background modes的数组,在下面添加名为App plays audio or streams audio/video using AirPlay的字符串

2、主场景细节options设置;

选项 兼容的场景 用途 描述
AVAudioSessionCategoryOptionMixWithOthers AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryPlayback AVAudioSessionCategoryMultiRoute 支持和其他APP音频混合
AVAudioSessionCategoryOptionDuckOthers AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryPlayback AVAudioSessionCategoryMultiRoute 导航地图 系统智能调低其他APP音频音量,突出本app的音量
AVAudioSessionCategoryOptionAllowBluetooth AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayAndRecord 支持蓝牙音频输入
AVAudioSessionCategoryOptionDefaultToSpeaker AVAudioSessionCategoryPlayAndRecord 设置默认输出音频到扬声器,即免提
AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers AVAudioSessionCategoryPlayback AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryMultiRoute app偶尔的使用音频播放
AVAudioSessionCategoryOptionAllowBluetoothA2DP AVAudioSessionCategoryPlayAndRecord 立体声蓝牙
AVAudioSessionCategoryOptionAllowAirPlay AVAudioSessionCategoryPlayAndRecord 远程AirPlay设备

3、主场景模式modes设置;

模式 兼容的场景 用途 描述
AVAudioSessionModeDefault 所有场景 默认模式 通用
AVAudioSessionModeVoiceChat AVAudioSessionCategoryPlayAndRecord Voice over IP语音应用 系统会选择最佳的输入设备,比如插上耳机就使用耳机上的麦克风进行采集
AVAudioSessionModeGameChat AVAudioSessionCategoryPlayAndRecord 游戏录制 适用于游戏App的采集和播放
AVAudioSessionModeVideoRecording AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord 录制视频时
AVAudioSessionModeMeasurement AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayback 最小化系统
AVAudioSessionModeMoviePlayback AVAudioSessionCategoryPlayback 视频播放 系统也会选择最佳的输入设备,比如插上耳机就使用耳机上的麦克风进行采集
AVAudioSessionModeVideoChat AVAudioSessionCategoryPlayAndRecord 视频通话
AVAudioSessionModeSpokenAudio AVAudioSessionCategoryPlayback AVAudioSessionCategorySoloAmbient AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryMultiRoute 有声读物 播放语音并暂停其他语音app

处理中断事件

1.当收到中断通知后,userInfo传值的字典包含AVAudioSessionInterruptionTypeKey类型值,

2.当这个类型等于 AVAudioSessionInterruptionTypeBegan时,表示开始中断。

3.当这个类型等于 AVAudioSessionInterruptionTypeEnded时,表示中断结束userInfo字典会传回一个 AVAudioSessionInterruptionOptionKey 值,当这个值等于AVAudioSessionInterruptionOptionShouldResume时,表明音频会话是否已经重新激活,以及是否可以再次播放。

线路改变事件

1.当收到线路变换通知后,userInfo传值的字典包含AVAudioSessionRouteChangeReasonKey值。

2.当这个值等于AVAudioSessionRouteChangeReasonOldDeviceUnavailable时,表示有设备断开。根据人性化原则,在耳机拔出时应该使正在播放的声音暂停。

3.当这个值等于AVAudioSessionRouteChangeReasonNewDeviceAvailable时,表示有设备连接。

核心代码

import <AVFoundation/AVFoundation.h>

该代码应写在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {这个方法里

 //设置音频会话
    AVAudioSession * session = [AVAudioSession sharedInstance];
    NSError * error;
    //设置会话的场景、选项、模式
    if( ![session setCategory:AVAudioSessionCategoryPlayback error:&error])
    {
        NSLog(@"音频会话分类设置出错:%@",[error localizedDescription]);
    }
    
    //激活会话
    if(![session setActive:YES error:&error])
    {
        NSLog(@"音频会话分类设置出错:%@",[error localizedDescription]);
    }
/**
 接收中断通知
 */
-(void)notification_Interrupt:(NSNotification *)sender
{
    NSDictionary * dic_info = sender.userInfo;
    
    AVAudioSessionInterruptionType type = [dic_info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
    if(type == AVAudioSessionInterruptionTypeBegan)
    {
        //表示中断开始
        //TODO.. 处理中断后的操作,系统会自动停止音频,在这里可以实现工作:保存播放状态,更改UI状态为暂停状态等。
    }
    else if(type == AVAudioSessionInterruptionTypeEnded)
    {
        //表示中断结束
        AVAudioSessionInterruptionOptions options = [dic_info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
        if(options == AVAudioSessionInterruptionOptionShouldResume)
        {
            //表示可以继续播放
            //TODO...系统不回自动恢复播放,在这里可以实现工作:自动播放,更改UI状态为播放状态。
        }
    }
    
}

/**
 接收线路变换通知

 @param sender <#sender description#>
 */
-(void)notification_routeChange:(NSNotification *)sender
{
    NSDictionary * dic_info = sender.userInfo;
    
    AVAudioSessionRouteChangeReason reason = [dic_info[AVAudioSessionRouteChangeReasonKey] unsignedIntegerValue];
    if(reason == AVAudioSessionRouteChangeReasonNewDeviceAvailable)
    {
        //表示有新设备接入
        //TODO...
    }
    else if(reason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable)
    {
        //表示有设备拔出
        
        //拔出之前的线路信息
        AVAudioSessionRouteDescription * previousRoute =  dic_info[AVAudioSessionRouteChangePreviousRouteKey];
        //拔出之前的输出线路
        AVAudioSessionPortDescription * previousOutput = previousRoute.outputs[0];
        NSString * portType = previousOutput.portType;//端口类型
        
        if([portType isEqualToString:AVAudioSessionPortHeadphones])
        {
            //表示是耳机设备拔出,根据人性化根据,耳机拔出后,正在播放的声音应停止播放
            //TODO..
        }
    }
}

QQ :384302147

上一篇下一篇

猜你喜欢

热点阅读