Get orientation from video or thumb obtained with AVAssetImageGenerator

4.4k Views Asked by At

In my application I create videos from single images. Everything works fine, videos are assembled correctly with right size and orientation. They are displayed correctly both in the Apple photo app, from MPMoviePlayer and from the sandbox directory where I save them.
The problem arise when I try to get a thumb from a movie. The orientation is not correct and I don't know how to fix, I've seen that there is a -preferredTransform property but the result is the the same for both landscape and portrait videos.
The url I'm using is the sandbox directory path. Here is the snippet:

- (void) setVideoPath:(NSString *)videoPath {
    if (videoPath ==_videoPath) {
        return;
    }
    _videoPath = videoPath;
    AVAsset *asset = [AVAsset assetWithURL:[NSURL fileURLWithPath:_videoPath]];
    AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]initWithAsset:asset];
    CMTime time = CMTimeMake(1, 1);
    CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL];
    UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);  
    self.videoImageView.image = thumbnail;
}
4

There are 4 best solutions below

0
On BEST ANSWER

Just use this, No need to write any methods

generator.appliesPreferredTrackTransform=true
0
On

For the moment I've found a trick, find the video rotation and apply to the thumbnail. It seems to work but I'm pretty sure there is another way around. The solution is taken from this gist, credits to Luca Bernardi.

{
//..
        NSArray *videoTracks = [asset tracksWithMediaType:AVMediaTypeVideo];
        AVAssetTrack* videoTrack    = [videoTracks firstObject];
        CGAffineTransform txf       = [videoTrack preferredTransform];        
        if (txf.a == 0 && txf.b == 1.0 && txf.c == -1.0 && txf.d == 0) {
            thumbOrientation = UIImageOrientationRight;
        }
        if (txf.a == 0 && txf.b == -1.0 && txf.c == 1.0 && txf.d == 0) {
            thumbOrientation =  UIImageOrientationLeft;
        }
        if (txf.a == 1.0 && txf.b == 0 && txf.c == 0 && txf.d == 1.0) {
            thumbOrientation =  UIImageOrientationUp;
        }
        if (txf.a == -1.0 && txf.b == 0 && txf.c == 0 && txf.d == -1.0) {
            thumbOrientation = UIImageOrientationDown;
        }
        UIImage *thumbnail = [UIImage imageWithCGImage:imageRef scale:[[UIScreen mainScreen]scale] orientation:thumbOrientation];
//..
}
0
On
-(UIImage *)generateThumbImage : (NSURL *)url
{
     AVAsset *asset = [AVAsset assetWithURL:url];
     AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]initWithAsset:asset];
     imageGenerator.appliesPreferredTrackTransform = YES;
     CMTime time = [asset duration];
     time.value = 0;
     CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL];
     UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
     CGImageRelease(imageRef);  // CGImageRef won't be released by ARC
     return thumbnail;
}

Where url is video url.

0
On

SWIFT version

            // generate thumb from video and set it
        var err: NSError? = nil
        let asset = AVURLAsset(URL: NSURL(fileURLWithPath: videoPath! as String), options: nil)
        let imgGenerator = AVAssetImageGenerator(asset: asset)
        imgGenerator.appliesPreferredTrackTransform = true
        let cgImage: CGImage!
        do {
            cgImage = try imgGenerator.copyCGImageAtTime(CMTimeMake(0, 60), actualTime: nil)
            let thumbnail = UIImage(CGImage: cgImage)
        } catch let error as NSError {
            err = error
            cgImage = nil
        }

Most important line for orientation:

imgGenerator.appliesPreferredTrackTransform = true