使用AVMutableVideoComposition导出时出现视频方向问题 [英] Video orientation issues when exporting with AVMutableVideoComposition

查看:380
本文介绍了使用AVMutableVideoComposition导出时出现视频方向问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是我用于导出视频的功能:

Here is the function I used to export video:

- (void) videoOutput
{
//1 - Early exit if there's no video file selected
if (!self.videoAsset) {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Please Load a Video Asset First"
                                                   delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];
    return;
}

// 2 - Create AVMutableComposition object. This object will hold your AVMutableCompositionTrack instances.
AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];

// 3 - Video track
AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
                                                                    preferredTrackID:kCMPersistentTrackID_Invalid];
[videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, self.videoAsset.duration)
                    ofTrack:[[self.videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]
                     atTime:kCMTimeZero error:nil];

// 3.1 - Create AVMutableVideoCompositionInstruction
AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, self.videoAsset.duration);

// 3.2 - Create an AVMutableVideoCompositionLayerInstruction for the video track and fix the orientation.
AVMutableVideoCompositionLayerInstruction *videolayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
AVAssetTrack *videoAssetTrack = [[self.videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

BOOL isVideoAssetPortrait_  = NO;
CGAffineTransform videoTransform = videoAssetTrack.preferredTransform;
if (videoTransform.a == 0 && videoTransform.b == 1.0 && videoTransform.c == -1.0 && videoTransform.d == 0) {
    isVideoAssetPortrait_ = YES;
}
if (videoTransform.a == 0 && videoTransform.b == -1.0 && videoTransform.c == 1.0 && videoTransform.d == 0) {

    isVideoAssetPortrait_ = YES;
}
if (videoTransform.a == 1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == 1.0) {
    isVideoAssetPortrait_  = NO;
}
if (videoTransform.a == -1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == -1.0) {
    isVideoAssetPortrait_  = NO;
}
[videolayerInstruction setTransform:videoAssetTrack.preferredTransform atTime:kCMTimeZero];
[videolayerInstruction setOpacity:0.0 atTime:self.videoAsset.duration];

// 3.3 - Add instructions
mainInstruction.layerInstructions = [NSArray arrayWithObjects:videolayerInstruction,nil];

AVMutableVideoComposition *mainCompositionInst = [AVMutableVideoComposition videoComposition];

CGSize naturalSize;
if(isVideoAssetPortrait_){
    naturalSize = CGSizeMake(videoAssetTrack.naturalSize.height, videoAssetTrack.naturalSize.width);
} else {
    naturalSize = videoAssetTrack.naturalSize;
}

mainCompositionInst.renderSize = naturalSize;
mainCompositionInst.instructions = [NSArray arrayWithObject:mainInstruction];
mainCompositionInst.frameDuration = CMTimeMake(1, 30);

// 4 - Get path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *myPathDocs =  [documentsDirectory stringByAppendingPathComponent:
                         [NSString stringWithFormat:@"FinalVideo-%d.mov",arc4random() % 1000]];
NSURL *url = [NSURL fileURLWithPath:myPathDocs];

// 5 - Create exporter
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition
                                                                  presetName:AVAssetExportPresetHighestQuality];
exporter.outputURL=url;
exporter.outputFileType = AVFileTypeQuickTimeMovie;
exporter.shouldOptimizeForNetworkUse = YES;
exporter.videoComposition = mainCompositionInst;
[exporter exportAsynchronouslyWithCompletionHandler:^{
    dispatch_async(dispatch_get_main_queue(), ^{
        [self exportDidFinish:exporter];
    });
}];
}

问题是我第一次使用此功能导出人像视频,变量 videoTransform(videoAssetTrack.preferredTransform)是:

The problem is that the first time I use this function to export a portrait video, the variable videoTransform (videoAssetTrack.preferredTransform) are:

videoTransform.a == 0 && videoTransform.b == 1.0 && videoTransform.c == -1.0 && videoTransform.d == 0

变量 isVideoAssetPortrait _ 等于。一切都是对的。但是,导出完成并保存到相机胶卷后,我使用此功能重新加载结果视频。这次, videoTransform 发生了变化:

And the variable isVideoAssetPortrait_ equals YES. Everything is right. However, after exporting completed and saved to Camera Roll, I used this function reload the result video. This time, the videoTransform changed:

videoTransform.a == 1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == 1.0

isVideoAssetPortrait _ 等于 NO 即可。这意味着一次导出后, videoTransform 更改了它的值(从纵向 - >横向方向)

And isVideoAssetPortrait_ equals NO. It means that after one time export, the videoTransform has changed it's values (orientation from portrait -> landscape)

我搜索了很多关于视频的问题AV基金会的方向,但尚未找到解决方案。

I googled many questions about video orientation of AV Foundation, but there hasn't found the solution yet.

感谢您阅读我的长篇解释。如果您有任何疑问,请告诉我。

Thank you for reading my long explanation. If you have any question, please let me know.

推荐答案

视频轨道没有纵向/横向等概念。它只是它的尺寸和应用的转换才能正确呈现它。默认情况下,肖像视频在摄像机生成时进行编码(比如横向渲染),90度旋转用于正确显示。

There is no such concept as portrait/landscape regarding the video tracks. It has just it's dimensions and a transformation applied in order to present it properly. By default the "portrait" video is encoded as it is produced by the camera (let say landscape) and a 90 degrees rotation used to present it properly.

当你导出它时,它的方向不会改变,它只是被物理旋转重新编码,所以不需要轮换来正确显示它。
这就是为什么你第二次得到单位矩阵(这并不意味着它从纵向变为横向),但这次它的自然大小也被交换了,一切都应该可以根据你的代码。

When you export it, it's orientation is not changed, it is just recoded physically rotated, so no rotation is needed to present it properly. This is why you get the identity matrix on the second time (it not means that it was changed from portrait to landscape), but this time the it's natural size is also swapped, and everything should be okay based on your code.

请在后面的情况下说明错误。

Please specify what's wrong in the later case.

这篇关于使用AVMutableVideoComposition导出时出现视频方向问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆