如何检测video文件是以纵向方式录制还是在iOS中横向录制
我正在使用AlAssetsGroup enumerateAssetsAtIndexes
列出照片(相机)应用程序中的资产。 对于给定的video资源,我想确定它是以纵向还是横向模式拍摄的。
在下面的代码中,asset是一个AlAsset
,我已经testing过它是否是一个video资产[asset valueForProperty:ALAssetPropertyType]
是AlAssetTypeVideo
,那么:
int orientation = [[asset valueForProperty:ALAssetPropertyOrientation] intValue];
在这种情况下, orientation
始终为0,即ALAssetOrientationUp
。 也许这是所期望的,所有的video都是正确的,但是一个纵向video在MPEG-4中被表示为一个90度的横向video(即,所有的video实际上都是横向的,如果你没有在Mac上尝试MediaInfo应用相信我)。
在文件内部和/或如何访问信息,告诉我实际上是以纵向方向握住手机时录制的?
考虑到资产的url,我也尝试了这一点:
AVURLAsset *avAsset = [[AVURLAsset alloc] initWithURL:url options:nil]; CGSize size = [avAsset naturalSize]; NSLog(@"size.width = %f size.height = %f", size.width, size.height); CGAffineTransform txf = [avAsset preferredTransform]; NSLog(@"txf.a = %f txf.b = %f txf.c = %f txf.d = %f txf.tx = %f txf.ty = %f", txf.a, txf.b, txf.c, txf.d, txf.tx, txf.ty);
对于iPhone 4,宽度= 1280高度= 720,并且变换a和d值为1.0
,其他值为0.0
,而不pipe捕获方向如何,它总是会产生宽度>高度。
我已经在Mac上使用MediaInfo应用程序来查看元数据,我做了一个Hexdump,到目前为止还没有发现任何风景和肖像video之间的区别。 但是,QuickTime垂直识别并显示纵向video,如果在回放时横向握持手机,并通过纵向握持手机正确显示手机,则手机会旋转纵向video。
顺便说一句,我不能使用ffmpeg
(不能忍受许可限制)。 有没有一个iPhone SDK原生的方式来做到这一点?
根据以前的答案,您可以使用以下来确定video方向:
+ (UIInterfaceOrientation)orientationForTrack:(AVAsset *)asset { AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; CGSize size = [videoTrack naturalSize]; CGAffineTransform txf = [videoTrack preferredTransform]; if (size.width == txf.tx && size.height == txf.ty) return UIInterfaceOrientationLandscapeRight; else if (txf.tx == 0 && txf.ty == 0) return UIInterfaceOrientationLandscapeLeft; else if (txf.tx == 0 && txf.ty == size.width) return UIInterfaceOrientationPortraitUpsideDown; else return UIInterfaceOrientationPortrait; }
有人在苹果开发论坛build议获得video轨道的变换,这是工作。 您可以从下面的日志中看到,对于这些方向,结果是有意义的,我们的Web开发人员现在可以旋转各种vid,以便它们匹配并将它们合成为一个video。
AVAssetTrack* videoTrack = [[avAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; CGSize size = [videoTrack naturalSize]; NSLog(@"size.width = %f size.height = %f", size.width, size.height); CGAffineTransform txf = [videoTrack preferredTransform]; NSLog(@"txf.a = %f txf.b = %f txf.c = %f txf.d = %f txf.tx = %f txf.ty = %f", txf.a, txf.b, txf.c, txf.d, txf.tx, txf.ty);
使用4个iPhone 4video和普通摄像机录制日志:(1)右侧的风景摄像机(左侧的主页button)(2)左侧的横向(3)纵向的纵向(4)右侧的纵向(底部的主页button)
2011-01-07 20:07:30.024 MySecretApp [1442:307] size.width = 1280.000000 size.height = 720.000000 2011-01-07 20:07:30.027 MySecretApp [1442:307] txf.a = -1.000000 txf。 b = 0.000000 txf.c = 0.000000 txf.d = -1.000000 txf.tx = 1280.000000 txf.ty = 720.000000
2011-01-07 20:07:45.052 MySecretApp [1442:307] size.width = 1280.000000 size.height = 720.000000 2011-01-07 20:07:45.056 MySecretApp [1442:307] txf.a = 1.000000 txf.b = 0.000000 txf.c = 0.000000
txf.d = 1.000000 txf.tx = 0.000000
txf.ty = 0.0000002011-01-07 20:07:53.763 MySecretApp [1442:307] size.width = 1280.000000 size.height = 720.000000 2011-01-07 20:07:53.766 MySecretApp [1442:307] txf.a = 0.000000 txf.b = -1.000000 txf.c = 1.000000
txf.d = 0.000000 txf.tx = 0.000000 txf.ty = 1280.0000002011-01-07 20:08:03.490 MySecretApp [1442:307] size.width = 1280.000000 size.height = 720.000000 2011-01-07 20:08:03.493 MySecretApp [1442:307] txf.a = 0.000000 txf.b = 1.000000 txf.c = -1.000000
txf.d = 0.000000 txf.tx = 720.000000 txf.ty = 0.000000
如果您不想使用AVFoundation Framework来获取录制video的方向,那么就试试看
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo: (NSDictionary *)info { NSString *orientation; NSString *videoPath = [[info objectForKey:UIImagePickerControllerMediaURL] path]; NSURL *myURL = [[NSURL alloc] initFileURLWithPath:videoPath]; self.movieController = [[MPMoviePlayerController alloc] initWithContentURL:myURL]; UIImage *thumbImage = [movieController thumbnailImageAtTime:1.0 timeOption:MPMovieTimeOptionNearestKeyFrame]; float width = thumbImage.size.width; float height = thumbImage.size.height; if (width > height){ orientation = @"Landscape"; }else{ orientation = @"Portrait"; } [self dismissViewControllerAnimated:YES completion:nil]; }
虽然这里的几个答案是正确的,但并不全面。 例如,您可能还需要知道使用哪个摄像头设备来应用适当的变换。 我创造了一个要做这件事的要点; 提取UIInterfaceOrientation和AVCaptureDevicePosition。
提取AVAsset方向和相机位置
- (UIImageOrientation)getImageOrientationWithVideoOrientation:(UIInterfaceOrientation)videoOrientation { UIImageOrientation imageOrientation; switch (videoOrientation) { case UIInterfaceOrientationLandscapeLeft: imageOrientation = UIImageOrientationUp; break; case UIInterfaceOrientationLandscapeRight: imageOrientation = UIImageOrientationDown; break; case UIInterfaceOrientationPortrait: imageOrientation = UIImageOrientationRight; break; case UIInterfaceOrientationPortraitUpsideDown: imageOrientation = UIImageOrientationLeft; break; } return imageOrientation; }
AVAssetImageGenerator
如果使用AVAssetImageGenerator
从AVAssets
生成图像,则可以简单地将.appliesPreferredTrackTransform
属性设置为true
并以正确的方向从资产返回图像! 🙂
Swift 3
但是要延续@ onmyway133在Swift 3中的答案:
import UIKit import AVFoundation extension AVAsset { var g_size: CGSize { return tracks(withMediaType: AVMediaTypeVideo).first?.naturalSize ?? .zero } var g_orientation: UIInterfaceOrientation { guard let transform = tracks(withMediaType: AVMediaTypeVideo).first?.preferredTransform else { return .portrait } switch (transform.tx, transform.ty) { case (0, 0): return .landscapeRight case (g_size.width, g_size.height): return .landscapeLeft case (0, g_size.width): return .portraitUpsideDown default: return .portrait } } }
在Swift 2中扩展了George的答案
UIImageOrientation
与UIImageOrientation
相同
extension AVAsset { var g_size: CGSize { return tracksWithMediaType(AVMediaTypeVideo).first?.naturalSize ?? .zero } var g_orientation: UIInterfaceOrientation { guard let transform = tracksWithMediaType(AVMediaTypeVideo).first?.preferredTransform else { return .Portrait } switch (transform.tx, transform.ty) { case (0, 0): return .LandscapeRight case (g_size.width, g_size.height): return .LandscapeLeft case (0, g_size.width): return .PortraitUpsideDown default: return .Portrait } } }
在我的使用案例中,我只需要知道一个video是否是纵向的(横向)。
guard let videoTrack = AVAsset(url: videoURL).tracks(withMediaType: AVMediaTypeVideo).first else { return ... } let transformedVideoSize = videoTrack.naturalSize.applying(videoTrack.preferredTransform) let videoIsPortrait = abs(transformedVideoSize.width) < abs(transformedVideoSize.height)
这已经通过前置和后置摄像头的所有方向testing。