Getting a thumbnail of a *.mov video IOS

。_饼干妹妹 提交于 2019-12-17 17:52:26

问题


I want to get a thumbnail of videos (*.mov) which taken with iPhone/iPAD. I am trying to use AVFoundation library for this and getting this error:

couldn't generate thumbnail, error:Error Domain=AVFoundationErrorDomain Code=-11822 "Cannot Open" UserInfo=0x15d90a30 {NSLocalizedDescription=Cannot Open, NSLocalizedFailureReason=This media format is not supported.}

Code:

NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDir=[paths objectAtIndex:0];
NSString *videoPath=[documentDir stringByAppendingPathComponent:[NSString stringWithFormat:@"videos/%@.mov",videoName]];


    AVURLAsset *asset=[[AVURLAsset alloc] initWithURL:videoPath options:nil];
    AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    generator.appliesPreferredTrackTransform=TRUE;

    CMTime thumbTime = CMTimeMakeWithSeconds(0,30);

    AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error){
        if (result != AVAssetImageGeneratorSucceeded) {
            NSLog(@"couldn't generate thumbnail, error:%@", error);
        }
        self.img.image=[UIImage imageWithCGImage:im];
    };

    CGSize maxSize = CGSizeMake(320, 180);
    generator.maximumSize = maxSize;
    [generator generateCGImagesAsynchronouslyForTimes:[NSArray arrayWithObject:[NSValue valueWithCMTime:thumbTime]] completionHandler:handler];

I recorded videos with my app and want to show a thumbnail of them.


回答1:


Here it is... (Picked up from this link- Getting video snapshot for thumbnail)

- (UIImage *)thumbnailImageFromURL:(NSURL *)videoURL {
    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL: videoURL options:nil];
    AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    NSError *err = NULL;
    CMTime requestedTime = CMTimeMake(1, 60);     // To create thumbnail image
    CGImageRef imgRef = [generator copyCGImageAtTime:requestedTime actualTime:NULL error:&err];
    NSLog(@"err = %@, imageRef = %@", err, imgRef);

    UIImage *thumbnailImage = [[UIImage alloc] initWithCGImage:imgRef];
    CGImageRelease(imgRef);    // MUST release explicitly to avoid memory leak

    return thumbnailImage;
}



回答2:


I don't have enough reputation to comment but the example above is missing CGImageRelease(imageRef)...

The final methode should look like:

- (UIImage*)loadImage {

    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:vidURL options:nil];
    AVAssetImageGenerator *generate = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    NSError *err = NULL;
    CMTime time = CMTimeMake(1, 60);
    //Grab image
    CGImageRef imgRef = [generate copyCGImageAtTime:time actualTime:NULL error:&err];
    NSLog(@"err==%@, imageRef==%@", err, imgRef);

    UIImage* finalImage = [[UIImage alloc] initWithCGImage:imgRef];
    CGImageRelease(imageRef);
    return finalImage;
}

Took me while to realize... So maybe it will help somebody.




回答3:


You can generate in swift in two ways 1. AVAssetImageGenerator 2. MPMoviePlayerController

1. 

    func generateThumnail(url : NSURL) -> UIImage{
            var asset : AVAsset = AVAsset.assetWithURL(url) as AVAsset
            var assetImgGenerate : AVAssetImageGenerator = AVAssetImageGenerator(asset: asset)
            assetImgGenerate.appliesPreferredTrackTransform = true
            var error       : NSError? = nil
            var time        : CMTime = CMTimeMake(1, 30)
            var img         : CGImageRef = assetImgGenerate.copyCGImageAtTime(time, actualTime: nil, error: &error)
            var frameImg    : UIImage = UIImage(CGImage: img)!

            return frameImg
        }

2. 

    override func viewDidLoad() {
            super.viewDidLoad()
            var moviePlayer         : MPMoviePlayerController!  = MPMoviePlayerController(contentURL: moviePlayManager.movieURL)
            moviePlayer.view.frame   = CGRect(x: self.view.frame.origin.x, y: self.view.frame.origin.y, width:
                                       self.view.frame.size.width, height: self.view.frame.height)
            moviePlayer.fullscreen   = true
            moviePlayer.controlStyle = MPMovieControlStyle.None
            NSNotificationCenter.defaultCenter().addObserver(self,
        selector: "videoThumbnailIsAvailable:",
        name: MPMoviePlayerThumbnailImageRequestDidFinishNotification,
        object: nil)


        let thumbnailTimes = 3.0
        moviePlayer.requestThumbnailImagesAtTimes([thumbnailTimes],
                timeOption: .NearestKeyFrame)
        }

    func videoThumbnailIsAvailable(notification: NSNotification){

        if let player = moviePlayer{
            let thumbnail =
            notification.userInfo![MPMoviePlayerThumbnailImageKey] as? UIImage

            if let image = thumbnail{

                /* We got the thumbnail image. You can now use it here */
                println("Thumbnail image = \(image)")
            }
        }



回答4:


You need to check if each video segment is empty in video track.

+ (UIImage*)getVideoPreViewImage:(AVAsset *)asset atTimeSec:(double)timeSec
{
    if (!asset) {
        return nil;
    }


    AVAssetTrack *videoTrack = [asset tracksWithMediaType:AVMediaTypeVideo].firstObject;
    NSArray<AVAssetTrackSegment *> *segs = videoTrack.segments;
    if (!segs.count) {
        return nil;
    }
    CMTime currentStartTime = kCMTimeZero;
    for (NSInteger i = 0; i < segs.count; i ++) {
        if (!segs[i].isEmpty) {
            currentStartTime = segs[i].timeMapping.target.start;
            break;
        }
    }

    CMTime coverAtTimeSec = CMTimeMakeWithSeconds(timeSec, asset.duration.timescale);

    if (CMTimeCompare(coverAtTimeSec, asset.duration) == 1 || CMTimeCompare(coverAtTimeSec, currentStartTime) == -1) {
        coverAtTimeSec = currentStartTime;
    }

    AVAssetImageGenerator *assetGen = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
    assetGen.requestedTimeToleranceBefore = kCMTimeZero;
    assetGen.requestedTimeToleranceAfter = kCMTimeZero;
    assetGen.appliesPreferredTrackTransform = YES;


    NSError *error = nil;
    CGImageRef image = [assetGen copyCGImageAtTime:coverAtTimeSec actualTime:NULL error:&error];
    if (error) {
        return nil;
    }
    UIImage *videoImage = [UIImage imageWithCGImage:image];


    CGImageRelease(image);
    return videoImage;
}


来源:https://stackoverflow.com/questions/19530800/getting-a-thumbnail-of-a-mov-video-ios

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!