ios开发小技巧

iOS 上传相册视频

2018-06-01  本文已影响0人  路小白同学

最近在重构自己写的代码,项目中需要将相册中的视频上传到云服务器。做个总结。
使用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地址

上一篇下一篇

猜你喜欢

热点阅读