如何检测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)

  1. 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

  2. 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.000000

  3. 2011-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.000000

  4. 2011-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

如果使用AVAssetImageGeneratorAVAssets生成图像,则可以简单地将.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的答案

UIImageOrientationUIImageOrientation相同

 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。