ios下视频边下载连播放实现
2014-07-23 14:41
281 查看
参见网上示例大概清楚了在线缓存播放原理
1,本地实现httpserver,MPMoviePlayerController通过访问本地资源来实现视频播放如(http://127.0.0.1/test.mp4)
2,自己实现下目标视频下载,并在返回文件头时,将content-length字段取出,并存入沙盒
2,文件下载中不断写入已下载资源
原来MPMoviePlayerController访问网络视频时会自动不断请求这个资源地址,我们通过不断往这个地址写入数据来实现本地缓存
参照源码和博文
具体代码如下
初始化httpserver
修改httpserver中HTTPFileResponse.m
部分视频出现如下错误
_itemFailedToPlayToEnd: {
kind = 1;
new = 2;
old = 0;
}
解决参见 /article/9304406.html
1,本地实现httpserver,MPMoviePlayerController通过访问本地资源来实现视频播放如(http://127.0.0.1/test.mp4)
2,自己实现下目标视频下载,并在返回文件头时,将content-length字段取出,并存入沙盒
2,文件下载中不断写入已下载资源
原来MPMoviePlayerController访问网络视频时会自动不断请求这个资源地址,我们通过不断往这个地址写入数据来实现本地缓存
参照源码和博文
具体代码如下
#import <Foundation/Foundation.h> typedef enum enWordResType { RES_TYPE_JPG, RES_TYPE_MP3, RES_TYPE_FLV, RES_TYPE_UNKNOW, }enWordResType; // // http下载任务委托 // @class HttpDownloadUnit; @protocol HttpDownloadUnitDelegate <NSObject> -(void) HttpDownloadUnitProgress:(HttpDownloadUnit *)object percent:(int)nPercent; -(void) HttpDownloadUnitCompleted:(HttpDownloadUnit *)object data:(NSData *)data; -(void) HttpDownloadUnitError:(HttpDownloadUnit *)object error:(NSError *)error; @end // // // @interface HttpDownloadUnit : NSObject<NSURLConnectionDelegate,NSURLConnectionDataDelegate> { NSURLConnection *_conn; NSMutableData *_buffer; int64_t _bytesTotal; } //属性定义 @property(nonatomic,retain) NSString *url; @property(nonatomic,retain) id<HttpDownloadUnitDelegate> delegate; //方法定义 //根据一个完整url返回一个不包含xxx.xxx.com的相对路径 +(NSString *)relativePath:(NSString *)strURL; //根据文件名创建对应的本地路径 +(void)CreateFolderByPath:(NSString *)strFileName; //取消 -(void)cancel; -(void)startCache:(NSString *)strURL; -(id)initWithURL:(NSString *)url; @end
// // WordResCache.m // LearningEnglish // // Created by w on 14-6-10. // Copyright (c) 2014年 xxx.com. All rights reserved. // #import "HttpDownloadUnit.h" #import "LocalDataMgr.h" @interface HttpDownloadUnit() @end @implementation HttpDownloadUnit // +(NSString *)relativePath:(NSString *)strURL; { //http://www.xxx.com/xx/xxx.xxx NSRange sr; sr.location = 7; // "http://" sr.length = strURL.length - 7; NSRange range1 = [strURL rangeOfString:@"/" options:NSCaseInsensitiveSearch range:sr]; if (range1.length != 0) { return [strURL substringFromIndex:range1.location + 1]; } return nil; } // -(void)cancel { [_conn cancel]; _conn = nil; } // -(void)startCache:(NSString *)strURL { self.url = strURL; if (_conn) { [_conn cancel]; _conn = nil; } [_buffer setLength:0]; NSURL *url = [[NSURL alloc] initWithString:strURL]; NSMutableURLRequest *urlReq = [[NSMutableURLRequest alloc] initWithURL:url]; urlReq.timeoutInterval = 10.0; urlReq.HTTPMethod = @"GET"; _conn = [NSURLConnection connectionWithRequest:urlReq delegate:self]; } // -(id)initWithURL:(NSString *)url { self = [super init]; if (self) { self.url = url; _buffer = [[NSMutableData alloc] init]; [self startCache:url]; } return self; } #pragma mark NSURLConnection Delegate -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { if (self.delegate && [self.delegate respondsToSelector:@selector(HttpDownloadUnitError:error:)]) [self.delegate HttpDownloadUnitError:self error:error]; NSLog(@"connection fail."); } // - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{ NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; if(httpResponse && [httpResponse respondsToSelector:@selector(allHeaderFields)]){ NSDictionary *httpResponseHeaderFields = [httpResponse allHeaderFields]; _bytesTotal = [[httpResponseHeaderFields objectForKey:@"Content-Length"] longLongValue]; //NSLog(@"%lld", total_); } } // -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [_buffer appendData:data]; int nPercent = (((float)_buffer.length / (float)_bytesTotal) * 100); if (self.delegate && [self.delegate respondsToSelector:@selector(HttpDownloadUnitProgress:percent:)]) [self.delegate HttpDownloadUnitProgress:self percent:nPercent]; } //根据文件名创建对应的本地路径 +(void)CreateFolderByPath:(NSString *)strFileName { NSRange range = [strFileName rangeOfString:@"/" options:NSBackwardsSearch]; if (range.length > 0) { NSFileManager *fileMgr = [NSFileManager defaultManager]; NSString *strFolder = [strFileName substringToIndex:range.location]; [fileMgr createDirectoryAtPath:strFolder withIntermediateDirectories:YES attributes:nil error:nil]; } } // -(void)connectionDidFinishLoading:(NSURLConnection *)connection { NSString *strRelativePath = [HttpDownloadUnit relativePath:self.url]; NSString *strLocalFile = [LocalDataMgr getLocalResFileName:strRelativePath]; //根据文件名创建对应的目录结构 [HttpDownloadUnit CreateFolderByPath:strLocalFile]; NSLog(@"保存本地文件:%@",strLocalFile); [_buffer writeToFile:strLocalFile atomically:YES]; if (self.delegate && [self.delegate respondsToSelector:@selector(HttpDownloadUnitCompleted:data:)]) [self.delegate HttpDownloadUnitCompleted:self data:_buffer]; } @end
// // httpVideoController.h // LearningEnglish // // Created by w on 14-7-21. // Copyright (c) 2014年 xxx.com. All rights reserved. // #import <UIKit/UIKit.h> #import "VideoCacheUnit.h" @interface httpVideoController : UIViewController<VideoCacheUnitDelegate> { VideoCacheUnit *_videoCacheUnit; } @end
// // httpVideoController.m // LearningEnglish // // Created by w on 14-7-21. // Copyright (c) 2014年 xxx.com. All rights reserved. // #import "httpVideoController.h" #import "VideoCacheUnit.h" #import <MediaPlayer/MediaPlayer.h> @interface httpVideoController () { } @end @implementation httpVideoController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } -(void)willStartVideCache { NSURL *url = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"http://127.0.0.1:%d/test.mp4",HTTP_SERVER_PORT]]; player = [[MPMoviePlayerController alloc] initWithContentURL:url]; // 设置播放器的大小(16:9) [player.view setFrame:CGRectMake(0, 30, 320, 180)]; //设置样式,让播放器影藏工具条 [player setControlStyle:MPMovieControlStyleEmbedded]; // 将播放器视图添加到根视图 [self.view addSubview:player.view]; [player play]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onReadyPlay:) name:MPMoviePlayerReadyForDisplayDidChangeNotification object:nil]; } MPMoviePlayerController *player ; - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; //NSArray *directoryPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //NSString *documentDirectory = [directoryPaths objectAtIndex:0]; // DBNAME 是要查找的文件名字,文件全名 //NSString *filePath = [documentDirectory stringByAppendingPathComponent:@"test.mp4"]; // // filePath = [[NSBundle mainBundle] pathForResource:@"q1" ofType:@"mp4"]; // NSLog(@"PATH=%@",filePath); // 用这个方法来判断当前的文件是否存在,如果不存在,就创建一个文件 //NSURL *url = [[NSBundle mainBundle]URLForResource:@"q1" withExtension:@"mp4"]; //NSURL *url = [[NSURL alloc] initFileURLWithPath:filePath]; //NSURL *url = [NSURL URLWithString:@"http://static.tripbe.com/videofiles/20121214/9533522808.f4v.mp4"]; _videoCacheUnit = [[VideoCacheUnit alloc] initWithURL:@"http://static.tripbe.com/videofiles/20121214/9533522808.f4v.mp4"]; _videoCacheUnit.delegate = self; // Do any additional setup after loading the view. } -(void)onReadyPlay:(NSNotification *)notify { [player play]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */ @end
初始化httpserver
-(void)startServer { NSError *error; if([httpServer start:&error]) { NSLog(@"Started HTTP Server on port %hu", [httpServer listeningPort]); } else { NSLog(@"Error starting HTTP Server: %@", error); } } -(void)initHttpServer { httpServer = [[HTTPServer alloc] init]; [httpServer setType:@"_http._tcp."]; [httpServer setPort:HTTP_SERVER_PORT]; // Serve files from our embedded Web folder NSString *webPath = [NSHomeDirectory() stringByAppendingPathComponent:@"WebRoot"]; webPath = NSTemporaryDirectory(); NSLog(@"webRoot=%@",webPath); NSFileManager *fileManager=[NSFileManager defaultManager]; if(![fileManager fileExistsAtPath:webPath]) { [fileManager createDirectoryAtPath:webPath withIntermediateDirectories:YES attributes:nil error:nil]; } [httpServer setDocumentRoot:webPath]; [self startServer]; }
修改httpserver中HTTPFileResponse.m
@implementation HTTPFileResponse - (id)initWithFilePath:(NSString *)fpath forConnection:(HTTPConnection *)parent { // NSLog(@"filePath = %@",fpath); if((self = [super init])) { HTTPLogTrace(); connection = parent; // Parents retain children, children do NOT retain parents fileFD = NULL_FD; filePath = [[fpath copy] stringByResolvingSymlinksInPath]; if (filePath == nil) { //HTTPLogWarn(@"%@: Init failed - Nil filePath", THIS_FILE); return nil; } //NSLog(@"filePath = %@",filePath); NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil]; if (fileAttributes == nil) { //HTTPLogWarn(@"%@: Init failed - Unable to get file attributes. filePath: %@", THIS_FILE, filePath); return nil; } //fileLength = (UInt64)[[fileAttributes objectForKey:NSFileSize] unsignedLongLongValue]; NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; fileLength = (UInt64)[userDefaults doubleForKey:cache_video_file_size]; //fileLength = 20955211; fileOffset = 0; //NSLog(@"fileAttributes = %@",fileAttributes); //NSLog(@"fileLength = %llu",fileLength); aborted = NO; // We don't bother opening the file here. // If this is a HEAD request we only need to know the fileLength. } return self; }
部分视频出现如下错误
_itemFailedToPlayToEnd: {
kind = 1;
new = 2;
old = 0;
}
解决参见 /article/9304406.html
相关文章推荐
- iOS音视频实现边下载边播放
- iOS音视频实现边下载边播放
- iOS音视频实现边下载边播放
- ios开发视频播放后台下载功能实现 :1,ios播放视频 ,包含基于AVPlayer播放器,2,实现下载,iOS后台下载(多任务同时下载,单任务下载,下载进度,下载百分比,文件大小,下载状态)(真机调试功能正常)
- 用 MPMoviePlayerController 实现简单的视频下载播放功能
- 通过ASIHTTPRequest实现简单流媒体视频播放下载
- iOS M3U8视频的下载与播放
- iOS中 MPMoviePlayer 实现视频音频播放 作者:韩俊强
- 用 MPMoviePlayerController 实现简单的视频下载播放功能
- iOS开发网络篇—实现一个视频播放客户端小应用(二)
- iOS 本地视频播放 二步实现
- iOS app启动播放视频实现
- IOS Android 视频播放(不使用第三方库,使用平台底层sdk)实现
- IOS上MediaPlayer framework实现视频播放
- iOS中 MediaPlayer framework实现视频播放 韩俊强的博客
- HttpServer实现边下载边播放视频(转)
- iOS autolayout进阶教程,实现视频播放时,横竖屏的自动切换-适配iOS8 sizeClass 和之前的版本
- iOS开发网络篇—实现一个视频播放客户端小应用(二)
- iOS开发网络篇—实现一个视频播放客户端小应用(三)
- iOS中 MPMoviePlayer 实现视频音频播放 作者:韩俊强