应项目需求,需要实现本地选取并上传图片、音频和视频文件。
其中选取图片这块有很多开源框架,不再赘述。本文主要是采用iOS自带的类MPMediaPickerController 来实现UIImagePickerController音频、视频文件的选取。
首先需要说明的是,如果需求是需要从语音备忘录里面读取原有录音,那么是较难实现的。我在http://stackoverflow.com/questions/5265215/iphone-access-voice-memos-programmatically上有找到相关回答说目前暂时还不能实现,只能现场马上录制并上传。
So,那么就考虑是从iPod的音乐库中导出音乐。
此处会用到一个类就是`MPMediaPickerController`来访问iPod Library.注意需要导入<MediaPlayer/MediaPlayer.h>并实现相应的代理另外在info.plist里面需要加入权限Privacy - Media Library Usage Description
简单初始化代码如下:
MPMediaPickerController *picker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeAnyAudio]; picker.prompt = @"请选择您需要上传的歌曲"; picker.showsCloudItems = YES; //是否显示下载项 picker.allowsPickingMultipleItems = NO; //是否多选 picker.delegate = self; [self presentViewController:picker animated:YES completion:nil];选择界面:
选中和取消代理回调:
#pragma mark MPMediaPickerControllerDelegate - (void)mediaPickerDidCancel:(MPMediaPickerController *)mediaPicker { [mediaPicker dismissViewControllerAnimated:YES completion:nil]; } - (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection { [mediaPicker dismissViewControllerAnimated:YES completion:nil]; MPMediaItem *item = mediaItemCollection.items.firstObject; [self convertToM4A:item]; NSLog(@"%@---%@-----", item.title, item.assetURL); }
选中回调集合里面放的是`MPMediaItem`对象。每一个此对象都表示了一首歌曲的信息,可以通过MPMediaEntity来访问其属性,具体可以查看.h文件。
值得一提的是其中有一个assetURL属性,格式类似于这样:ipod-library://item/item.wav?id=3524634042900602222
此属性可以直接用于AVPlayer播放该音频,但是如果要通过该URL访问音频数据,则是不能实现的。
要想获取到本地的音频文件,需要用到AVAssetExportSession将其导出。具体操作代码如下
- (void)convertToM4A: (MPMediaItem *)song { NSURL *url = [song valueForProperty:MPMediaItemPropertyAssetURL]; AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:url options:nil]; NSFileManager *fileManager = [NSFileManager defaultManager]; NSArray *dirs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectoryPath = [dirs objectAtIndex:0]; NSLog(@"%@", documentsDirectoryPath); NSLog (@"compatible presets for songAsset: %@",[AVAssetExportSession exportPresetsCompatibleWithAsset:songAsset]); NSArray *ar = [AVAssetExportSession exportPresetsCompatibleWithAsset: songAsset]; NSLog(@"%@", ar); AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset: songAsset presetName: AVAssetExportPresetAppleM4A]; NSLog (@"created exporter. supportedFileTypes: %@", exporter.supportedFileTypes); exporter.outputFileType = @"com.apple.m4a-audio"; NSString *exportFile = [documentsDirectoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.m4a",[song valueForProperty:MPMediaItemPropertyTitle]]]; NSError *error1; if([fileManager fileExistsAtPath:exportFile]) { [fileManager removeItemAtPath:exportFile error:&error1]; } NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager]enumeratorAtPath:documentsDirectoryPath]; for (NSString *fileName in enumerator) { NSLog(@"------%@", fileName); } NSURL* exportURL = [NSURL fileURLWithPath:exportFile]; exporter.outputURL = exportURL; // do the export [exporter exportAsynchronouslyWithCompletionHandler:^ { NSData *data1 = [NSData dataWithContentsOfFile:exportFile]; double size = (long)data1.length / 1024. / 1024.; NSString *title = song.title; if ([[title stringByReplacingOccurrencesOfString:@" " withString:@""] isEqualToString:@""]) { title = @"无名称音频"; } title = [title stringByAppendingString:[NSString stringWithFormat:@" %.2fM", size]]; dispatch_async(dispatch_get_main_queue(), ^{ self.audiolb.text = title; }); // NSLog(@"==================data1:%@",data1); int exportStatus = exporter.status; switch (exportStatus) { case AVAssetExportSessionStatusFailed: { // log error to text view NSError *exportError = exporter.error; NSLog (@"AVAssetExportSessionStatusFailed: %@", exportError); break; } case AVAssetExportSessionStatusCompleted: { NSLog (@"AVAssetExportSessionStatusCompleted"); break; } case AVAssetExportSessionStatusUnknown: { NSLog (@"AVAssetExportSessionStatusUnknown"); break; } case AVAssetExportSessionStatusExporting: { NSLog (@"AVAssetExportSessionStatusExporting"); break; } case AVAssetExportSessionStatusCancelled: { NSLog (@"AVAssetExportSessionStatusCancelled"); break; } case AVAssetExportSessionStatusWaiting: { NSLog (@"AVAssetExportSessionStatusWaiting"); break; } default: { NSLog (@"didn't get export status"); break; } } }]; }需注意在其他线程中操作UI时,应将UI操作用GCD放到主线程中。
视频选择其实用到的就是经常用的图片选择器,iOS中照片和摄像文件同样储存在相册中的,所有跟图片处理器的使用大同小异。
选择好UIImagePickerController的mediaTypes就好
UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { UIImagePickerController *picker = [[UIImagePickerController alloc] init]; picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; picker.mediaTypes = @[(NSString *)kUTTypeMovie]; picker.delegate = self; [self presentViewController:picker animated:YES completion:nil];
有一点非常好的是,选中视频文件之后,系统会自动为我们导出并压缩一份文件,返回的URL也可以直接访问到本地文件。另外可以用 MPMoviePlayerController对象来获取视频文件里的某一张图作为封面图。
#pragma mark UIImagePickerControllerDelegate - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { [picker dismissViewControllerAnimated:YES completion:nil]; } - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info { [picker dismissViewControllerAnimated:YES completion:nil]; NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType]; if([mediaType isEqualToString:@"public.movie"]) { NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL]; NSLog(@"found a video"); NSError *error = nil; NSData *data = [NSData dataWithContentsOfURL:videoURL options:NSDataReadingUncached error:&error]; if (!error) { double size = (long)data.length / 1024. / 1024.; self.vediolb.text = [NSString stringWithFormat:@"%.2fMB", size]; if (size > 30.0) { //文件过大 UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"视频文件不得大于30M" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *cancle = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil]; [alert addAction:cancle]; [self presentViewController:alert animated:YES completion:nil]; } else { //保存数据 //获取视频的thumbnail MPMoviePlayerController *player = [[MPMoviePlayerController alloc]initWithContentURL:videoURL] ; UIImage *thumbnail = [player thumbnailImageAtTime:0.01 timeOption:MPMovieTimeOptionNearestKeyFrame]; player = nil; self.vedioimage.image = thumbnail; } } } }
(欢迎随手给一颗星星哦~)本篇博客Demo地址https://github.com/xmy0010/DemoForCSDN (TyunMediaPickerDemo)
本人邮箱[email protected]欢迎小伙伴一起讨论,学习,进步。