简体   繁体   English

AVQueuePlayer无法播放本地MP3文件

[英]AVQueuePlayer unable to play local MP3 files

I'm currently writing an iOS app that allows users to stream music from soundcloud. 我目前正在编写一个iOS应用程序,该程序允许用户从soundcloud流式传输音乐。 Currently I am able to stream just fine from Soundcloud, in booth forefront and background app states. 目前,我能够从Soundcloud中以最前沿和后台应用程序状态流式传输。 I have an issue when I download an MP3 files and attempt to play it and have continuously playback when the app in in the background, more specifically in the locked screen or the screen is off. 当我在后台(尤其是在锁定屏幕中或屏幕关闭)中下载该应用程序并尝试播放它并尝试连续播放并连续播放时遇到问题。

When I play a downloaded file and lock the screen, the audio continues to play for a while. 当我播放下载的文件并锁定屏幕时,音频会继续播放一段时间。 Usually it plays for 2 -3 mins. 通常播放2 -3分钟。 After that playback will stop and any other downloaded mp3 files in the playlist will not playback until the user returns to the app. 此后,播放将停止,并且播放列表中的所有其他下载的mp3文件将不会播放,直到用户返回到应用为止。 Items in the playlist that are not downloaded will playback perfectly if the user has an internet connection, regardless if a downloaded item failed to play previously. 如果用户具有Internet连接,则播放列表中未下载的项目将完美播放,而不管下载的项目以前是否播放失败。

There are times when I receive the following error: 有时我会收到以下错误:

AVPlayerItemStatusFailed: Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not becompleted" UserInfo=0x170270500 {NSUnderlyingError=0x170059380 "The operation couldn't be completed. Operation not permitted", NSLocalizedFailureReason=An unknown error occurred (1), NSLocalizedDescription=The operation could not be completed} AVPlayerItemStatusFailed:错误域= AVFoundationErrorDomain代码= -11800“操作无法完成” UserInfo = 0x170270500 {NSUnderlyingError = 0x170059380“操作无法完成。不允许操作”,NSLocalizedFailureReason =发生未知错误(1),NSLocalizedDescription =操作无法完成}

I will additionally get the following notification from the AVPlayerItem 我还将从AVPlayerItem收到以下通知

Notification: NSConcreteNotification 0x1700538c0 {name = AVPlayerItemDidPlayToEndTimeNotification; 通知:NSConcreteNotification 0x1700538c0 {name = AVPlayerItemDidPlayToEndTimeNotification; object = AVPlayerItem: 0x178009300, asset = AVURLAsset: 0x17822aaa0, URL = file:///var/mobile/Applications/51118E74-3334-4EFC-B148-B485DE675F9E/Documents/Downloads/SC_165903784.mp3} object = AVPlayerItem:0x178009300,资产= AVURLAsset:0x17822aaa0,URL = file:///var/mobile/Applications/51118E74-3334-4EFC-B148-B485DE675F9E/Documents/Downloads/SC_165903784.mp3}

This notification is received when the first item that is playing stop playing. 当正在播放的第一个项目停止播放时,将收到此通知。 It doesn't make sense that I get this notification when it doesn't finish playing to end of its duration. 当它在播放期间还没有结束播放时,我得到此通知是没有意义的。

My guess is that because the app is in background mode there is a limited time set for reading files, but I somehow doubt that. 我的猜测是,由于该应用程序处于后台模式,因此读取文件的时间设置有限,但是我对此表示怀疑。

I'm using the following to create a AVPlayerItem from a Local file. 我正在使用以下内容从本地文件创建AVPlayerItem。

NSURL* url = [NSURL fileURLWithPath:song.downloadFilePath]; [AVPlayerItem playerItemWithURL:url];

I have tried building my own AVQueuePlayer and also using iOS Hysteria Player, but both instances have given me the same bug for offline download playback. 我曾尝试构建自己的AVQueuePlayer并使用iOS Hysteria Player,但两个实例都给了我相同的Bug,可进行离线下载播放。

Any insights or solutions are greatly appreciated. 任何见解或解决方案,我们将不胜感激。

Thanks! 谢谢!

Are you playing your files from the Documents directory? 您正在从“文档”目录播放文件吗? (Or anywhere besides the app bundle?) (或者除了应用程序捆绑包之外的其他地方?)

If so, be sure to save the files to the directory using [fileToSave writeToFile:filePath options:NSDataWritingFileProtectionNone error:nil]; 如果是这样,请确保使用[fileToSave writeToFile:filePath options:NSDataWritingFileProtectionNone error:nil];将文件保存到目录[fileToSave writeToFile:filePath options:NSDataWritingFileProtectionNone error:nil]; .

The NSDataWritingFileProtectionNone is the critical bit! NSDataWritingFileProtectionNone是关键! What's going on, at least in my case, is this: iOS is trying to be secure, and so is by default enabling file protection on the files you add to the Documents directory (and also the other non-app-bundle directories as well, I believe). 至少在我看来,这是怎么回事:iOS试图确保安全,因此默认情况下,对添加到Documents目录(以及其他非app-bundle目录)中的文件启用文件保护, 我相信)。 By adding NSDataWritingFileProtectionNone , you're requesting the system to no longer enable this protection on your files. 通过添加NSDataWritingFileProtectionNone ,您请求系统不再对文件启用此保护。

From Apple's iOS Documentation : Apple的iOS文档中

If you protect a file, your app must be prepared to lose access to that file. 如果您保护文件,则您的应用必须准备好失去对该文件的访问权限。 When complete file protection is enabled, your app loses the ability to read and write the file's contents when the user locks the device. 启用完整的文件保护后,当用户锁定设备时,您的应用程序将失去读写文件内容的功能。

Now, as soon as I read that, I was almost positive that this was the cause for my app not being able to continue playback once the device was locked. 现在,一旦我读到它,我几乎可以肯定,这是导致设备锁定后我的应用无法继续播放的原因。 For security's sake, iOS seems to default to automatically putting files under protection… but this keeps everything, including your app, from being able to access it while the device is locked. 为了安全起见,iOS似乎默认情况下会自动将文件置于保护之下……但是,这会阻止包括设备在内的所有内容在设备锁定时访问它。 My bug was that it only played part of the song as soon as the device was locked, and that makes sense… since its access to the actual song file was revoked, it was only able to play the part of the song that had already been buffered into RAM! 我的错误是,仅在设备锁定后才播放歌曲的一部分,这是有道理的……由于撤消了对实际歌曲文件的访问,因此它只能播放已经被删除的歌曲的一部分。缓冲到RAM中!

This was the fix for a month-long problem I've been pulling my hair out to try to solve. 这是解决我一个月来一直在努力解决的问题的解决方案。 I sincerely hope it fixes the issue for you too. 我衷心希望它也为您解决此问题。

I believe this issue is caused by the limitation of AVQueuePlayer, and HysteriaPlayer using AVQueuePlayer as core player so that's why. 我认为此问题是由于AVQueuePlayer的限制以及使用AVQueuePlayer作为核心播放器的HysteriaPlayer造成的,所以这就是原因。

I've seen AVQueuePlayer document mentioned (I can't find it unfortunately) that it can't handle the queue mixed with local and remote audios. 我看过提到的AVQueuePlayer文档(不幸的是,我找不到),它无法处理与本地和远程音频混合的队列。

There's some workarounds: 有一些解决方法:

Use AVPlayer 使用AVPlayer

Don't use AVQueuePlayer, handle the queue by yourself and feed it to AVPlayer. 不要使用AVQueuePlayer,自己处理队列并将其馈送到AVPlayer。

Separate two AVQueuePlayer 分离两个AVQueuePlayer

One for local media, one for remote media. 一种用于本地媒体,一种用于远程媒体。 Insert and use PlayerItem and Player properly. 正确插入并使用PlayerItem和Player。

I would patch HysteriaPlayer to meet this requirement a month later, you can come back that time. 一个月后,我将对HysteriaPlayer进行补丁以满足此要求,您可以在那时回来。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM