Как определить, был ли видеофайл записан в книжной или альбомной ориентации в iOS - PullRequest
27 голосов
/ 07 января 2011

Я использую AlAssetsGroup enumerateAssetsAtIndexes для перечисления активов в приложении Фото (Камера).Для данного видео актива я хочу определить, был ли он снят в портретном или ландшафтном режиме.

В следующем коде актив - это AlAsset, и я проверил, является ли он активом видео [asset valueForProperty:ALAssetPropertyType] - это AlAssetTypeVideo, тогда:

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

В этомcase orientation всегда равно 0, что ALAssetOrientationUp.Возможно, этого и следовало ожидать, все видео работают правильно, но портретное видео представлено в MPEG-4 как альбомное видео, повернутое на 90 градусов (т.е. все видео на самом деле в альбомной ориентации, попробуйте приложение MediaInfo на 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);

, который всегда дает width> height, то есть для iPhone 4, width = 1280 height = 720, а значения a и d преобразования равны 1.0, остальные 0.0, независимоориентации захвата.

Я просмотрел метаданные с помощью приложения MediaInfo на Mac, сделал Hexdump и до сих пор не нашел различий между альбомным и портретным видео.Но QuickTime знает и отображает портретные видео по вертикали, и телефон знает, поворачивая портретное видео, если вы держите телефон в альбомной ориентации при воспроизведении и правильно отображаете его, если держите его в портретном режиме.используйте ffmpeg (не может жить с лицензионными ограничениями).Есть ли в iPhone SDK родной способ сделать это?

Ответы [ 8 ]

40 голосов
/ 18 мая 2011

На основании предыдущего ответа вы можете использовать следующее для определения ориентации видео:

+ (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;
}
20 голосов
/ 13 января 2011

Кто-то на форумах разработчиков Apple предложил получить преобразование видео-трека, это делает работу. Из журналов ниже видно, что для этих ориентаций результаты имеют смысл, и наш веб-разработчик теперь может поворачивать различные видеоролики, чтобы они все совпали и объединили их в одно видео.

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

4 голосов
/ 20 сентября 2016

AVAssetImageGenerator

Если вы используете AVAssetImageGenerator для создания изображений из AVAssets, вы можете просто установить свойство .appliesPreferredTrackTransform для AVAssetImageGenerator в 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
        }
    }
}
2 голосов
/ 02 марта 2017

В моем случае мне нужно было только знать, видео в портретной ориентации или нет (альбомная).

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 голосов
/ 29 октября 2015

Хотя некоторые ответы здесь верны, они не являются исчерпывающими. Например, вам также может понадобиться узнать, какое устройство камеры использовалось для применения правильных преобразований. Я создал суть, чтобы сделать эту самую вещь; извлечь UIInterfaceOrientation и AVCaptureDevicePosition.

Извлечение ориентации AVAsset и положения камеры

2 голосов
/ 14 февраля 2013

Если вы не хотите использовать 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];

}
1 голос
/ 13 ноября 2013
- (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;
}
0 голосов
/ 08 сентября 2016

Распространение ответа Джорджа в Swift 2

UIInterfaceOrientation то же самое с 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
    }
  }
}
...