web-dev-qa-db-fra.com

Comment détecter si un fichier vidéo a été enregistré en orientation portrait ou paysage dans iOS

J'utilise AlAssetsGroup enumerateAssetsAtIndexes pour répertorier les actifs dans l'application Photos (Appareil photo). Pour un élément vidéo donné, je souhaite déterminer s'il a été tourné en mode portrait ou paysage.

Dans le code suivant, l'élément est une AlAsset et j'ai testé pour voir s'il s'agissait d'un élément vidéo [asset valueForProperty:ALAssetPropertyType] est AlAssetTypeVideo, puis:

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

Dans ce cas, orientation est toujours 0, ce qui est ALAssetOrientationUp. C’est peut-être à prévoir, toutes les vidéos sont en bon ordre, mais une vidéo portrait est représentée sous la forme MPEG-4 sous la forme d’une vidéo en mode paysage tournée à 90 degrés mac si tu ne me crois pas).

Où dans le fichier et/ou comment puis-je accéder aux informations qui me disent qu’elles ont été réellement enregistrées tout en maintenant le téléphone en mode portrait?

J'ai également essayé ceci, étant donné l'URL de l'actif:

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

Ce qui donne toujours une largeur> hauteur donc pour iPhone 4, largeur = 1280 hauteur = 720 et les valeurs de transformation a et d sont 1.0, les autres sont 0.0, quelle que soit l’orientation de la capture.

J'ai examiné les métadonnées à l'aide de l'application MediaInfo sur le Mac, j'ai réalisé un Hexdump et, jusqu'à présent, je n'ai trouvé aucune différence entre un paysage et une vidéo de portrait. Mais QuickTime connaît et affiche les vidéos portrait verticalement, et le téléphone sait en tournant une vidéo portrait si vous tenez le téléphone en orientation paysage lors de la lecture et l'affiche correctement s'il est tenu en portrait.

En passant, je ne peux pas utiliser ffmpeg (je ne peux pas vivre avec les restrictions de licence). Existe-t-il un moyen natif du SDK pour iPhone de procéder?

25
George C.

Quelqu'un sur les forums de développement Apple a suggéré d'obtenir la transformation de la piste vidéo, cela fait le travail. Vous pouvez voir dans les journaux ci-dessous que, pour ces orientations, les résultats ont du sens et que notre développeur Web est désormais en mesure de faire pivoter une variété de vids afin qu'ils correspondent et les composent en une seule vidéo.

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

Journalise avec 4 vidéos iPhone 4 avec la caméra normale: (1) caméra en paysage à droite (bouton principal à gauche) (2) paysage à gauche (3) portrait à l'envers (4) portrait en haut à droite (bouton principal en bas)

  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

18
George C.

Sur la base de la réponse précédente, vous pouvez utiliser les éléments suivants pour déterminer l'orientation de la vidéo:

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

Bien que plusieurs réponses soient correctes, elles ne sont pas exhaustives. Par exemple, vous devrez peut-être également savoir quel appareil photo a été utilisé pour appliquer les transformations appropriées. J'ai créé un Gist pour faire cette chose même; extraire les UIInterfaceOrientation et AVCaptureDevicePosition.

Extraction de l'orientation et de la position de la caméra AVAsset

2
dhallman

Dans mon cas d'utilisation, je n'avais besoin que de savoir si une vidéo est en portrait ou non (paysage).

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)

Cela a été testé avec les caméras avant et arrière pour toutes les possibilités d'orientation.

2

Si vous ne souhaitez pas utiliser AVFoundation Framework uniquement pour obtenir l'orientation de la vidéo enregistrée, essayez-le.

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

AVAssetImageGenerator

Si vous utilisez AVAssetImageGenerator pour générer des images à partir de AVAssets, vous pouvez simplement définir la propriété .appliesPreferredTrackTransform de AVAssetImageGenerator sur true et les images de votre actif vous seront renvoyées dans l'orientation correcte! :)


Swift 3

Mais pour prolonger la réponse de @ onmyway133 dans 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
        }
    }
}
1
cleverbit
- (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

Étendre la réponse de George dans Swift 2

UIInterfaceOrientation est la même chose que 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
    }
  }
}
0
onmyway133