iOS音频问题通用配置

[[AVAudioSession sharedInstance] setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation  error:NULL];

**场景一

**
场景说明:
应用A正在播放音乐,应用B启动语音合成,但不中断应用A播放。
解决步骤:

  1. 在应用B中设置AVAudioSession的Category属性:
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:***AVAudioSessionCategoryOptionMixWithOthers ***error:nil];
  2. 启动语音合成:
    [_iFlySpeechSynthesizer startSpeaking:str];
    **场景二

**
场景说明:
应用A正在播放音乐,应用B启动语音合成,此时中断应用A播放,当合成结束后自动恢复应用A播放。
解决步骤:

  1. 在应用B中设置AVAudioSession的Category属性:
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
  2. 启动语音合成:
    [_iFlySpeechSynthesizerstartSpeaking:str];
  3. 合成结束后会调用回调方法:
    -(void)onCompleted
    IFlySpeechError) error
    在此回调方法中实现如下操作以恢复应用A的音乐播放:
    [[AVAudioSession sharedInstance] setActive:NOwithOptions:
    AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation* error:NULL];
  4. 如果是调用stopSpeaking结束合成,则不会调用步骤3的回调方法。此时需要在调用stopSpeaking之后实现如下操作以恢复应用A的音乐播放:
    [[AVAudioSession sharedInstance] setActive:NOwithOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivationerror:NULL];
    **场景三

**
场景说明:
应用A正在播放音乐,应用B启动语音识别,但不中断应用A播放。
解决步骤:

  1. 在应用B中设置AVAudioSession的Category属性:
    [[AVAudioSession sharedInstance]setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionMixWithOtherserror:nil];
  2. 启动语音识别:
    [_iFlySpeechRecognizerstartListening];
    **场景四

**
场景说明:
应用A正在播放音乐,应用B启动语音识别,此时中断应用A播放,当识别结束后自动恢复应用A播放。
解决步骤:

  1. 在应用B中设置AVAudioSession的Category属性:
    [[AVAudioSession sharedInstance]setCategory:AVAudioSessionCategoryRecord withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:nil];
  2. 启动语音识别:
    [_iFlySpeechRecognizerstartListening];
  3. 识别结束后会调用回调方法:
  • (void)onError
    IFlySpeechError ) error
    在此回调方法中实现如下操作以恢复应用A的音乐播放:
    [[AVAudioSession sharedInstance] setActive:NOwithOptions:
    AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation*error:NULL];
    **场景五

**
场景说明:
应用A正在播放音乐,然后在应用A启动语音识别,但不中断之前的音乐播放。
解决步骤:

  1. 在应用A启动识别前设置AVAudioSession的Category属性:
    [[AVAudioSession sharedInstance]setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker

|

AVAudioSessionCategoryOptionAllowBluetooth|

AVAudioSessionCategoryOptionMixWithOtherserror:nil];

  1. 启动语音识别:
    [_iFlySpeechRecognizerstartListening];
    **场景六

**
场景说明:
应用A正在播放音乐,然后在应用A启动语音识别,此时中断之前的音乐播放。当识别结束后自动恢复音乐播放。
解决步骤:

  1. 在应用A启动识别前中断正在运行的音乐播放:
    NSDictionary *userInfo = [NSDictionarydictionaryWithObjectsAndKeys:[NSNumbernumberWithInteger:1],AVAudioSessionInterruptionTypeKey, nil];
    [[NSNotificationCenter defaultCenter]postNotificationName:AVAudioSessionInterruptionNotification object:niluserInfo:userInfo];
  2. 设置识别AVAudioSession的Category属性:
    [[AVAudioSession sharedInstance]setCategory:AVAudioSessionCategoryRecord withOptions: AVAudioSessionCategoryOptionAllowBluetootherror:nil];
  3. 启动语音识别:
    [_iFlySpeechRecognizerstartListening];
  4. 识别结束后会调用回调方法:
  • (void)onError
    IFlySpeechError ) error
    在此回调方法中
    先恢复设置启动识别之前的AVAudioSession的Category*属性。然后在此回调方法中恢复应用A之前的音乐播放:
    NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumbernumberWithInteger:0],AVAudioSessionInterruptionTypeKey, nil];
    [[NSNotificationCenter defaultCenter]postNotificationName:AVAudioSessionInterruptionNotification object:niluserInfo:userInfo];
    注意事项:
  1. 切不可在识别结束后直接调用:
    [[AVAudioSession sharedInstance] setActive:NOwithOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivationerror:NULL];
    因为应用中还有音频播放服务未结束,只有在应用中所有音频服务都结束后才可以调用。
  2. 应用A中被中断的音乐播放控件必须有系统中断通知处理。
    **场景七

**
场景说明:

应用A正在播音或录音,然后在应用A启动语音合成,但不中断之前的播音或录音。
解决步骤:

  1. 在应用A启动合成前设置AVAudioSession的Category属性:
    [[AVAudioSession sharedInstance]setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionMixWithOtherserror:nil];
  2. 启动语音合成:
    [_iFlySpeechSynthesizerstartSpeaking:str];
    **场景八

**
场景说明:

应用A正在播音或录音,然后在应用A启动语音合成,此时中断之前的播音或录音。当合成结束后自动恢复播音或录音。
解决步骤:

  1. 在应用A启动合成前中断正在运行的播音或录音:
    NSDictionary *userInfo = [NSDictionarydictionaryWithObjectsAndKeys:[NSNumbernumberWithInteger:1],AVAudioSessionInterruptionTypeKey, nil];
    [[NSNotificationCenter defaultCenter]postNotificationName:AVAudioSessionInterruptionNotification object:niluserInfo:userInfo];

  2. 设置合成AVAudioSession的Category属性:
    [[AVAudioSession sharedInstance]setCategory:AVAudioSessionCategoryPlayback error:nil];

  3. 启动语音合成:
    [_iFlySpeechSynthesizerstartSpeaking:str];

  4. 合成结束后会调用回调方法:
    -(void)onCompleted

    IFlySpeechError) error
    在此回调方法中
    先恢复设置启动合成之前的AVAudioSession的Category*属性。然后在此回调方法中恢复应用A之前的播音或录音:
    NSDictionary *userInfo = [NSDictionarydictionaryWithObjectsAndKeys:[NSNumber numberWithInteger:0],AVAudioSessionInterruptionTypeKey,nil];
    [[NSNotificationCenter defaultCenter]postNotificationName:AVAudioSessionInterruptionNotification object:niluserInfo:userInfo];

  5. 如果是调用stopSpeaking结束合成,则不会调用步骤4的回调方法。此时需要在调用stopSpeaking之后先恢复设置启动合成之前的AVAudioSession的Category属性。然后在此回调方法中恢复应用A之前的播音或录音:
    NSDictionary *userInfo = [NSDictionarydictionaryWithObjectsAndKeys:[NSNumber numberWithInteger:0],AVAudioSessionInterruptionTypeKey,nil];
    [[NSNotificationCenter defaultCenter]postNotificationName:AVAudioSessionInterruptionNotification object:niluserInfo:userInfo];
    注意事项:

  6. 切不可在合成结束后直接调用:
    [[AVAudioSession sharedInstance] setActive:NOwithOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivationerror:NULL];
    因为应用中还有播放或录音服务未结束,只有在应用中所有音频服务都结束后才可以调用。

  7. 应用A中被中断的播音或录音控件必须有系统中断通知处理。
    **特别说明

**

  1. 上面介绍的只是一些典型场景,还有很多其他复杂场景这里不再一一例举,但基本可以找到类似的解决方法;
  2. 以上各场景中有关AVAudioSession的Category属性设置并不唯一,可根据实际需要作适当更改;
  3. 激活AVAudioSession:
    [[AVAudioSession sharedInstance] setActive:YESerror:NULL];
    一般是系统默认启动的,可以不用调用。
    **常见问题

**

  1. 合成开始播放声音时音量由小变大
    问题说明:
    在启动语音合成播放音频时,播放的音量刚开始由小逐渐变大最后正常。此现象目前只在iPhone 7上出现,其他机型没有出现。
    出现机型:
    iPhone 7 iOS10.1;
    出现场景:
    如果在启动语音合成前如此设置AVAudioSession的Category属性:
    [[AVAudioSession sharedInstance]setCategory:AVAudioSessionCategoryPlayAndRecordwithOptions:AVAudioSessionCategoryOptionDefaultToSpeaker|AVAudioSessionCategoryOptionAllowBluetootherror:nil];
    a. 在合成播放过程中被其他音频服务中断后又恢复会出现此现象;
    b. 在本次合成播放结束后如果没有设置:
    [[AVAudioSession sharedInstance] setActive:NOwithOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivationerror:NULL];
    则当重新启动新的合成服务时会出现此现象。
    解决思路:
    a. 在启动合成前将AVAudioSession的Category属性设置为AVAudioSessionCategoryPlayback,则可以完全避免上述问题。
    b. 若启动合成前AVAudioSession的Category属性仍是AVAudioSessionCategoryPlayAndRecord,则以上场景a问题无法避免。
    c. 若启动合成前AVAudioSession的Category属性仍是AVAudioSessionCategoryPlayAndRecord,则可以通过如下操作避免场景b问题。在每次启动合成服务前设置:
    [[AVAudioSessionsharedInstance] setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivationerror:NULL];
    初步怀疑这可能是iPhone 7 的bug,因为其他机型上并没有出现,如果大家有更好的解决方案,欢迎留言分享。

  2. AVAudioSession警告
    只有在应用中所有正在运行的音频服务都结束后才可以调用:
    [[AVAudioSession sharedInstance] setActive:NOwithOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivationerror:NULL];
    否则会出现如下警告:
    [avas] AVAudioSession.mm:1074:-[AVAudioSessionsetActive:withOptions:error:]: Deactivating an audio session that has runningI/O. All I/O should be stopped or paused prior to deactivating the audiosession.

  3. 蓝牙耳机无法录音
    所使用的蓝牙耳机必须支持A2DP协议。

  4. 后台无法启动合成或识别
    

问题说明:

当应用A正在处于后台工作时,此时启动应用A音频服务(播放或者录音)或者恢复应用A中被中断的音频服务,音频启动会失败。

原因分析:

出现以上现象时系统会报AVAudioSessionErrorCodeCannotInterruptOthers

(错误码为560557684)。这是因为当启动后台应用的音频服务时不能影响前台应用的音频服务,因此后台应用的AVAudioSession的Category属性必须含有***AVAudioSessionCategoryOptionMixWithOthers
*** 选项。

解决方法:

在合成或者识别前如下设置AVAudioSession的Category属性:

[[AVAudioSessionsharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:
AVAudioSessionCategoryOptionMixWithOtherserror:nil];

或者

[[AVAudioSessionsharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:
AVAudioSessionCategoryOptionMixWithOtherserror:nil];

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

推荐阅读更多精彩内容