音频会话“闪避”在 iOS 4 中中断...?

Posted

技术标签:

【中文标题】音频会话“闪避”在 iOS 4 中中断...?【英文标题】:Audio Session "Ducking" Broken in iOS 4...? 【发布时间】:2010-07-20 19:33:57 【问题描述】:

我有一个应用程序,它使用 MPAudioPlayerController 访问 iPod 音乐库,并使用 AVAudioPlayer 将音频覆盖在音乐之上。我使用this documentation 作为指导。具体来说:

最后,您可以增强一个类别以在播放音频时自动降低其他音频的音量。例如,这可以在锻炼应用程序中使用。假设当您的应用程序想要覆盖口头消息时,用户正在使用他们的 iPod 进行锻炼——例如,“您已经划船 10 分钟了。”为确保来自应用程序的消息可理解,请将 kAudiosessionProperty_OtherMixableAudioShouldDuck 属性应用于音频会话。发生闪避时,设备上的所有其他音频(除了电话音频)的音量都会降低。

但我没有看到这种行为。事实上,我看到(或听到)是,如果我设置 AudioSession 并将 kAudioSessionProperty_OtherMixableAudioShouldDuck 设置为 true,则 MPAudioPlayerController 初始音量会降低,如果我随后在 MPAudioPlayerController 上调用暂停(然后再次播放)音量级别提高到“正常”水平。播放 AVAudioPlayer 对音频电平没有任何影响...

所以我设置了一个简单的测试用例来重现这个。

在 ViewController 标头中:

#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>

@interface MusicPlayerVolumeTestViewController : UIViewController <AVAudioPlayerDelegate>

    UIButton *musicButton;
    UIButton *soundButton;
    AVAudioPlayer *audioPlayer;
    MPMusicPlayerController *musicPlayerController;

@property (nonatomic, retain) IBOutlet UIButton *musicButton;
@property (nonatomic, retain) IBOutlet UIButton *soundButton;
@property (nonatomic, retain) MPMusicPlayerController *musicPlayerController;

- (IBAction)musicAction;
- (IBAction)soundAction;

@end

在实现中:

- (void)viewDidLoad

    [super viewDidLoad];

    //Setup our Audio Session
    OSStatus status = AudioSessionInitialize(NULL, NULL, NULL, NULL);    
    //We want our audio to play if the screen is locked or the mute switch is on
    UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
    status = AudioSessionSetProperty (kAudioSessionProperty_AudioCategory, sizeof (sessionCategory), &sessionCategory);
    //We want our audio to mix with other app's audio
    UInt32 shouldMix = true;
    status = AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof (shouldMix), &shouldMix);
    //Enable "ducking" of the iPod volume level while our sounds are playing
    UInt32 shouldDuck = true;
    AudioSessionSetProperty(kAudioSessionProperty_OtherMixableAudioShouldDuck, sizeof(shouldDuck), &shouldDuck);
    //Activate our audio session
    AudioSessionSetActive(YES);

    //Setup the Music Player to access the iPod music library
    self.musicPlayerController = [MPMusicPlayerController applicationMusicPlayer];
    [self.musicPlayerController setShuffleMode: MPMusicShuffleModeSongs];
    [self.musicPlayerController setRepeatMode: MPMusicRepeatModeNone];
    [self.musicPlayerController setQueueWithQuery:[MPMediaQuery songsQuery]];

    //Setup a AVAudioPlayer sound to overlay against the Music Player audio
    NSURL *soundURL = [NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"overlay" ofType:@"mp3"]];
    NSError *error = nil;
    audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL error: &error];
    if (!audioPlayer)
    
        NSLog(@"Could not create audio effect player: %@", [error localizedDescription]);
    
    [audioPlayer prepareToPlay];


- (IBAction)musicAction

    if (self.musicPlayerController.playbackState == MPMusicPlaybackStatePlaying)
    
        [self.musicPlayerController pause];
    
    else if (self.musicPlayerController.playbackState == MPMusicPlaybackStateStopped
          || self.musicPlayerController.playbackState == MPMusicPlaybackStatePaused)
    
        [self.musicPlayerController play];
    


- (IBAction)soundAction

    if (audioPlayer.playing)
    
        [audioPlayer pause];
    
    else
    
        [audioPlayer play];
    

我已经连接了几个 UIButton。一个用于musicAction(用于播放/暂停MPMusicPlayerController),一个用于soundAction(用于播放/暂停AVAudioPlayer)。

如前所述,如果我点击 musicAction 按钮,则播放音乐,但音量会降低;如果我点击 soundAction 按钮,则播放叠加层,但不会影响 MPMusicPlayerController 的音量。而且,更类似于错误的是,当我暂停然后播放 MPMusicPlayerController 时,音乐的音量会增加到我没有设置 AudioSession 时的水平。

我很想知道其他人是否有过这种经历,如果有的话,如果你找到了解决方法(或者可以告诉我我做错了什么)。否则,我想我要去雷达了。

非常感谢,

李维斯

【问题讨论】:

【参考方案1】:

当我遇到类似问题并且无法使其始终如一地工作时,我使用了这篇文章。它会工作一段时间,然后就被卡住了。我花了很多时间研究和调试这个,最后打电话给苹果。他们告诉我查看面包屑示例代码。我遵循了那个例子,一切都很好。

这是苹果的示例代码:

http://developer.apple.com/library/ios/#samplecode/Breadcrumb/Introduction/Intro.html

Apple 的支持/开发人员还表示要注意他们设置会话属性的方式和时间。这显然是诀窍。在这里和其他地方阅读了很多帖子后,我的设置相互冲突。从头开始并遵循面包屑示例使其工作。从那以后我再也没有遇到过问题。

我在这里发布了相同的答案:

How to unduck AVAudioSession

对我来说,这个答案是边缘商业机密,因为它很难开始工作,而且市场上有可用的应用程序。对我来说,看到一个可行的例子,这几乎只是声音的闪避和不闪避就值得它的重量。

另外,我向 Apple 提到这是一个已知问题,他们不同意。他们不知道这里有任何问题。果然,如果您按照面包屑示例,它可以在没有任何奇怪的会话停用和反应等情况下工作。

【讨论】:

【参考方案2】:

闪避不会以任何方式自动与您播放的声音相关联。当您打开闪避时,背景声音会闪避。当您关闭闪避并停用音频会话时,背景声音会恢复到原来的水平。

所以不要在你的viewDidLoad 中打开闪避功能。在您真正要播放声音之前不要打开它。这会导致背景声音变小。当您的声音播放完毕后,关闭回避功能并再次将您的音频会话切换为非活动和活动。这会导致背景声音消失:

UInt32 duck = 0;
AudioSessionSetProperty(kAudioSessionProperty_OtherMixableAudioShouldDuck, 
                        sizeof(duck), &duck);
AudioSessionSetActive(false);
AudioSessionSetActive(true);

【讨论】:

【参考方案3】:

文档并不清楚闪避的预期行为应该是什么,但我发现如果您为闪避设置音频会话,当您激活音频会话时,它会闪避,并且当您停用它时,它会松开。因此,您必须不断激活和停用音频会话,以避开音乐,只为您的声音提示。

我发现的一个错误是,如果您在 AVAudioPlayerDelegateaudioPlayerDidFinishPlaying:successfully: 方法内停用音频会话,则不会删除闪避,并且音量保持在同一水平。我已经为此提交了雷达,但如果其他文件类似,也没有什么坏处。事实上,它可能会给他们施加一些压力来修复它。

您所做的是启动音频会话并使其保持打开状态,因此它会立即闪避并保持闪避状态,这样当您播放声音时它就不会再闪避音乐了。暂停和播放音乐后音量恢复的问题听起来像是一个错误。

【讨论】:

以上是关于音频会话“闪避”在 iOS 4 中中断...?的主要内容,如果未能解决你的问题,请参考以下文章

音频会话中断后恢复 twilio 通话

音频会话中断通知

OpenTok 在音频/视频会议会话中缺少音频

Iphone IOS,从另一个音频会话访问音频数据

如何取消 AVAudioSession

如何在后台开始录制 iOS 音频会话?