1

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

我有一个在应用程序声音中使用的应用程序。目前我正在使用 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 音乐时可能会出现一些轻微的性能问题,但我宁愿坚持这种播放音频的方法。

感谢您提供任何帮助。

-瑞安

4

1 回答 1

0

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

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

因此,我建议再次检查您的代码,并确保所有调用playSound都是从主线程进行的。此外,最好使用performSelectorOnMainThread而不是performSelectorAfterDelay文档所说的那样:

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

于 2013-06-27T20:26:55.833 回答