iOS 8 在 10 分钟后停止在后台流式传输音频

Posted

技术标签:

【中文标题】iOS 8 在 10 分钟后停止在后台流式传输音频【英文标题】:iOS 8 stops streaming audio in background after 10 minutes 【发布时间】:2014-10-04 18:14:37 【问题描述】:

我有一个应用程序可以播放来自 SHOUTcast 服务器的流式音频。当应用程序处于前台并且禁用自动锁定时,一切正常。然而,该应用程序也能够在后台播放音频,此功能在 ios 6 和 iOS 7 上一直运行良好。但现在我的用户报告说,在升级到 iOS 8 大约 10 分钟后后台音频停止。

只需在 iOS 8 上运行该应用程序,我就可以自己重现该问题。由于该应用程序本身非常复杂,因此我制作了一个简单的演示来展示该问题。我正在使用 Xcode 6 并且 Base SDK 设置为 iOS 8。我已在 Info.plist 中将 audio 添加到 UIBackgroundModes。有人知道下面的代码有什么问题吗?

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
    NSURL *streamingURL = [NSURL URLWithString:@"http://www.radiofmgold.be/stream.php?ext=pls"];

    AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:streamingURL];
    [self setPlayerItem:playerItem];

    AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];
    [player setAllowsExternalPlayback:NO];

    [self setPlayer:player];
    [player play];

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

    return YES;

【问题讨论】:

如果你找到了请分享修复。我的用户也报告了这个问题。我无法重现它。 一开始我也无法重现该问题,因为并非所有流媒体链接都出现此问题。然而,我的代码中的流总是在十分钟后停止,而它在 iOS 7 上运行良好。这真的很烦人,因为这种流是我的应用程序的主要功能,我现在被一星评论和用户的抱怨所淹没。我会尽快在这个问题上设置赏金,但我担心这是苹果公司的一个错误。我真的希望我能自己修复它。我的应用程序基本上依赖于这个功能。 大家好,我也遇到了同样的问题。在我看来,Apple 搞砸了。在我的情况下,直到流停止播放的时间变化很大(5 分钟到 12 分钟)。似乎流突然失去连接然后播放,直到用完缓冲数据。当应用程序在前台以及在后台时发生。处理它的唯一方法是观察 AVPlayerItem 的状态。我会将其发布为答案。 【参考方案1】:

我在 iOS 8.0.2 下遇到了同样的问题。我的远程音频源以 mp3 播放。 似乎内部错误导致 AVAudioSession 重新启动。你可以用不同的方式来处理它:

您可以观察 AVPlayerItem 的状态。

void* YourAudioControllerItemStatusContext = "YourAudioControllerItemStatusContext";
...
@implementation YourAudioController
...
- (void)playStream 
    ...
    AVPlayerItem *item = [[AVPlayerItem alloc] initWithURL:streamUrl];
    [item addObserver:self forKeyPath:@"status" options:0 context:MJAudioControllerItemStatusContext];


- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
    if (context == YourAudioControllerItemStatusContext) 
        AVPlayerItem *item = object;
        if (item.status == AVPlayerItemStatusFailed) 
            [self recoverFromError];
        
    

这种方式似乎不可靠,因为在 AVPlayerItem 的状态发生变化之前可能会有很长的时间延迟 - 如果它发生变化的话。

我通过observeValueForKeyPath调试,发现AVPlayerItem的状态变为AVErrorMediaServicesWereReset,并且设置了错误码-11819

自从我遇到 AVErrorMediaServicesWereReset 错误后,我研究了导致此错误的原因 - 是 AVAudioSession 发疯了。参考 Apple 的 Technical Q&A,您应该注册 AVAudioSessionMediaServicesWereResetNotifications。把它放在你的代码中:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionWasReset:) name:AVAudioSessionMediaServicesWereResetNotification object:nil];

然后添加这个方法:

- (void)audioSessionWasReset:(NSNotification *)notification 
    [self recoverFromError];

在 recoverFromError 方法中尝试以下方法之一:

显示一条警报,描述 iOS 8 下存在问题并且需要重新启动流 通过再次激活 AVAudioSession 来重新启动流,并使用新的 AVPlayerItem 实例化一个新的 AVPlayer 实例

目前这是我知道如何处理它的唯一方法。问题是为什么 AudioSession 会重新启动。

更新 iOS 8.1 的发布解决了这个问题。

【讨论】:

【参考方案2】:

我也遇到过同样的问题,并在运行 iOS 8.0.2 的 iPhone 5s 和运行 iOS 8.1 beta 2 的 iPad Mini Retina 上进行了测试,这意味着这个问题在即将到来的测试版。大约 30 分钟后,两者都停止播放音频。

当 AVPlayer.status == AVPlayerItemStatusFailed 时,您可以注销 AVPlayer.status 以获取有关错误的更多详细信息。我收到:Error Domain=AVFoundationErrorDomain Code=-11819 "Cannot Complete Action" UserInfo=0x178a75bc0 NSLocalizedDescription=Cannot Complete Action, NSLocalizedRecoverySuggestion=Try again later.

即使在尝试捕捉并停止并启动我的播放器时,我也会收到一个致命错误,告诉我 AVPlayer 已被释放。此时可能值得尝试按照 Hendrik 的建议重新初始化一个新的 AVPlayer 实例。这仍然不能解决当您尝试重新初始化时音频会暂时中断的事实。您的 AVPlayer 也可能在您重新初始化之前收到通知,这意味着您将收到一个致命错误;这远非永久修复。

也许其他人会对此有更多的运气,并且可以提供更具体的解决方案。同时,我也向苹果报告了这个错误。

2014 年 10 月 15 日更新:Apple 已关闭我的错误报告,状态如下:重复 18152675(已关闭)。

【讨论】:

【参考方案3】:

看起来它在 iOS 8.1 中已修复

【讨论】:

是的,我运行了问题中的示例代码,流式传输持续了 30 分钟(之后我手动停止了它)。我想知道为什么这个 iOS 8.0 错误没有影响 Pandora 和 Spotify。【参考方案4】:

这个问题似乎已经在 iOS8.1 更新中得到修复。我昨天更新了它,能够播放 45 分钟,而在更新之前,它会在 10-15 分钟内崩溃。

【讨论】:

以上是关于iOS 8 在 10 分钟后停止在后台流式传输音频的主要内容,如果未能解决你的问题,请参考以下文章

IOS - 流式传输和下载音频文件

iOS解决应用进入后台后计时器和位置更新停止的问题

将音频流式传输到本地网络

调度程序播放在 10 分钟后停止 (discord.js)

将音频记录从浏览器流式传输到服务器?

Phonegap / Cordova 在后台 IOS 一段时间后停止音频