访问iOS中所有电影帧的最佳方式 [英] Best way to access all movie frames in iOS
问题描述
我试图在顶部添加效果来编辑现有的电影,因此我需要能够扫描所有电影帧,将它们作为UIImage,应用效果,然后更新该帧或将其写入新电影。
我发现人们建议使用AVAssetImageGenerator。下面是我最后编辑的样本:我是怎么做的:
Im trying to edit existing movie with added effects on top thus I need ability to scan all movie frames, get them as UIImage, apply effect and then either update that frame or write it into new movie. What I found is people suggesting to use AVAssetImageGenerator. Below is my final edited sample of how Im doing it:
-(void)processMovie:(NSString*)moviePath {
NSURL* url = [NSURL fileURLWithPath:moviePath];
AVURLAsset *asset=[[AVURLAsset alloc] initWithURL:url options:nil];
float movieTimeInSeconds = CMTimeGetSeconds([movie duration]);
AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
generator.requestedTimeToleranceBefore = generator.requestedTimeToleranceAfter = kCMTimeZero;
generator.appliesPreferredTrackTransform=TRUE;
[asset release];
// building array of time with steps as 1/10th of second
NSMutableArray* arr = [[[NSMutableArray alloc] init] retain];
for(int i=0; i<movieTimeInSeconds*10; i++) {
[arr addObject:[NSValue valueWithCMTime:CMTimeMake(i,10)]];
}
AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error){
if (result == AVAssetImageGeneratorSucceeded) {
UIImage* img = [UIImage imageWithCGImage:im];
// use img to apply effect and write it in new movie
// after last frame do [generator release];
}
};
[generator generateCGImagesAsynchronouslyForTimes:arr completionHandler:handler];
}
这种方法有2个问题:
- 我需要猜测电影的时间步长,或者在我的例子中假设电影的10FPS。实际的时间步长不是均匀间隔加上有时候我们跳过了帧。
- 扫描帧很慢。如果以高分辨率录制电影,我会在0.5秒左右为每帧检索UIImage。
看起来不自然。问题:是否有更好的方法来扫描电影的所有原始帧?
It seems unnatural. Question: is there better way to scan all original frames of the movie?
推荐答案
终于找到了我想要的东西。下面是我扫描电影中所有样本的代码。 BTW使用AVAssetImageGenerator工作但很慢。这种方法很快。
Finally found what I was looking for. Below is my code that scans all samples in the movie. BTW using AVAssetImageGenerator was working but was very slow. This approach is fast.
inputUrl = [NSURL fileURLWithPath:filePath];
AVURLAsset* movie = [AVURLAsset URLAssetWithURL:inputUrl options:nil];
NSArray* tracks = [movie tracksWithMediaType:AVMediaTypeVideo];
AVAssetTrack* track = [tracks firstObject];
NSError* error = nil;
AVAssetReader* areader = [[AVAssetReader alloc] initWithAsset:movie error:&error];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kCVPixelFormatType_32ARGB], kCVPixelBufferPixelFormatTypeKey,
nil];
AVAssetReaderTrackOutput* rout = [[AVAssetReaderTrackOutput alloc] initWithTrack:track outputSettings:options];
[areader addOutput:rout];
[areader startReading];
while ([areader status] == AVAssetReaderStatusReading) {
CMSampleBufferRef sbuff = [rout copyNextSampleBuffer];
if (sbuff) {
dispatch_sync(dispatch_get_main_queue(), ^{
[self writeFrame:sbuff];
});
}
}
这篇关于访问iOS中所有电影帧的最佳方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!