AVQueuePlayer和音频会话问题

时间:2013-06-21 17:55:35

标签: iphone ios audio avaudioplayer

我将尝试详细说明我的问题。

我有一个应用程序在商店中使用app声音。目前我正在使用AVQueuePlayer,因为一些声音将重叠并允许它按顺序播放。当我使用AVPlayer播放嵌入式视频时,正在播放大量此声音,这可能无关紧要。问题是我有整个应用程序声音停止的报告。我自己无法重现,但我们有很多活跃的用户,有些人报道了。每当报告并且我们确定它不仅仅是静音开关或音量下降时重新启动应用程序总能解决问题。偶尔我们听说声音神奇地回来,没有任何变化。我还有一些报道说它在使用airplay和蓝牙时会发生,但这可能只是问题或巧合的复杂因素。

下面是我正在使用的代码,也许我只是使用设置错误或不使用我应该的设置,但此代码在99.9%的情况下工作。

我使用躲避我播放的所有声音来降低用户iPod音乐的音量。

这是我在appDidFinishLaunchingWithOptions中的初始化(也许在开始时根本不需要它,并且很抱歉混合约定):

AudioSessionInitialize (NULL, NULL, NULL, NULL);

    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];

    UInt32 sessionCategory = kAudioSessionCategory_AmbientSound;
    AudioSessionSetProperty (kAudioSessionProperty_AudioCategory, sizeof (sessionCategory), &sessionCategory);

    [[AVAudioSession sharedInstance] setActive:YES withFlags:AVAudioSessionSetActiveFlags_NotifyOthersOnDeactivation error:nil];

当我播放声音时:

-(void)playSound: (NSString *)soundString
{
    OSStatus propertySetError = 0;
    UInt32 allowMixing = true;
    propertySetError |= AudioSessionSetProperty(kAudioSessionProperty_OtherMixableAudioShouldDuck, sizeof(allowMixing), &allowMixing);

    [[AVAudioSession sharedInstance] setActive:YES withFlags:AVAudioSessionSetActiveFlags_NotifyOthersOnDeactivation error:nil];

    NSURL *thisUrl = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@.caf", [[NSBundle mainBundle] resourcePath], soundString]];

    AVPlayerItem *item = [[AVPlayerItem alloc] initWithURL:thisUrl];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(reachedEndOfItem:)
                                                 name:AVPlayerItemDidPlayToEndTimeNotification
                                               object:item];

    if(_audioPlayerQueue == nil)
    {
        _audioPlayerQueue = [[AVQueuePlayer alloc] initWithItems:[NSArray arrayWithObject:item]];
    }
    else
    {
        if([_audioPlayerQueue canInsertItem:item afterItem:nil])
        {
            [_audioPlayerQueue insertItem:item afterItem:nil];
        }
    }

    if(_audioPlayerQueue == nil)
    {
        NSLog(@"error");
    }
    else
    {
        [_audioPlayerQueue play];
    }

    return;
}

声音结束播放时:

- (void)reachedEndOfItem: (AVPlayerItem*)item
{
    [self performSelector:@selector(turnOffDucking) withObject:nil afterDelay:0.5f];
}

- (void)turnOffDucking
{
    NSLog(@"reached end");

    [[AVAudioSession sharedInstance] setActive:NO withFlags:AVAudioSessionSetActiveFlags_NotifyOthersOnDeactivation error:nil];

    OSStatus propertySetError = 0;
    UInt32 allowMixing = false;
    propertySetError |= AudioSessionSetProperty(kAudioSessionProperty_OtherMixableAudioShouldDuck, sizeof(allowMixing), &allowMixing);
}

对于我做错了什么,我应该为音频会话使用什么设置或已知错误/问题的任何见解都会非常有帮助。我愿意考虑使用不同的音频引擎,因为在播放视频和iPod音乐串联播放时会出现一些轻微的性能问题,但我宁愿坚持使用这种播放音频的方法。

感谢您提供任何帮助。

-Ryan

1 个答案:

答案 0 :(得分:0)

我过去遇到过类似的问题,并发现并发线程访问是原因。

具体来说,我认为调用performSelectorAfterDelay可能是因为另一个线程试图在延迟结束的同时修改音频会话,因为那时我们将有两个不同的线程试图访问音频会话。

因此,我建议再次检查您的代码,并确保所有对playSound的调用都是从主线程进行的。此外,最好使用performSelectorOnMainThread代替performSelectorAfterDelay作为the docs说:

  

不保证在任何特定线程或队列上进行块,键值观察器或通知处理程序的调用。相反,AV Foundation会在执行其内部任务的线程或队列上调用这些处理程序。