csw*_*285 1 transform objective-c video-processing avfoundation ios
我正在努力改变视频的方向。它以纵向记录,然后以横向保存。更改变换只会使视频在横向视频中旋转。在这个带有 M_PI_2 的例子中,它消失了,因为它旋转了屏幕或平面。但是如果我把它改成 M_PI_2/2 或者它看起来是歪的。我知道 AVFoundation 默认情况下会这样做。我该如何改变?我从本教程中得到了很多这样的代码:https : //www.raywenderlich.com/30200/avfoundation-tutorial-adding-overlays-and-animations-to-videos 但使用 AVMutableVideoCompositionLayerInstruction 不起作用。
AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
preferredTrackID:kCMPersistentTrackID_Invalid];
CMTime insertTime = kCMTimeZero;
for(AVAsset *videoAsset in self.videoArray){
[videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:insertTime error:nil];
// Updating the insertTime for the next insert
insertTime = CMTimeAdd(insertTime, videoAsset.duration);
}
CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(M_PI_2);
videoTrack.preferredTransform = rotationTransform;
// 3.1 - Create AVMutableVideoCompositionInstruction
AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
mainInstruction.timeRange = videoTrack.timeRange;
// 3.2 - Create an AVMutableVideoCompositionLayerInstruction for the video track and fix the orientation.
AVMutableVideoCompositionLayerInstruction *videolayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
AVAssetTrack *videoAssetTrack = [[videoTrack.asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
UIImageOrientation videoAssetOrientation_ = UIImageOrientationUp;
BOOL isVideoAssetPortrait_ = NO;
CGAffineTransform videoTransform = videoAssetTrack.preferredTransform;
if (videoTransform.a == 0 && videoTransform.b == 1.0 && videoTransform.c == -1.0 && videoTransform.d == 0) {
videoAssetOrientation_ = UIImageOrientationRight;
isVideoAssetPortrait_ = YES;
}
if (videoTransform.a == 0 && videoTransform.b == -1.0 && videoTransform.c == 1.0 && videoTransform.d == 0) {
videoAssetOrientation_ = UIImageOrientationLeft;
isVideoAssetPortrait_ = YES;
}
if (videoTransform.a == 1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == 1.0) {
videoAssetOrientation_ = UIImageOrientationUp;
}
if (videoTransform.a == -1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == -1.0) {
videoAssetOrientation_ = UIImageOrientationDown;
}
//CGAffineTransform rotationTransform = videoAssetTrack.preferredTransform;
[videolayerInstruction setTransform:videoAssetTrack.preferredTransform atTime:kCMTimeZero];
[videolayerInstruction setOpacity:0.0 atTime:videoTrack.timeRange.duration];
Run Code Online (Sandbox Code Playgroud)
有没有办法设置锚点或进行我自己的变换?
查看https://developer.apple.com/library/content/qa/qa1744/_index.html,这是使用 AVFoundation 设置视频方向的官方解释。简单地说,您需要使用 AVMutableVideoCompositionLayerInstruction 对象来修改变换以应用于视频合成中的给定轨道。
然后让我们谈谈您应该应用的转换。有很多人建议使用 AVAssetTrack 的 preferredTransform。在大多数情况下,它是有效的,您应该使用它来获取 assetTrack 的视频方向。但有时 preferredTransform 可能缺少 tx(ty) 的值(如果您不知道 tx(ty) 是什么,则应查看 Apple API 参考中的 CGAffineTransform)或 tx(ty) 的值不准确,从而导致视频定位错误。
所以主要思想是:使用preferredTransform来确定原始视频方向并进行自己的变换。
这是获取轨道方向的代码:
- (UIInterfaceOrientation)orientationForTrack:(AVAsset *)asset {
UIInterfaceOrientation orientation = UIInterfaceOrientationPortrait;
NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
if([tracks count] > 0) {
AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
CGAffineTransform t = videoTrack.preferredTransform;
// Portrait
if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0) {
orientation = UIInterfaceOrientationPortrait;
}
// PortraitUpsideDown
if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0) {
orientation = UIInterfaceOrientationPortraitUpsideDown;
}
// LandscapeRight
if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0) {
orientation = UIInterfaceOrientationLandscapeRight;
}
// LandscapeLeft
if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0) {
orientation = UIInterfaceOrientationLandscapeLeft;
}
}
return orientation;
}
Run Code Online (Sandbox Code Playgroud)
以及用于获取所需转换以应用的代码:
- (CGAffineTransform)transformBasedOnAsset:(AVAsset *)asset {
UIInterfaceOrientation orientation = [AVUtilities orientationForTrack:asset];
AVAssetTrack *assetTrack = [asset tracksWithMediaType:AVMediaTypeVideo][0];
CGSize naturalSize = assetTrack.naturalSize;
CGAffineTransform finalTranform;
switch (orientation) {
case UIInterfaceOrientationLandscapeLeft:
finalTranform = CGAffineTransformMake(-1, 0, 0, -1, naturalSize.width, naturalSize.height);
break;
case UIInterfaceOrientationLandscapeRight:
finalTranform = CGAffineTransformMake(1, 0, 0, 1, 0, 0);
break;
case UIInterfaceOrientationPortrait:
finalTranform = CGAffineTransformMake(0, 1, -1, 0, naturalSize.height, 0);
break;
case UIInterfaceOrientationPortraitUpsideDown:
finalTranform = CGAffineTransformMake(0, -1, 1, 0, 0, naturalSize.width);
break;
default:
break;
}
return finalTranform;
}
Run Code Online (Sandbox Code Playgroud)
如果您感到困惑,我建议您先拍摄不同方向的视频,然后使用 NSStringFromCGAffineTransform() 或其他方法打印出视频的 preferredTransform 以查看详细信息。
| 归档时间: |
|
| 查看次数: |
393 次 |
| 最近记录: |