Cómo detectar si un file de video se grabó en orientación vertical o horizontal en iOS

Estoy usando AlAssetsGroup enumerateAssetsAtIndexes para enumerar los activos en la aplicación Fotos (Cámara). Para un determinado recurso de video, quiero determinar si se grabó en modo vertical o horizontal.

En el siguiente código, el activo es un AlAsset y he probado para ver si es un activo de video [asset valueForProperty:ALAssetPropertyType] es AlAssetTypeVideo , luego:

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

En este caso, la orientation es siempre 0, que es ALAssetOrientationUp . Tal vez esto sea de esperar, todos los videos están correctos, pero un video retrato se representa en MPEG-4 como un video panorámico girado 90 grados (es decir, todos los videos son realmente panorámicos, testing la aplicación MediaInfo en la Mac si no lo haces créame).

¿Dónde dentro del file y / o cómo accedo a la información que me dice que en realidad se grabó mientras sostenía el teléfono en orientación vertical?

También he intentado esto, dada la URL del activo:

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

Que siempre produce un ancho> alto para iPhone 4, ancho = 1280 alto = 720 y los valores de transformación ay d son 1.0 , los otros son 0.0 , independientemente de la orientación de la captura.

Miré los metadatos usando la aplicación MediaInfo en Mac, hice un Hexdump y hasta ahora no he encontrado ninguna diferencia entre un video de paisaje y retrato. Pero QuickTime conoce y muestra verticalmente los videos retratos, y el teléfono sabe si gira un video retratado si mantiene el teléfono en orientación horizontal en la reproducción y lo visualiza correctamente si lo mantiene retratado.

Por cierto, no puedo usar ffmpeg (no puedo vivir con las restricciones de licencia). ¿Hay una forma nativa de iPhone SDK para hacer esto?

Según la respuesta anterior, puede usar lo siguiente para determinar la orientación del video:

 + (UIInterfaceOrientation)orientationForTrack:(AVAsset *)asset { AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; CGSize size = [videoTrack naturalSize]; CGAffineTransform txf = [videoTrack prefernetworkingTransform]; 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; } 

Alguien en los foros de Apple dev sugirió get la transformación de la pista de video, esto hace el trabajo. Puede ver en los loggings a continuación que, para estas orientaciones, los resultados tienen sentido y nuestro desarrollador web ahora puede rotar una variedad de videos para que todos los emparejen y los compongan en un solo 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 prefernetworkingTransform]; 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); 

Registros usando 4 videos de iPhone 4 con la camera normal: (1) camera horizontal en el lado derecho (button de inicio a la izquierda) (2) paisaje izquierdo (3) retrato al revés (4) retrato arriba a la derecha (button de inicio en la parte inferior)

  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

Si no desea utilizar AVFoundation Framework solo para get la orientación del video grabado, pruébelo

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

Si bien varias de las respuestas aquí son correctas, no son integrales. Por ejemplo, es posible que también necesite saber qué dispositivo de camera se utilizó para aplicar las transformaciones adecuadas. Creé una esencia para hacer esto mismo; extraiga el UIInterfaceOrientation y el AVCaptureDevicePosition.

Extraer la orientación de AVAsset y la position de la camera

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

Extendiendo la respuesta de George en Swift 2

UIInterfaceOrientation es lo mismo con UIImageOrientation

 extension AVAsset { var g_size: CGSize { return tracksWithMediaType(AVMediaTypeVideo).first?.naturalSize ?? .zero } var g_orientation: UIInterfaceOrientation { guard let transform = tracksWithMediaType(AVMediaTypeVideo).first?.prefernetworkingTransform 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 } } } 

AVAssetImageGenerator

Si está utilizando AVAssetImageGenerator para generar imágenes de AVAssets , simplemente puede establecer la propiedad AVAssetImageGenerator de AVAssetImageGenerator en true y le devolverá las imágenes de su activo en la orientación correcta. 🙂


Swift 3

Pero para extender la respuesta de @ onmyway133 en 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?.prefernetworkingTransform 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 } } } 

En mi caso de uso solo necesitaba saber si un video está en retrato o no (paisaje).

 guard let videoTrack = AVAsset(url: videoURL).tracks(withMediaType: AVMediaTypeVideo).first else { return ... } let transformedVideoSize = videoTrack.naturalSize.applying(videoTrack.prefernetworkingTransform) let videoIsPortrait = abs(transformedVideoSize.width) < abs(transformedVideoSize.height) 

Esto se ha probado con cameras delanteras y traseras para todas las posibilidades de orientación.