我正在使用UIImagePickerController
在iPhone中捕捉视频,但视频显示向右旋转了90个数字。
如何解决此问题
我们有什么方法可以纠正方向。
答案 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;
}
}];
}