22

对不起我的英语)寻找有关使用 iPhone 从视频中读取帧的信息我发现了这个项目,http://www.codza.com/extracting-frames-from-movies-on-iphone/comment-page-1#comment -1116,但我还在某处读到,您可以使用 AVFoundation 从视频中捕获帧以获得更好的性能..

但是我找不到有关如何做到这一点的信息...

有什么想法?

谢谢阅读

4

5 回答 5

37

您说的是使用调用在特定时间从视频中生成 Apple 所称的缩略图。

对于 MPMoviePlayerController(iOS 用来保存来自文件或其他来源的视频),有两个命令可以做到这一点。第一个从特定时间点的电影生成单个缩略图(图像),第二个生成一个时间范围内的一组缩略图。

此示例将 10 秒时的图像放入影片剪辑myMovie.mp4 中

MPMoviePlayerController *movie = [[MPMoviePlayerController alloc]
        initWithContentURL:[NSURL URLWithString:@"myMovie.mp4"]];
UIImage *singleFrameImage = [movie thumbnailImageAtTime:10 
        timeOption:MPMovieTimeOptionExact];

请注意,这是同步执行的——即当您获取屏幕截图时,用户将被迫等待。

另一种选择是从电影中获取一系列图像,从一系列时间:

MPMoviePlayerController *movie = [[MPMoviePlayerController alloc]
        initWithContentURL [NSURL URLWithString:@"myMovie.mp4"]];
NSNumber time1 = 10;
NSNumber time2 = 11;
NSNumber time3 = 12;
NSArray *times = [NSArray arrayWithObjects:time1,time2,time3,nil];
[movie requestThumbnailImagesAtTimes:times timeOption:MPMovieTimeOptionExact];

MPMoviePlayerThumbnailImageRequestDidFinishNotification第二种方式将在每次生成新图像时触发类型通知。您可以设置一个观察者来监控它并处理图像 - 我会让您自己解决这个问题!

于 2010-11-16T23:09:24.360 回答
19

您也可以尝试AVAssetImageGenerator,特别是generateCGImagesAsynchronouslyForTimes:completionHandler

这个 SO 答案有很好的示例代码。

于 2010-11-18T09:14:37.497 回答
7

使用 AVAssetImageGenerator 获取帧的 Swift 2 代码:

func previewImageForLocalVideo(url:NSURL) -> UIImage?
{
    let asset = AVAsset(URL: url)
    let imageGenerator = AVAssetImageGenerator(asset: asset)
    imageGenerator.appliesPreferredTrackTransform = true

    var time = asset.duration
    //If possible - take not the first frame (it could be completely black or white on camara's videos)
    time.value = min(time.value, 2)

    do {
        let imageRef = try imageGenerator.copyCGImageAtTime(time, actualTime: nil)
        return UIImage(CGImage: imageRef)
    }
    catch let error as NSError
    {
        print("Image generation failed with error \(error)")
        return nil
    }
}
于 2015-10-27T14:11:32.230 回答
3

这是从视频中获取 FPS 图像的代码

1) 进口

#import <Photos/Photos.h>

2) 在 vi​​ewDidLoad

    videoUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle]pathForResource:@"VfE_html5" ofType:@"mp4"]];
    [self createImage:5]; // 5 is frame per second (FPS) you can change FPS as per your requirement.

3) 功能

-(void)createImage:(int)withFPS {
    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoUrl options:nil];
    AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    generator.requestedTimeToleranceAfter =  kCMTimeZero;
    generator.requestedTimeToleranceBefore =  kCMTimeZero;

    for (Float64 i = 0; i < CMTimeGetSeconds(asset.duration) *  withFPS ; i++){
        @autoreleasepool {
            CMTime time = CMTimeMake(i, withFPS);
            NSError *err;
            CMTime actualTime;
            CGImageRef image = [generator copyCGImageAtTime:time actualTime:&actualTime error:&err];
            UIImage *generatedImage = [[UIImage alloc] initWithCGImage:image];
            [self savePhotoToAlbum: generatedImage]; // Saves the image on document directory and not memory
            CGImageRelease(image);
        }
    }
}

-(void)savePhotoToAlbum:(UIImage*)imageToSave {

    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
        PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:imageToSave];
    } completionHandler:^(BOOL success, NSError *error) {
        if (success) {
            NSLog(@"sucess.");
        }
        else {
            NSLog(@"fail.");
        }
    }];
}
于 2018-07-17T11:07:24.813 回答
1

在 Swift 4 中,这对我进行了一些修改,主要是将 imageGenerator.copyCGImage 的“at”参数更改为 CMTime 类型:

func showFrame(from file:String) {
    let file = file.components(separatedBy: ".")
    guard let path = Bundle.main.path(forResource: file[0], ofType:file[1]) else {
        debugPrint( "\(file.joined(separator: ".")) not found")
        return
    }
    let url = URL(fileURLWithPath: path)
    let image = previewImageForLocalVideo(url: url)
    let imgView = UIImageView(image: image)
    view.addSubview(imgView)
}    

func previewImageForLocalVideo(url:URL) -> UIImage? {
    let asset = AVAsset(url: url)
    let imageGenerator = AVAssetImageGenerator(asset: asset)
    imageGenerator.appliesPreferredTrackTransform = true
    let tVal = NSValue(time: CMTimeMake(12, 1)) as! CMTime
    do {
        let imageRef = try imageGenerator.copyCGImage(at: tVal, actualTime: nil)
        return UIImage(cgImage: imageRef)
    }
    catch let error as NSError
    {
        print("Image generation failed with error \(error)")
        return nil
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    showFrame(from:"video.mp4")
}

来源

于 2018-02-25T11:58:05.613 回答