ios 视频处理详解一(视频导出)

- (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;
}

 

你可能感兴趣的:(OC)