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时流式传输视频所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)