【发布时间】:2013-06-21 17:55:34
【问题描述】:
我将尝试详细说明我的问题。
我有一个应用程序在商店中使用应用程序声音。目前我正在使用 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 音乐时可能会出现一些轻微的性能问题,但我宁愿坚持使用这种播放音频的方法。
感谢您提供的任何帮助。
-瑞恩
【问题讨论】:
-
是否有可能两个不同的线程可以在您的应用程序中同时修改音频会话?我过去遇到过类似的问题,发现是并发线程访问的原因。
-
写完之后,我真的觉得这就是问题所在。所以你是说我的“performSelectorAfterDelay”是问题所在?之所以存在,是因为该通知在会话仍处于活动状态时发生,因此闪避不会关闭。
-
是的,如果另一个线程试图在延迟结束的同时修改音频会话,这可能是原因。所以我建议再次检查你的代码,并确保所有对
playSound的调用都是从主线程进行的。 -
另外,使用
performSelectorOnMainThread可能会更好,因为文档说'调用块、键值观察器或通知处理程序——不保证在任何特定线程或队列上进行' (developer.apple.com/library/ios/#documentation/AudioVideo/…)。 -
是的,这是一个很好的观点。我会仔细检查我所有的播放声音调用是否来自主线程,但有 50/50 的可能性它们不是,我可以确保我正在调用关闭主线程上的闪避。
标签: iphone ios audio avaudioplayer