写真(カメラ)アプリでアセットを一覧表示するために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ネイティブの方法はありますか?
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)縦向き右上(ホームボタンを下に)
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
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.0000002011-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.0000002011-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
前の回答に基づいて、以下を使用してビデオの向きを決定できます。
+ (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;
}
AVAssetImageGenerator
を使用してAVAssets
から画像を生成する場合は、単に.appliesPreferredTrackTransform
プロパティをAVAssetImageGenerator
からtrue
に変更すると、アセットから画像が正しい向きで返されます。 :)
しかし、@-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
}
}
}
ここでの回答のいくつかは正しいですが、それらは包括的ではありません。たとえば、適切な変換を適用するために使用されたカメラデバイスを知る必要がある場合もあります。私はこれをまさに行うためにGistを作成しました。 UIInterfaceOrientationとAVCaptureDevicePositionを抽出します。
私の使用例では、ビデオが縦向きか横向きかを知るだけで済みました。
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)
これは、すべての方向の可能性について、フロントカメラとリアカメラの両方でテストされています。
録画したビデオの向きを取得するためだけに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];
}
- (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;
}
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
}
}
}