2015-04-03 39 views
7

Tôi có một số NSURL có chứa video và tôi muốn quay một khung của video đó mười lần mỗi giây. Và tôi có mã sẽ chụp một hình ảnh của máy nghe nhạc của tôi, nhưng tôi gặp khó khăn khi thiết lập nó để chụp 10 khung hình mỗi giây. Tôi đang cố gắng một cái gì đó như thế này, nhưng nó quay trở lại cùng một khung hình ban đầu của video, số lần chính xác? Dưới đây là những gì tôi có:iOS Chụp nhiều ảnh chụp màn hình

AVAsset *asset = [AVAsset assetWithURL:videoUrl]; 
CMTime vidLength = asset.duration; 
float seconds = CMTimeGetSeconds(vidLength); 
int frameCount = 0; 
for (float i = 0; i < seconds;) { 
    AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]initWithAsset:asset]; 
    CMTime time = CMTimeMake(i, 10); 
    CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL]; 
    UIImage *thumbnail = [UIImage imageWithCGImage:imageRef]; 
           CGImageRelease(imageRef); 
NSString* filename = [NSString stringWithFormat:@"Documents/frame_%d.png", frameCount]; 
NSString* pngPath = [NSHomeDirectory() stringByAppendingPathComponent:filename]; 

[UIImagePNGRepresentation(thumbnail) writeToFile: pngPath atomically: YES]; 
frameCount++; 
i = i + 0.1; 
} 

Nhưng thay vì nhận được khung tại thời điểm hiện tại i của đoạn video, tôi chỉ nhận được khung ban đầu?

Làm cách nào để có được khung hình của video 10 lần một giây?

Thanks for the help :)

Trả lời

2

Với CMTimeMake(A, B) bạn lưu trữ một số lượng hợp lý, một phần chính xác A/B giây, và tham số đầu tiên của chức năng này có giá trị int. Trong 20 giây video, bạn sẽ chụp một khung với thời gian ((int) 19.9)/10 = 1.9 giây trong lần lặp cuối cùng của chu kỳ của bạn. Sử dụng chức năng CMTimeMakeWithSeconds(i, NSEC_PER_SEC) để khắc phục sự cố thời gian này.

10

Bạn đang nhận được khung ban đầu bởi vì bạn đang cố gắng để tạo ra CMTime với sự giúp đỡ của giá trị float:

CMTime time = CMTimeMake(i, 10); 

Kể từ CMTimeMake chức năng mất int64_t giá trị như tham số đầu tiên, giá trị float của bạn sẽ được làm tròn đến int, và bạn sẽ nhận được kết quả không chính xác.

Cho phép thay đổi mã của bạn một chút:

1) Lúc đầu, bạn cần phải tìm tổng khung đếm mà bạn cần phải nhận được từ video. Bạn viết rằng bạn cần 10 khung hình mỗi giây, do đó mã sẽ là:

int requiredFramesCount = seconds * 10; 

2) Tiếp theo, bạn cần phải tìm một giá trị sẽ được tăng giá trị CMTime của bạn trên mỗi bước:

int64_t step = vidLength.value/requiredFramesCount; 

3) và cuối cùng, bạn cần phải thiết lập requestedTimeToleranceBefore và requestedTimeToleranceAfter để kCMTimeZero, để có được một khung thời gian chính xác:

imageGenerator.requestedTimeToleranceAfter = kCMTimeZero; 
imageGenerator.requestedTimeToleranceBefore = kCMTimeZero; 

Sau đây là cách mã của bạn sẽ trông giống như:

CMTime vidLength = asset.duration; 
float seconds = CMTimeGetSeconds(vidLength); 

int requiredFramesCount = seconds * 10; 
int64_t step = vidLength.value/requiredFramesCount; 

int value = 0; 

for (int i = 0; i < requiredFramesCount; i++) { 

    AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]initWithAsset:asset]; 
    imageGenerator.requestedTimeToleranceAfter = kCMTimeZero; 
    imageGenerator.requestedTimeToleranceBefore = kCMTimeZero; 

    CMTime time = CMTimeMake(value, vidLength.timescale); 

    CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL]; 
    UIImage *thumbnail = [UIImage imageWithCGImage:imageRef]; 
    CGImageRelease(imageRef); 
    NSString* filename = [NSString stringWithFormat:@"Documents/frame_%d.png", i]; 
    NSString* pngPath = [NSHomeDirectory() stringByAppendingPathComponent:filename]; 

    [UIImagePNGRepresentation(thumbnail) writeToFile: pngPath atomically: YES]; 

    value += step; 
} 
+0

Câu hỏi tương tự sử dụng Swift http://stackoverflow.com/questions/32286320/grab-frames-from-video-using-swift/32297251 – arpo

Các vấn đề liên quan