实况图片其实就是一张封面图和一个.mov视频,它们是通过一个identifier来关联起来的。
/// 给图片文件写入live信息
/// @param photoURL 图片地址
/// @param outputFile 输出地址
/// @param identifier identifier => [[NSUUID UUID] UUIDString]
+ (BOOL)writeMetaDataByPath:(NSURL*)photoURL toPath:(NSString *)outputFile identify:(NSString *)identifier {
NSMutableData *data = [NSData dataWithContentsOfURL:photoURL].mutableCopy;
UIImage *image = [UIImage imageWithData:data];
CGImageRef imageRef = image.CGImage;
NSDictionary *imageMetadata = @{(NSString *)kCGImagePropertyMakerAppleDictionary : @{@"17" : identifier}};
CGImageDestinationRef dest = CGImageDestinationCreateWithData((CFMutableDataRef)data, kUTTypeJPEG, 1, nil);
CGImageDestinationAddImage(dest, imageRef, (CFDictionaryRef)imageMetadata);
CGImageDestinationFinalize(dest);
return [data writeToFile:outputFile atomically:YES];
}
// 成功block
typedef void(^VideoCompositionSuccess)(NSString *filePath);
// 失败block
typedef void(^VideoCompositionFail)(NSString *errorMsg);
/// 视频MP4转Mov,并写入identifier信息
/// @param sourcePath 视频源文件地址
/// @param outputPath 输出地址
/// @param identifier identifier => [[NSUUID UUID] UUIDString]
/// @param success 成功回调
/// @param fail 失败回调
- (void)mp4FileTransformToMovWithSourcePath:(NSString *)sourcePath outputPath:(NSString *)outputPath identifier:(NSString *)identifier success:(VideoCompositionSuccess)success fail:(VideoCompositionFail)fail {
NSURL *sourceUrl = [NSURL fileURLWithPath:sourcePath];
AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:sourceUrl options:nil];
NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset];
if ([compatiblePresets containsObject:AVAssetExportPresetHighestQuality]) {
_exportSession = [[AVAssetExportSession alloc] initWithAsset:avAsset presetName:AVAssetExportPresetHighestQuality];
AVMutableMetadataItem* item = [AVMutableMetadataItem metadataItem];
item.keySpace = AVMetadataKeySpaceQuickTimeMetadata;
item.key = AVMetadataQuickTimeMetadataKeyContentIdentifier;
item.value = identifier;
NSArray* metadata = [NSArray arrayWithObject:item];
_exportSession.metadata = metadata;
_exportSession.outputURL = [NSURL fileURLWithPath:outputPath];
_exportSession.outputFileType = @"com.apple.quicktime-movie";//AVFileTypeQuickTimeMovie;
_exportSession.shouldOptimizeForNetworkUse = YES;
//如有此文件则直接返回
if ([[NSFileManager defaultManager] fileExistsAtPath:outputPath]) {
if (success) {
success(outputPath);
}
return;
}
__block AVAssetExportSession *weakSession = _exportSession;
[_exportSession exportAsynchronouslyWithCompletionHandler:^(void) {
switch (weakSession.status) {
case AVAssetExportSessionStatusUnknown: {
break;
}
case AVAssetExportSessionStatusWaiting: {
break;
}
case AVAssetExportSessionStatusExporting: {
break;
}
case AVAssetExportSessionStatusCompleted: {
NSLog(@"mov file size:%lf MB",[NSData dataWithContentsOfURL:weakSession.outputURL].length/1024.f/1024.f);
NSData *da = [NSData dataWithContentsOfFile:outputPath];
NSLog(@"da:%lu",(unsigned long)da.length);
if (success) {
success(outputPath);
}
}
break;
case AVAssetExportSessionStatusFailed: {
if (fail) {
fail(@"视频格式转换出错");
}
}
break;
case AVAssetExportSessionStatusCancelled: {
if (fail) {
fail(weakSession.error.localizedDescription);
}
}
break;
}
}];
}
}
/// 把有live信息的图片和.mov视频保存到相册
#import <Photos/Photos.h>
NSURL *photo = [NSURL fileURLWithPath:finalCoverPath];
NSURL *video = [NSURL fileURLWithPath:finalVideoPath];
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAsset];
[request addResourceWithType:PHAssetResourceTypePhoto fileURL:photo options:nil];
[request addResourceWithType:PHAssetResourceTypePairedVideo fileURL:video options:nil];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
if (success) {
dispatch_async(dispatch_get_main_queue(), ^{
[BaseProgressHUD showMiddleInfoText:@"已保存到相册" inView:nil];
});
}else {
dispatch_async(dispatch_get_main_queue(), ^{
[BaseProgressHUD showMiddleInfoText:@"保存失败,请重试" inView:nil];
});
}}];
网友评论