我正在使用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];
Run Code Online (Sandbox Code Playgroud)
当我收到数据块时,我将它附加到文件的本地副本的末尾:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:[self videoFilePath]];
[handle truncateFileAtOffset:[handle seekToEndOfFile]];
[handle writeData:data];
}
Run Code Online (Sandbox Code Playgroud)
如果我让设备运行,文件下载成功,我可以使用MPMoviePlayerViewController播放它:
NSURL *url=[NSURL fileURLWithPath:self.videoFilePath];
MPMoviePlayerViewController *controller = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
controller.moviePlayer.scalingMode = MPMovieScalingModeAspectFit;
[self presentMoviePlayerViewControllerAnimated:controller];
Run Code Online (Sandbox Code Playgroud)
但是,如果我在文件完全下载之前启动播放器,则视频开始播放就好了.它甚至可以在顶部擦洗条上显示正确的视频长度.但是当用户到达视频中我在视频开始之前完成下载的位置时,视频就会挂起.如果我关闭并重新打开MPMoviePlayerViewController,那么视频会播放,直到它到达我再次启动MPMoviePlayerViewController时的任何位置.如果我等到整个视频下载完毕,那么视频播放没有问题.
我没有收到任何事件,或者在发生这种情况时打印到控制台的错误消息(视频启动后永远不会发送MPMoviePlayerPlaybackStateDidChangeNotification和MPMoviePlayerPlaybackDidFinishNotification).似乎还有其他东西告诉控制器视频的长度是什么,而不是洗涤器使用的...
有谁知道可能导致这个问题的原因是什么?我不一定要使用MPMoviePlayerViewController,所以如果在这种情况下使用不同的视频播放方法,我就是为了它.
相关未解决的问题:
使用AVURLAssets进行AVPlayer和逐行视频下载
更新1 我发现视频停顿确实是因为视频开始播放时的文件大小.我可以通过在开始下载之前创建一个归零文件来解决这个问题,并在我去的时候覆盖它.由于我可以控制视频流服务器,因此我添加了一个自定义标头,因此我知道正在流式传输的文件的大小(流式文件的默认文件大小标头为-1).我在didReceiveResponse方法中创建文件,如下所示:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// Retrieve the size …Run Code Online (Sandbox Code Playgroud) video-streaming progressive-download mpmovieplayer ios nsurlsessiondownloadtask
我想使用AVPlayer缓存渐进式下载视频.如何将AVPlayer的项目保存到磁盘?我正在尝试在播放器的currentItem(完全加载)上使用AVAssetExportSession.这段代码给了我" AVAssetExportSessionStatusFailed(操作无法完成) ":
AVAsset *mediaAsset = self.player.currentItem.asset;
AVAssetExportSession *es = [[AVAssetExportSession alloc] initWithAsset:mediaAsset presetName:AVAssetExportPresetLowQuality];
NSString *outPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"out.mp4"];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:outPath error:NULL];
es.outputFileType = @"com.apple.quicktime-movie";
es.outputURL = [[[NSURL alloc] initFileURLWithPath:outPath] autorelease];
NSLog(@"exporting to %@",outPath);
[es exportAsynchronouslyWithCompletionHandler:^{
NSString *status = @"";
if( es.status == AVAssetExportSessionStatusUnknown ) status = @"AVAssetExportSessionStatusUnknown";
else if( es.status == AVAssetExportSessionStatusWaiting ) status = @"AVAssetExportSessionStatusWaiting";
else if( es.status == AVAssetExportSessionStatusExporting ) status = @"AVAssetExportSessionStatusExporting";
else if( es.status == AVAssetExportSessionStatusCompleted ) status = @"AVAssetExportSessionStatusCompleted"; …Run Code Online (Sandbox Code Playgroud) 我有一个处理流媒体视频的应用程序.从.m3u8播放列表开始,它会创建一个AVAssets数组,并通过它们翻转
[player replaceCurrentItemWithPlayerItem:[AVPlayerItem playerItemWithAsset:[assetItems objectAtIndex:index]]]
Run Code Online (Sandbox Code Playgroud)
这很好,但在此之前,我想用渐进式下载播放短的mp4视频.我使用加载AVPlayer
AVAsset *prerollAsset = [AVAsset assetWithURL:prerollURL];
[player replaceCurrentItemWithPlayerItem:[AVPlayerItem playerItemWithAsset:prerollAsset]];
Run Code Online (Sandbox Code Playgroud)
它播放,但当我像以前一样继续播放流视频时,我得到AVPlayerStatusFailed的状态,AVPlayerItem中的错误 The operation could not be completed
为了它的工作,我需要为(渐进式下载)预卷创建一个AVPlayer对象,然后创建一个全新的AVPlayer对象来开始播放流式视频.
是否有可能单个AVPlayer实例无法播放渐进式下载视频,然后是流式视频?或者可能还有别的我做错了?