iOS 上传相册视频

最近在重构自己写的代码,项目中需要将相册中的视频上传到云服务器。做个总结。
使用UIImagePickerController获取相册的视频,研究发现,获取后的视频是经过压缩的,经测试如果一个3M的视频经过压缩后会变成1.3M.如果你们服务器需要的正是经过压缩的,那么恭喜你,不用走那么多弯路了。我这边恰好需要的是不经过压缩的视频,然后网上找了很多方法,发现要获取相册中的视频是必须经过压缩的(如果你有获取相册原生视频的方法请在下方留言告诉我,万分感谢!),既然不让获取原生的,那么只能退而求其次, ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibraryshi;(这个方法呢有个问题,就是如果视频的分辨率小于手机的分辨率,视频会变大,一般3M会变成10.3M,有多大自己体会~)设置视频的导出质量为高质量。

 UIImagePickerController *ipc=[[UIImagePickerController alloc] init];
        ipc=[[UIImagePickerController alloc] init];
        ipc.delegate=self;
        ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        ipc.videoQuality = UIImagePickerControllerQualityTypeMedium;
        ipc.mediaTypes = [NSArray arrayWithObjects:@"public.movie", nil];

一般呢,我们会在didFinishPickingMediaWithInfo代理方法中获取视频路径。
这个时候我们得出的是临时路径,不能是指作为视频路径直接上传,我再模拟器下截取了这个临时路径,如图:


temp.jpeg

我们需要把原视频导出到自己的APP内,而后根据这个路径进行上传即可。
导出的方法也有两种:
一是根据路径直接拷贝,二是进行视频导出,第二中方式可以对视频进行进一步压缩。可以根据自己的项目需求选择。
代码如下(ViewController页面全部代码):


#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface ViewController ()<UIImagePickerControllerDelegate,UINavigationControllerDelegate,UITextViewDelegate>
@property (weak, nonatomic) IBOutlet UIImageView *videoImageView;
@property (weak, nonatomic) IBOutlet UILabel *videoMessageLabel;
@property (nonatomic,assign)BOOL isImagePicker;
@property (nonatomic,strong)NSString *filePath;
@property (nonatomic,strong)NSString *imagePath;
@property (nonatomic,strong)NSString *pingUploadUrlString;
@property (nonatomic,assign)NSInteger timeSecond;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    NSLog(@"%@",NSHomeDirectory());
}
- (IBAction)getVideo:(UIButton *)sender
{
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary])
    {
        UIImagePickerController *ipc=[[UIImagePickerController alloc] init];
        ipc=[[UIImagePickerController alloc] init];
        ipc.delegate=self;
        ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        ipc.videoQuality = UIImagePickerControllerQualityTypeMedium;
        ipc.mediaTypes = [NSArray arrayWithObjects:@"public.movie", nil];
        [self presentViewController:ipc animated:YES completion:nil];
        _isImagePicker = YES;
    }
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
    if ([mediaType isEqualToString:@"public.movie"])
    {
        NSURL *videoUrl = [info objectForKey:UIImagePickerControllerMediaURL];
        AVURLAsset *asset = [AVURLAsset assetWithURL:videoUrl];
        NSString  *videoPath =  info[UIImagePickerControllerMediaURL];
        
        NSLog(@"相册视频路径是:%@",videoPath);
        
        
        //第一中方法,通过路径直接copy
        
//        //删除原来的 防止重复选
//                [[NSFileManager defaultManager] removeItemAtPath:_filePath error:nil];
//                [[NSFileManager defaultManager] removeItemAtPath:_imagePath error:nil];
//                NSDateFormatter *formater = [[NSDateFormatter alloc] init];
//                [formater setDateFormat:@"yy-MM-dd-HH:mm:ss"];
//
//                _filePath = [NSHomeDirectory() stringByAppendingFormat:@"/Documents/%@", [[formater stringFromDate:[NSDate date]] stringByAppendingString:@".mp4"]];
//
//
//                NSString  *videoPath =  info[UIImagePickerControllerMediaURL];
//
//                NSFileManager *fileManager = [NSFileManager defaultManager];
//
//                NSError *error;
//                [fileManager copyItemAtPath:videoPath toPath:_filePath error:&error];
//                if (error)
//                {
//
//                    NSLog(@"文件保存到缓存失败");
//                }
//
//                [self getSomeMessageWithFilePath:_filePath];
        
        
        //第二种方法,进行视频导出
                [self startExportVideoWithVideoAsset:asset completion:^(NSString *outputPath) {
        
                    [self getSomeMessageWithFilePath:_filePath];
        
                }];;
        
        
        
    }
    _isImagePicker = NO;
    [picker dismissViewControllerAnimated:YES completion:nil];
}
//获取视频第一帧
- (void)getSomeMessageWithFilePath:(NSString *)filePath
{
    
    
    NSURL *fileUrl = [NSURL fileURLWithPath:filePath];
    
    AVURLAsset *asset = [AVURLAsset assetWithURL:fileUrl];
    
    
    NSString *duration = [NSString stringWithFormat:@"%0.0f", ceil(CMTimeGetSeconds(asset.duration))];
    _videoImageView.image = [self getImageWithAsset:asset];
//    _image = _imageView.image;
    _timeSecond = duration.integerValue;
    _videoMessageLabel.text = [NSString stringWithFormat:@"时长是:%ld",(long)_timeSecond];
    NSLog(@"时长是:%@",duration);
}

- (UIImage *)getImageWithAsset:(AVAsset *)asset
{
    AVURLAsset *assetUrl = (AVURLAsset *)asset;
    NSParameterAssert(assetUrl);
    AVAssetImageGenerator *assetImageGenerator =[[AVAssetImageGenerator alloc] initWithAsset:assetUrl];
    assetImageGenerator.appliesPreferredTrackTransform = YES;
    assetImageGenerator.apertureMode = AVAssetImageGeneratorApertureModeEncodedPixels;
    
    CGImageRef thumbnailImageRef = NULL;
    CFTimeInterval thumbnailImageTime = 0;
    NSError *thumbnailImageGenerationError = nil;
    thumbnailImageRef = [assetImageGenerator copyCGImageAtTime:CMTimeMake(thumbnailImageTime, 60)actualTime:NULL error:&thumbnailImageGenerationError];
    
    if(!thumbnailImageRef)
        NSLog(@"thumbnailImageGenerationError %@",thumbnailImageGenerationError);
    
    UIImage *thumbnailImage = thumbnailImageRef ? [[UIImage alloc]initWithCGImage: thumbnailImageRef] : nil;
    
    return thumbnailImage;
}

- (void)startExportVideoWithVideoAsset:(AVURLAsset *)videoAsset completion:(void (^)(NSString *outputPath))completion
{
    // Find compatible presets by video asset.
    NSArray *presets = [AVAssetExportSession exportPresetsCompatibleWithAsset:videoAsset];
    
    NSString *pre = nil;
    
    if ([presets containsObject:AVAssetExportPreset3840x2160])
    {
        pre = AVAssetExportPreset3840x2160;
    }
    else if([presets containsObject:AVAssetExportPreset1920x1080])
    {
        pre = AVAssetExportPreset1920x1080;
    }
    else if([presets containsObject:AVAssetExportPreset1280x720])
    {
        pre = AVAssetExportPreset1280x720;
    }
    else if([presets containsObject:AVAssetExportPreset960x540])
    {
        pre = AVAssetExportPreset1280x720;
    }
    else
    {
        pre = AVAssetExportPreset640x480;
    }
    
    // Begin to compress video
    // Now we just compress to low resolution if it supports
    // If you need to upload to the server, but server does't support to upload by streaming,
    // You can compress the resolution to lower. Or you can support more higher resolution.
    if ([presets containsObject:AVAssetExportPreset640x480]) {
        //        AVAssetExportSession *session = [[AVAssetExportSession alloc]initWithAsset:videoAsset presetName:AVAssetExportPreset640x480];
        AVAssetExportSession *session = [[AVAssetExportSession alloc]initWithAsset:videoAsset presetName:AVAssetExportPreset640x480];
        
        NSDateFormatter *formater = [[NSDateFormatter alloc] init];
        [formater setDateFormat:@"yy-MM-dd-HH:mm:ss"];
        
        NSString *outputPath = [NSHomeDirectory() stringByAppendingFormat:@"/Documents/%@", [[formater stringFromDate:[NSDate date]] stringByAppendingString:@".mov"]];
        NSLog(@"video outputPath = %@",outputPath);
        //删除原来的 防止重复选
        _timeSecond = 0;
        [[NSFileManager defaultManager] removeItemAtPath:_filePath error:nil];
        [[NSFileManager defaultManager] removeItemAtPath:_imagePath error:nil];
        
        _filePath = outputPath;
        session.outputURL = [NSURL fileURLWithPath:outputPath];
        
        // Optimize for network use.
        session.shouldOptimizeForNetworkUse = true;
        
        NSArray *supportedTypeArray = session.supportedFileTypes;
        if ([supportedTypeArray containsObject:AVFileTypeMPEG4]) {
            session.outputFileType = AVFileTypeMPEG4;
        } else if (supportedTypeArray.count == 0) {
            NSLog(@"No supported file types 视频类型暂不支持导出");
            return;
        } else {
            session.outputFileType = [supportedTypeArray objectAtIndex:0];
        }
        
        if (![[NSFileManager defaultManager] fileExistsAtPath:[NSHomeDirectory() stringByAppendingFormat:@"/Documents"]]) {
            [[NSFileManager defaultManager] createDirectoryAtPath:[NSHomeDirectory() stringByAppendingFormat:@"/Documents"] withIntermediateDirectories:YES attributes:nil error:nil];
        }
        
        if ([[NSFileManager defaultManager] fileExistsAtPath:outputPath]) {
            [[NSFileManager defaultManager] removeItemAtPath:outputPath error:nil];
        }
        
        // Begin to export video to the output path asynchronously.
        [session exportAsynchronouslyWithCompletionHandler:^(void) {
            switch (session.status) {
                case AVAssetExportSessionStatusUnknown:
                    NSLog(@"AVAssetExportSessionStatusUnknown"); break;
                case AVAssetExportSessionStatusWaiting:
                    NSLog(@"AVAssetExportSessionStatusWaiting"); break;
                case AVAssetExportSessionStatusExporting:
                    NSLog(@"AVAssetExportSessionStatusExporting"); break;
                case AVAssetExportSessionStatusCompleted: {
                    NSLog(@"AVAssetExportSessionStatusCompleted");
                    dispatch_async(dispatch_get_main_queue(), ^{
                        if (completion) {
                            completion(outputPath);
                        }
                        //                        _videoArray = [VRVideoTool getAllFileNameFormDoucuments];
                        //                        [_tableView reloadData];
                        
                    });
                }  break;
                case AVAssetExportSessionStatusFailed:
                    NSLog(@"AVAssetExportSessionStatusFailed"); break;
                default: break;
            }
        }];
    }
}


@end

获取视频第一帧图片的原理是通过视频路径获取视频的AVURLAsset,通过对AVURLAsset进行处理可以获得视频的一些信息,例如时长,第一帧图片等。上面代码里面有,不再赘述。
如果你有更好的获取相册视频的方法,请在下方留言告知~~。
DEMO地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容