在下载iOS时流式传输视频

在下载iOS时流式传输视频,第1张

概述我正在使用iOS 7,我有一个.mp4视频,我需要在我的应用程序下载.视频很大(约1 GB),这就是为什么它不作为应用程序的一部分包含在内.我希望用户能够在开始下载后立即开始观看视频.我也希望视频能够被缓存在iOS设备上,以便用户以后不需要再次下载.播放视频的正常方法(渐进式下载和实时流式传输)似乎不让您缓存视频,因此我已经制作了自己的Web服务,将我的视频文件重新整理并将字节流传输给客户端.我使 我正在使用iOS 7,我有一个.mp4视频,我需要在我的应用程序下载.视频很大(约1 GB),这就是为什么它不作为应用程序的一部分包含在内.我希望用户能够在开始下载后立即开始观看视频.我也希望视频能够被缓存在iOS设备上,以便用户以后不需要再次下载.播放视频的正常方法(渐进式下载和实时流式传输)似乎不让您缓存视频,因此我已经制作了自己的Web服务,将我的视频文件重新整理并将字节流传输给客户端.我使用NSURLConnection启动流http呼叫:
self.request = [[NSMutableURLRequest alloc] initWithURL:self.url];[self.request setTimeoutInterval:10]; // Expect data at least every 10 seconds[self.request sethttpMethod:@"GET"];self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:YES];

当我收到数据块时,我将其附加到文件的本地副本的末尾:

- (voID)connection:(NSURLConnection *)connection dIDReceiveData:(NSData *)data{     NSfileHandle *handle = [NSfileHandle fileHandleForWritingAtPath:[self vIDeofilePath]];     [handle truncatefileAtOffset:[handle seekToEndOffile]];     [handle writeData:data];}

如果我让设备运行,该文件成功下载,我可以使用MPMovIEPlayerVIEwController播放:

NSURL *url=[NSURL fileURLWithPath:self.vIDeofilePath];MPMovIEPlayerVIEwController *controller = [[MPMovIEPlayerVIEwController alloc] initWithContentURL:url];controller.movIEPlayer.scalingMode = MPMovIEScalingModeAspectFit;[self presentMovIEPlayerVIEwControllerAnimated:controller];

但是,如果我在文件完全下载之前启动播放器,视频开始播放很好.它甚至在顶部洗涤器栏显示正确的视频长度.但是当用户在视频开始之前到达视频中已完成下载的位置时,视频就挂起了.如果我关闭并重新打开MPMovIEPlayerVIEwController,则视频播放,直到它再次启动MPMovIEPlayerVIEwController时,到达任何位置.如果我等到整个视频被下载,那么视频播放没有问题.

发生这种情况时,我没有收到任何事件的发生,或打印到控制台的错误消息(MPMovIEPlayerPlaybackStateDIDChangeNotification和MPMovIEPlayerPlaybackDIDFinishNotification从未在视频启动后发送).似乎还有一些其他事情告诉控制器视频的长度是什么,除了洗涤器正在使用…

有人知道可能导致这个问题吗?我没有必要使用MPMovIEPlayerVIEwController,所以如果不同的视频播放方法可以在这种情况下工作,我都是为了这一点.

相关未解决的问题:

AVPlayer and Progressive Video Downloads with AVURLAssets

Progressive Video Download on iOS

How to play an in downloading progress video file in IOS

更新1
我发现视频播放确实是因为视频开始播放时的文件大小.我可以通过在开始下载之前创建一个零编辑文件,并在我去时覆盖它来解决这个问题.由于我可以控制视频流服务器,所以我添加了一个自定义标题,所以我知道正在流式传输的文件的大小(流文件的默认文件大小为-1).我以我的dIDReceiveResponse方法创建文件如下:

- (voID)connection:(NSURLConnection *)connection dIDReceiveResponse:(NSURLResponse *)response{            // RetrIEve the size of the file being streamed.    NShttpURLResponse *httpResponse = (NShttpURLResponse *)response;    NSDictionary *headers = httpResponse.allheaderFIElds;    NSNumberFormatter * formatter = [[NSNumberFormatter alloc] init];    [formatter setNumberStyle:NSNumberFormatterDecimalStyle];    self.streamingfileSize = [formatter numberFromString:[headers objectForKey:@"StreamingfileSize"]];    // Check if we need to initialize the download file    if (![[NSfileManager defaultManager] fileExistsAtPath:self.path])    {                    // Create the file being downloaded        [[NSData data] writetofile:self.path atomically:YES];        // Allocate the size of the file we are going to download.        const char *cString = [self.path cStringUsingEnCoding:NSASCIIStringEnCoding];        int success = truncate(cString,self.streamingfileSize.longLongValue);        if (success != 0)        {            /* Todo: handle errors here. Probably not enough space... See 'man truncate' */        }    }}

这样做很好,除了截断导致应用程序挂起大约10秒,同时在磁盘上创建〜1GB的文件(在模拟器上是即时的,只有一个真正的设备有这个问题).这是我现在所在的地方 – 有没有人知道一种更有效地分配文件的方法,还是以不同的方式让视频播放器识别文件的大小而不需要实际分配?我知道一些文件系统支持“文件大小”和“磁盘大小”作为两个不同的属性…不知道如果iOS有这样的东西?

解决方法 我想出了如何做到这一点,它比我原来的想法简单得多.

首先,由于我的视频是.mp4,MPMovIEPlayerVIEwController或AVPlayer类可以直接从Web服务器播放 – 我不需要执行任何特殊的 *** 作,他们仍然可以寻求视频中的任何一点.这必须是.mp4编码与电影播放器​​一起使用的一部分.所以,我只需要在服务器上提供原始文件 – 不需要特殊的头文件.

接下来,当用户决定播放视频时,我立即从服务器URL开始播放视频:

NSURL *url=[NSURL fileURLWithPath:serverVIDelfileURLString];controller = [[MPMovIEPlayerVIEwController alloc] initWithContentURL:url];controller.movIEPlayer.scalingMode = MPMovIEScalingModeAspectFit;[self presentMovIEPlayerVIEwControllerAnimated:controller];

这使得用户可以观看视频并寻找到他们想要的任何位置.然后,我开始使用NSURLConnection手动下载文件,就像我以前一直在做的,除了现在我没有流式传输文件,我只是直接下载它.这样我不需要自定义标题,因为文件大小包含在http响应中.

当我的后台下载完成后,我将播放项从服务器URL切换到本地文件.这对于网络性能很重要,因为电影播放器​​只能在用户正在观看的几秒钟之前下载.能够尽快切换到本地文件是避免下载太多重复数据的关键:

NSTimeInterval currentPlaybackTime = vIDeoController.movIEPlayer.currentPlaybackTime;[controller.movIEPlayer setContentURL:url];[controller.movIEPlayer setCurrentPlaybackTime:currentPlaybackTime];[controller.movIEPlayer play];

这种方法确实让用户最初同时下载了两个视频文件,但是在网络上的初始测试速度,我的用户将会使用它,只会增加下载时间几秒钟.为我工作!

总结

以上是内存溢出为你收集整理的在下载iOS时流式传输视频全部内容,希望文章能够帮你解决在下载iOS时流式传输视频所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1097995.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-28
下一篇 2022-05-28

发表评论

登录后才能评论

评论列表(0条)

保存