如何检测视频文件是以纵向方式录制还是以横向方式录制在iOS中

Geo*_* C. 28 objective-c video-processing video-encoding ios

AlAssetsGroup enumerateAssetsAtIndexes用来列出照片(相机)应用程序中的资产.对于给定的视频资源,我想确定它是以纵向还是横向模式拍摄的.

在下面的代码,资产是一个AlAsset和我已经测试,看看它是否是一个视频资产[asset valueForProperty:ALAssetPropertyType]AlAssetTypeVideo,则:

int orientation = [[asset valueForProperty:ALAssetPropertyOrientation] intValue];
Run Code Online (Sandbox Code Playgroud)

在这种情况下orientation,总是0 ALAssetOrientationUp.也许这是预期的,所有视频都是正确的,但是纵向视频在MPEG-4中表示为90度旋转的景观视频(即所有视频实际上都是风景,如果不是,请尝试使用Mac上的MediaInfo应用程序相信我).

文件中的位置和/或如何在纵向握住手机时访问告诉我实际记录的信息?

考虑到资产的网址,我也尝试了这个:

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);
Run Code Online (Sandbox Code Playgroud)

这总是产生宽度>高度因此对于iPhone 4,宽度= 1280高度= 720并且变换a和d值是1.0,其他是0.0,无论捕获方向如何.

我在Mac上使用MediaInfo应用程序查看了元数据,我做了一个Hexdump,到目前为止还没有发现横向和纵向视频之间有任何区别.但是,QuickTime会垂直识别并显示纵向视频,如果您在播放时以横向方向握住手机并且如果以纵向方式握住手机正确显示,则手机会通过旋转纵向视频来了解.

BTW我不能使用ffmpeg(不能忍受许可限制).是否有iPhone SDK本机方式来执行此操作?

Geo*_*rge 41

根据上一个答案,您可以使用以下内容确定视频方向:

+ (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;
}
Run Code Online (Sandbox Code Playgroud)

  • 上面的注释返回了landscape的WRONG右/左UIInterfaceOrientation值.也许乔治P正在考虑UIDeviceOrientationLandscape*或正在根据一个模糊的文本回答"(1)右侧的风景凸轮(左侧的主页按钮)(2)从第一个答案离开的风景".正确的返回值是:if(size.width == txf.tx && size.height == txf.ty)返回UIInterfaceOrientationLandscapeLeft; else if(txf.tx == 0 && txf.ty == 0)返回UIInterfaceOrientationLandscapeRight; (3认同)

Geo*_* C. 21

苹果开发论坛上有人建议进行视频轨道的转换,这样就可以了.您可以从下面的日志中看到,对于这些方向,结果是有意义的,我们的Web开发人员现在能够旋转各种视频,以便它们全部匹配并将它们合成为一个视频.

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);
Run Code Online (Sandbox Code Playgroud)

使用普通凸轮使用4个iPhone 4视频记录:(1)右侧的横向凸轮(左侧的主页按钮)(2)横向左侧(3)纵向上下颠倒(4)纵向右侧(主页按钮位于底部)

  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

  • 是的,不推荐使用AVAsset的naturalSize.但是,AVAssetTrack的naturalSize不会被弃用.由于上面的代码使用AVAssetTrack,它应该没问题. (2认同)
  • 对我来说,无论视频开始录制的方向如何,都会返回相同的结果。可能出什么问题了? (2认同)

Mic*_*all 15

在我的用例中,我只需要知道视频是否为纵向(横向)。

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)
Run Code Online (Sandbox Code Playgroud)

这已经通过前后摄像头的所有方向可能性进行了测试。


cle*_*bit 8

AVAssetImageGenerator

如果您使用AVAssetImageGenerator从 生成图像AVAssets,您只需设置to的.appliesPreferredTrackTransform属性,它就会以正确的方向从您的资产中返回图像!:)AVAssetImageGeneratortrue


斯威夫特 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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)