web-dev-qa-db-ja.com

ビデオファイルが縦向きで記録されたか、iOSで横向きで記録されたかを検出する方法

写真(カメラ)アプリでアセットを一覧表示するためにAlAssetsGroup enumerateAssetsAtIndexesを使用しています。特定のビデオアセットについて、ポートレートモードとランドスケープモードのどちらで撮影されたかを判断したいと思います。

次のコードでは、アセットはAlAssetであり、動画アセットであるかどうかをテストしました[asset valueForProperty:ALAssetPropertyType]AlAssetTypeVideoの場合、次のようになります。

int orientation = [[asset valueForProperty:ALAssetPropertyOrientation] intValue];

この場合、orientationは常に0、つまりALAssetOrientationUpです。おそらくこれは予想されることですが、すべてのビデオは正しいですが、縦向きのビデオはMPEG-4で表されます。横向きのビデオは90度回転しています(つまり、すべてのビデオは実際には横向きです。あなたが私を信じていない場合は、Mac上のアプリ)。

ファイル内のどこにあるか、および/または電話を縦向きにしたまま実際に記録されたという情報にアクセスするにはどうすればよいですか?

アセットの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です。

MacのMediaInfoアプリを使用してメタデータを確認しました。Hexdumpを実行しましたが、これまでのところ、横長のビデオと縦長のビデオの間に違いはありません。しかし、QuickTimeは縦向きのビデオを認識して垂直に表示します。また、再生時に電話を横向きに保持している場合は縦向きのビデオを回転させ、縦向きに保持している場合は正しく表示することで電話を認識します。

ところで私はffmpegを使用できません(ライセンス制限に耐えられません)。これを行うためのiPhone SDKネイティブの方法はありますか?

28
George C.

Apple devフォーラムの誰かがビデオトラックの変換を取得することを提案しました。これでうまくいきます。以下のログから、これらの方向で結果が理にかなっており、Web開発者ができるようになったことがわかります。さまざまなvidを回転させ、すべて一致させて1つのビデオに合成します。

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

20
George C.

前の回答に基づいて、以下を使用してビデオの向きを決定できます。

+ (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;
}
40
George

AVAssetImageGenerator

AVAssetImageGeneratorを使用してAVAssetsから画像を生成する場合は、単に.appliesPreferredTrackTransformプロパティをAVAssetImageGeneratorからtrueに変更すると、アセットから画像が正しい向きで返されます。 :)


スウィフト3

しかし、@-onmyway133の回答を拡張するにはSwift

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
        }
    }
}
4
cleverbit

ここでの回答のいくつかは正しいですが、それらは包括的ではありません。たとえば、適切な変換を適用するために使用されたカメラデバイスを知る必要がある場合もあります。私はこれをまさに行うためにGistを作成しました。 UIInterfaceOrientationとAVCaptureDevicePositionを抽出します。

AVAssetの方向とカメラの位置を抽出

2
dhallman

私の使用例では、ビデオが縦向きか横向きかを知るだけで済みました。

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)

これは、すべての方向の可能性について、フロントカメラとリアカメラの両方でテストされています。

2

録画したビデオの向きを取得するためだけにAVFoundation Frameworkを使用したくない場合は、試してください

-(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];

}
2
Gyanendra Singh
- (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;
}
1
evya

Swift 2のジョージの答えを拡張する

UIInterfaceOrientationUIImageOrientationと同じです

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
    }
  }
}
0
onmyway133