- (void)test:(NSURL *)videoUrl{
//videoUrl为什么视频的输入地址
NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:videoUrl options:options];
NSArray *array = [urlAsset tracksWithMediaType:AVMediaTypeVideo];
// 这个是视频输入源错误
if (!array.count)return;
// 输出的时候需要判断视频的角度是不是0(视频角度0度是 是home建在右边,视频横着拍摄的视频;角度是90度是home键在下面竖着拍摄的;180度是home键在左边横着拍摄的;270度是home键在上面,竖着拍摄) 根据自己的需来调整视频的角度,一般为了方便处理是需要输入视频的时候把角度调为0度
AVAssetTrack *videoTrack = [array firstObject];
// 视频输出
// AVAssetExportPresetMediumQuality高质量的 常用的如下
/**
1,固定分辨率预设属性
(1)AVAssetExportPreset640x480:设置视频分辨率640x480
(2)AVAssetExportPreset960x540:设置视频分辨率960x540
(3)AVAssetExportPreset1280x720:设置视频分辨率1280x720
(4)AVAssetExportPreset1920x1080:设置视频分辨率1920x1080
(5)AVAssetExportPreset3840x2160:设置视频分辨率3840x2160
2,相对质量预设属性
(1)AVAssetExportPresetLowQuality:低质量
(2)AVAssetExportPresetMediumQuality:中等质量
(3)AVAssetExportPresetHighestQuality:高质量
这种设置方式,最终生成的视频分辨率与具体的拍摄设备有关。比如 iPhone6 拍摄的视频:
使用AVAssetExportPresetHighestQuality则视频分辨率是1920x1080(不压缩)。
AVAssetExportPresetMediumQuality视频分辨率是568x320
AVAssetExportPresetLowQuality视频分辨率是224x128
**/
AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:urlAsset presetName:AVAssetExportPresetMediumQuality];
// 视频的输出地址
exportSession.outputURL = [NSURL fileURLWithPath:@"视频的输出路径"];
// 视频的输出格式
exportSession.outputFileType = AVFileTypeMPEG4;
// 这个一般设置为yes(指示输出文件应针对网络使用进行优化,例如QuickTime电影文件应支持“快速启动”)
exportSession.shouldOptimizeForNetworkUse = YES;
// 文件的最大多大的设置
exportSession.fileLengthLimit = 10 * 1024 * 1024;
// 视频角度校正
if ([self degressFromVideoFileWithAVAssetTrack:videoTrack] != 0){
// 修正角度
exportSession.videoComposition = [self fixedCompositionWithAsset:urlAsset];
}
[exportSession exportAsynchronouslyWithCompletionHandler:^{
if (exportSession.status == AVAssetExportSessionStatusCancelled){
} else if (exportSession.status == AVAssetExportSessionStatusFailed){
} else if (exportSession.status == AVAssetExportSessionStatusCompleted){
// 完成后的操作在这个里面执行 这里面不是主线程
}
}];
}
- (int)degressFromVideoFileWithAVAssetTrack:(AVAssetTrack *)videoTrack {
int degress = 0;
// 视频的transform
CGAffineTransform t = videoTrack.preferredTransform;
// 矩阵的abcd来判断视频的角度
if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0){
// Portrait
degress = 90;
} else if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0){
// PortraitUpsideDown
degress = 270;
} else if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0){
// LandscapeRight
degress = 0;
} else if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0){
// LandscapeLeft
degress = 180;
}
return degress;
}
// 处理视频角度
- (AVMutableVideoComposition *)fixedCompositionWithAsset:(AVAsset *)videoAsset {
// AVMutableVideoComposition 指示是否启用视频合成导出,并提供视频合成说明。导出预设为AVAssetExportPresetPassthrough时忽略
AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
// 视频转向
int degrees = [VideoCommonTools degressFromVideoFileWithAsset:videoAsset];
if (degrees != 0) {
CGAffineTransform translateToCenter;
CGAffineTransform mixedTransform;
videoComposition.frameDuration = CMTimeMake(1, 30);
NSArray *tracks = [videoAsset tracksWithMediaType:AVMediaTypeVideo];
if (!tracks.count)return nil;
AVAssetTrack *videoTrack = [tracks firstObject];
// 视频合成器的具体操作类
AVMutableVideoCompositionInstruction *roateInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
roateInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, [videoAsset duration]);
// 具体操作视频的大小角度的一个类
AVMutableVideoCompositionLayerInstruction *roateLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
if (degrees == 90) {
// 顺时针旋转90°
translateToCenter = CGAffineTransformMakeTranslation(videoTrack.naturalSize.height, 0.0);
mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI_2);
videoComposition.renderSize = CGSizeMake(videoTrack.naturalSize.height,videoTrack.naturalSize.width);
[roateLayerInstruction setTransform:mixedTransform atTime:kCMTimeZero];
} else if(degrees == 180){
// 顺时针旋转180°
translateToCenter = CGAffineTransformMakeTranslation(videoTrack.naturalSize.width, videoTrack.naturalSize.height);
mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI);
videoComposition.renderSize = CGSizeMake(videoTrack.naturalSize.width,videoTrack.naturalSize.height);
[roateLayerInstruction setTransform:mixedTransform atTime:kCMTimeZero];
} else if(degrees == 270){
// 顺时针旋转270°
translateToCenter = CGAffineTransformMakeTranslation(0.0, videoTrack.naturalSize.width);
mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI_2*3.0);
videoComposition.renderSize = CGSizeMake(videoTrack.naturalSize.height,videoTrack.naturalSize.width);
[roateLayerInstruction setTransform:mixedTransform atTime:kCMTimeZero];
}
roateInstruction.layerInstructions = @[roateLayerInstruction];
// 加入视频方向信息
videoComposition.instructions = @[roateInstruction];
}
return videoComposition;
}