如何在iOS中流式传输电影并在以后从文件系统播放?

时间:2012-09-21 16:25:31

标签: ios

我有一个应用程序,目前附带了它可以嵌入其中的所有视频。这不能很好地扩展,除非你想播放所有电影,否则会浪费磁盘空间。它还使得升级应用程序变得不太可取,因为您必须重新下载所有电影。

我想要做的是即时下载电影,下载时播放,然后如果成功下载,将其保存到文件系统,以便下次他们想要观看时,它会从本地文件。

我可以为视频做任何需要,但目前我正在将其作为来自Amazon S3的.mp4文件提供,其mimetype为video / mp4,因此我的问题的前半部分工作正常:电影下载,MPMovieViewController会在认为已下载“足够”后立即开始播放。

有没有办法进入该视频文件的缓存,以便我可以保存它并控制它驻留在文件系统上的时间?这似乎是最简单的方法。

我的目标是iOS 5 + 6,但如果唯一可用的解决方案需要iOS 6,我也会考虑它。谢谢!

更新:我认为,使用AFNetworking,我现在已经到了中途了。我正在从服务器下载视频文件,并监听下载进度。一旦我看到25%的视频已被下载,我就会使用MPMoviePlayerController在本地文件上开始播放。

我现在遇到的主要问题是回放似乎搞砸了。它正常,25%下载,播放开始...正常继续下载...然后文件完成下载,此后不久视频冻结。屏幕播放计时器仍然表示正在播放,我没有看到任何“播放完成”类型的通知,但视频被冻结。我根据行为得出的猜测是,视频播放的初始缓冲区可能用完了,现在还没有检测到磁盘上有更多视频可用?

有没有办法与MPMoviePlayerController进行交互,让它定期知道刷新它正在播放的缓冲区?或者其他一些方法来处理这种情况?

2 个答案:

答案 0 :(得分:8)

更新:请务必查看@TomHamming的新答案。

我还没有找到一个确凿的答案,但此时我相信答案是:你不能可靠地做到这一点。至少没有很多工作似乎太像黑客。我向Apple提交了一个功能请求,因为它似乎可以通过对MPMoviePlayerController进行一些调整来实现。

我会回顾我尝试或考虑的各种事情,以及我遇到的结果。

  • 将MPMoviePlayerController的URL传递给您的电影文件,该文件允许它流式传输,然后将文件从保存到的缓存中拉出到本地Documents文件夹中。赢了'从iOS 6开始工作。我向Apple提交了一个功能请求,但是现在它已经无法获取他们正在下载的文件,AFAIK。

  • 开始使用NSURLConnection(或像AFNetwork之类的东西)下载电影文件,然后将“体积数量”下载到设备时,将文件URL传递给MPMoviePlayerController并让它从磁盘。工作类型,但不是很好。三个问题:

    • 很难知道何时开始播放该文件。我还没有弄清楚Apple使用的算法,所以我总是在谨慎方面犯错,等待下载前下载25%。

    • MPMoviePlayerController接口不提供正在流式传输的电影,就像Apple通过网络进行计算时一样。用户看来,文件完全没有下载。

    • 最重要的是,MPMoviePlayerController似乎无法正常播放未完全下载的文件。文件下载完毕后,我遇到了播放问题,或者玩家注意到了下载量,并且从未找到优雅的方法来处理这些情况。

  • 与上面相同的程序,但使用AVFoundation类来更精细地控制播放过程,并避免上述有关播放停止等问题。可能会工作,但我想要所有的MPMoviePlayerController的功能。为了获得这一功能,我自己重新实现MPMoviePlayerController似乎是浪费时间。

  • 与上面#1相同的程序,但在您的应用中运行一个小型Web服务器来处理从磁盘到MPMoviePlayerController 的视频流,希望流式传输可以更多地工作就像通常直接从外部Web服务器流式传输文件时一样。工作,但结果仍然是零星的,表现似乎受到影响。我用CocoaHTTP进行了测试。我决定反对这种方法,因为它只是感觉像是一个可怕的黑客。

  • 运行轻量级HTTP代理,从而拦截下载的影片文件数据,因为它从互联网流式传输到您的MPMoviePlayerController。不确定这是否有效。我还没有能够测试这个,因为我还没有找到用Objective-C编写的轻量级HTTP代理,并且此时不想实现一个只是为了尝试这个实验。这似乎是所有这些黑客中最容易实现的 - 如果您不必编写代理!

在这一点上,我决定采用不太简单,但也不那么用户友好的简单下载文件的路线,然后将其传递给MPMoviePlayerController,直到出现更好的解决方案。

答案 1 :(得分:1)

您可以使用AVAssetDownloadTask从iOS 10开始执行此操作。请参阅this WWDC 2016 sessionthis documentation

或者,如果您的电影不是DRM,则可以使用AVAssetResourceLoaderDelegate执行此操作,这有效地允许您为{{1}}提供任意字节流。请参阅this walkthrough