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

Mas*_*iti 5 ios

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

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

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

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

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

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

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

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

Mas*_*iti 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代理,从而拦截下载的电影文件数据,因为它从Internet传输到MPMoviePlayerController.不确定这是否有效.我还没有能够测试这个,因为我还没有找到用Objective-C编写的轻量级HTTP代理,并且此时不想实现一个只是为了尝试这个实验.它似乎是所有这些黑客中最容易实现的 - 如果您不必编写代理!

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


Tom*_*ing 2

从 iOS 10 开始,您可以使用AVAssetDownloadTask. 请参阅WWDC 2016 会议本文档

或者,如果您的电影没有 DRM,您可以使用AVAssetResourceLoaderDelegate来实现,它可以有效地让您提供AVPlayer任意字节流。请参阅此演练