如何在目标c中纠正视频的方向

时间:2013-12-05 14:06:08

标签: iphone objective-c video uiimagepickercontroller video-capture

我正在使用UIImagePickerController在iPhone中捕捉视频,但视频显示向右旋转了90个数字。

如何解决此问题

我们有什么方法可以纠正方向。

2 个答案:

答案 0 :(得分:4)

您需要使用AVExportSession对视频进行重新编码,以便将视频旋转到与Oleksiy Ivanov相同的方向。 所以你需要这样的东西:

NSError *error = nil;
AVURLAsset *videoAssetURL = [[AVURLAsset alloc] initWithURL:self.videoUrl options:nil]; 

AVMutableComposition *composition = [AVMutableComposition composition];
AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

AVAssetTrack *videoTrack = [[videoAssetURL tracksWithMediaType:AVMediaTypeVideo] firstObject];
AVAssetTrack *audioTrack = [[videoAssetURL tracksWithMediaType:AVMediaTypeAudio] firstObject];
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAssetURL.duration) ofTrack:videoTrack atTime:kCMTimeZero error:&error];
[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAssetURL.duration) ofTrack:audioTrack atTime:kCMTimeZero error:&error];

CGAffineTransform transformToApply = videoTrack.preferredTransform;
AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack];
[layerInstruction setTransform:transformToApply atTime:kCMTimeZero];
[layerInstruction setOpacity:0.0 atTime:videoAssetURL.duration];

AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
instruction.timeRange = CMTimeRangeMake( kCMTimeZero, videoAssetURL.duration);
instruction.layerInstructions = @[layerInstruction];

AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
videoComposition.instructions = @[instruction];
videoComposition.frameDuration = CMTimeMake(1, 30); //select the frames per second
videoComposition.renderScale = 1.0;
videoComposition.renderSize = CGSizeMake(640, 640); //select you video size

AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetMediumQuality];

exportSession.outputURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"videoname.MOV"]];
exportSession.outputFileType = AVFileTypeMPEG4; //very important select you video format (AVFileTypeQuickTimeMovie, AVFileTypeMPEG4, etc...)
exportSession.videoComposition = videoComposition;
exportSession.shouldOptimizeForNetworkUse = NO;
exportSession.timeRange = CMTimeRangeMake(kCMTimeZero, videoAssetURL.duration);

[exportSession exportAsynchronouslyWithCompletionHandler:^{

            switch ([exportSession status]) {

                case AVAssetExportSessionStatusCompleted: {

                    NSLog(@"Triming Completed");

                    //generate video thumbnail
                    self.videoUrl = exportSession.outputURL;
                    AVURLAsset *videoAssetURL = [[AVURLAsset alloc] initWithURL:self.videoUrl options:nil];
                    AVAssetImageGenerator *genrateAsset = [[AVAssetImageGenerator alloc] initWithAsset:videoAssetURL];
                    genrateAsset.appliesPreferredTrackTransform = YES;
                    CMTime time = CMTimeMakeWithSeconds(0.0,600);
                    NSError *error = nil;
                    CMTime actualTime;

                    CGImageRef cgImage = [genrateAsset copyCGImageAtTime:time actualTime:&actualTime error:&error];
                    self.videoImage = [[UIImage alloc] initWithCGImage:cgImage];
                    CGImageRelease(cgImage);

                    break;
                }
                default: {
                    break;
                }
            }
        }];

只需要为你改变self.videoUrl视频网址,它应该可以正常工作:)

答案 1 :(得分:1)

[编辑]编辑添加说明如何在设备上完成视频重新编码。

当使用UIImagePickerController录制视频时,它应该在视频文件中嵌入方向作为exif标志。视频本身是纵向的。当这样的视频在iPhone上播放时(或以其他方式进行exif轮换),视频应该正确定向。例如,播放视频的方式解释为http://mobile.tutsplus.com/tutorials/iphone/mediaplayer-framework_mpmovieplayercontroller_ios4/

如果以自定义方式播放视频,则应从视频中提取方向(例如,如此处所述https://stackoverflow.com/a/9195350/2546685)并在播放期间应用。

还可以使用AVExportSession重新编码视频,以便将视频旋转到正确的方向,并避免在播放期间使用exif标志。示例如何重新编码: 将此答案https://stackoverflow.com/a/16314552/2546685与此https://stackoverflow.com/a/9195350/2546685结合使用(我没有尝试编译,可能存在语法错误) - >

AVURLAsset *footageVideo = [AVURLAsset URLAssetWithURL:assetURL options:nil];
AVAssetTrack *footageVideoTrack = [footageVideo tracksWithMediaType:AVMediaTypeVideo][0];

CGAffineTransform t = footageVideoTrack.preferredTransform;

AVMutableComposition *composition = [AVMutableComposition composition];

AVMutableCompositionTrack *videoCompositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];

[videoCompositionTrack insertTimeRange:footageVideoTrack.timeRange ofTrack: footageVideoTrack atTime:CMTimeMakeWithSeconds(0, NSEC_PER_SEC) error:NULL];

NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:anAsset];
if ([compatiblePresets containsObject:AVAssetExportPresetMediumQuality]) {

self.exportSession = [[AVAssetExportSession alloc]
                      initWithAsset:composition presetName:AVAssetExportPresetMediumQuality];
// Implementation continues.

NSURL *furl = [NSURL fileURLWithPath:self.tmpVideoPath];

self.exportSession.outputURL = furl;
//provide outputFileType acording to video format extension
self.exportSession.outputFileType = AVFileTypeQuickTimeMovie;
self.exportSession.timeRange = footageVideoTrack.timeRange;

self.self.btnTrim.hidden = YES;
self.myActivityIndicator.hidden = NO;
[self.myActivityIndicator startAnimating];
[self.exportSession exportAsynchronouslyWithCompletionHandler:^{

    switch ([self.exportSession status]) {
        case AVAssetExportSessionStatusFailed:
            NSLog(@"Export failed: %@", [[self.exportSession error] localizedDescription]);
            break;
        case AVAssetExportSessionStatusCancelled:
            NSLog(@"Export canceled");
            break;
        default:
            NSLog(@"Triming Completed");
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.myActivityIndicator stopAnimating];
                self.myActivityIndicator.hidden = YES;
            });

            break;
    }
}];

}