2012-06-08 13 views
5

tôi đang cố gắng để chuyển đổi video toàn bộ vào một chuỗi hình ảnh với tốc độ 60fps, có nghĩa là 60 hình ảnh được tạo ra mỗi giây của video ...iOS AVFoundation - Chuyển đổi video thành nhiều ảnh ở 60 fps

Để làm như vậy, tôi đang sử dụng AVAssetImageGenerator và phương thức generateCGImagesAsynchronouslyForTimes ...

Mọi thứ diễn ra khá tốt, ngoại trừ việc tôi gặp vấn đề về hiệu năng nghiêm trọng khi xử lý thời gian thực thi xử lý hàng loạt (khoảng 5 phút trong 13 giây). ..

Hơn nữa, trên kích thước sau CGSizeMake (512, 324), tôi gặp sự cố. ..

Có ai đã từng trải nghiệm loại xử lý này và biết cách giảm thời gian thực hiện cũng như có thể trích xuất hình ảnh ở độ phân giải cao hơn không?

Dưới đây là đoạn code tôi đang thử nghiệm ...

NSURL *movieURL = [NSURL fileURLWithPath:getCaptureMoviePath()]; 

AVURLAsset *asset=[[AVURLAsset alloc] initWithURL:movieURL options:nil]; 
AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset]; 
generator.appliesPreferredTrackTransform=TRUE; 
generator.requestedTimeToleranceAfter=kCMTimeZero; 
generator.requestedTimeToleranceBefore=kCMTimeZero; 
NSMutableArray *thumbTimes=[NSMutableArray arrayWithCapacity:asset.duration.value]; 

for(int t=0;t < asset.duration.value;t=t+2) { 
    CMTime thumbTime = CMTimeMake(t, asset.duration.timescale); 
    NSLog(@"Time Scale : %d ", asset.duration.timescale); 
    NSValue *v=[NSValue valueWithCMTime:thumbTime]; 
     [thumbTimes addObject:v]; 
} 
NSLog(@"thumbTimes array contains %d objects : ", [thumbTimes count]); 
[asset release]; 
AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error) { 
    if (result != AVAssetImageGeneratorSucceeded) { 
     NSLog(@"couldn't generate thumbnail, error:%@", error); 
    } else { 
     NSLog(@"actual time: %lld/%d (requested: %lld/%d)",actualTime.value,actualTime.timescale,requestedTime.value,requestedTime.timescale); 
     NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 
     [formatter setDateFormat:@"yyyyMMdd-HHmmss"]; 
     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
     NSString *documentsDirectory = [paths objectAtIndex:0]; 
     NSString *filename = [NSString stringWithFormat:@"%@.png", [formatter stringFromDate:[NSDate date]]]; 
     NSString *filepath = [documentsDirectory stringByAppendingPathComponent:filename]; 
     CFURLRef url = (CFURLRef)[NSURL fileURLWithPath:filepath]; 
     CGImageDestinationRef destination = CGImageDestinationCreateWithURL(url, kUTTypePNG, 1, NULL); 
     CGImageDestinationAddImage(destination, im, nil); 
     if (!CGImageDestinationFinalize(destination)) {  
      NSLog(@"Failed to write image to %@", filepath); 
     } 
     CFRelease(destination); 
    } 
    //[generator release]; 
}; 
CGSize maxSize = CGSizeMake(512, 324); 
generator.maximumSize = maxSize; 

[generator generateCGImagesAsynchronouslyForTimes:thumbTimes completionHandler:handler]; 

Cám ơn bạn trước,

j.

+0

Tôi đang gặp phải sự cố tương tự ngoại trừ trường hợp của tôi, tôi đang cố chia nhỏ khoảng 14 video clip ngắn. Bạn đã bao giờ tìm ra bất kỳ tối ưu hóa nào có thể? – afrederick

Trả lời

6

Hey @Sooriah Joel thử sử dụng mã sau đây. Nó làm việc tốt cho tôi.

- (void)generateCMTimesArrayOfAllFramesUsingAsset:(AVURLAsset *)asset 
{ 
    if (cmTimeArray.count>0) { 
     [cmTimeArray removeAllObjects]; 
    } 
    //Generate all frames present in video 
    for(int t=0;t < asset.duration.value;t++) { 
     CMTime thumbTime = CMTimeMake(t,asset.duration.timescale); 
     NSValue *v=[NSValue valueWithCMTime:thumbTime]; 
     [cmTimeArray addObject:v]; 
    } 
    NSLog(@"Array of time %@ count = %d",cmTimeArray, cmTimeArray.count); 
    //NSLog(@"Array count = %d",cmTimeArray.count); 
} 


- (void)generateCMTimesArrayOfFrames:(int)framesInterval UsingAsset:(AVURLAsset *)asset 
{ 
    int videoDuration = ceilf(((float)asset.duration.value/asset.duration.timescale)); 
    NSLog(@"Video duration %lld seconds timescale = %d",asset.duration.value,asset.duration.timescale); 
    if (cmTimeArray.count>0) { 
     [cmTimeArray removeAllObjects]; 
    } 
    //Generate limited frames present in video 
    for (int i = 0; i<videoDuration; i++) 
    { 
     int64_t tempInt = i; 
     CMTime tempCMTime = CMTimeMake(tempInt,1); 
     int32_t interval = framesInterval; 
     for (int j = 1; j<framesInterval+1; j++) 
     { 
      CMTime newCMtime = CMTimeMake(j,interval); 
      CMTime addition = CMTimeAdd(tempCMTime, newCMtime); 
      [cmTimeArray addObject:[NSValue valueWithCMTime:addition]]; 
     } 
    } 
    NSLog(@"Array of time %@ count = %d",cmTimeArray, cmTimeArray.count); 
    //NSLog(@"Array count = %d",cmTimeArray.count); 
} 


- (void)generateThumbnailsFromVideoURL:(AVURLAsset *)videoAsset 
{ 
    //Generate CMTimes Array of required frames 
    //1.Generate All Frames 
    //[self generateCMTimesArrayOfAllFramesUsingAsset:asset]; 

    //2.Generate specific frames per second 
    [self generateCMTimesArrayOfFrames:30 UsingAsset:videoAsset]; 

    __block int i = 0; 
    AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error){ 
    if (result == AVAssetImageGeneratorSucceeded) { 
     [framesArray addObject:[UIImage imageWithCGImage:im]]; 
    } 
    if (result == AVAssetImageGeneratorFailed) { 
     NSLog(@"Failed with error: %@ code %d", [error localizedDescription],error.code); 
    } 
    if (result == AVAssetImageGeneratorCancelled) { 
     NSLog(@"Canceled"); 
    } 

    i++; 
    imageIndex = i; 

    if(i == cmTimeArray.count) { 
     //Thumbnail generation completed 
    } 
}; 

    // Launching the process... 
    self.generator = [[AVAssetImageGenerator alloc] initWithAsset:videoAsset]; 
    self.generator.apertureMode = AVAssetImageGeneratorApertureModeCleanAperture; 
    self.generator.appliesPreferredTrackTransform=TRUE; 
    self.generator.requestedTimeToleranceBefore = kCMTimeZero; 
    self.generator.requestedTimeToleranceAfter = kCMTimeZero; 
    self.generator.maximumSize = CGSizeMake(40, 40); 
    [self.generator generateCGImagesAsynchronouslyForTimes:cmTimeArray completionHandler:handler]; 
}