GPUImage过滤视频

时间:2014-04-09 20:53:18

标签: ios gpuimage

这是对之前但仅略微相关的question

的后续行动

我正在使用GPUImage库将滤镜应用到相机应用中的静态照片和视频。几乎所有东西都运转良好。我无法解决的另一个问题如下:

  1. 我捕获了一个GPUImageMovie
  2. 我将其写入文件系统
  3. 我从文件系统中读取它并应用新过滤器
  4. 我将其写入文件系统中的其他网址
  5. 保存到该新网址的是具有正确持续时间但没有移动的视频。当我点击播放时,它只是一张静止图像,我想是视频的第一帧。每当我将任何过滤器应用于从文件系统检索的视频时,都会发生这种情况。将过滤器应用于实时录制视频可以正常工作。我的代码如下。

    任何人都可以告诉我如何修改它以保存整个原始视频并应用过滤器?

    - (void)applyProcessingToVideoAtIndexPath:(NSIndexPath *)indexPath withFilter:(GPUImageFilter *)selectedFilter
    {
        NSArray *urls = [self.videoURLsByIndexPaths objectForKey:self.indexPathForDisplayedImage];
        NSURL *url = [urls lastObject];
        self.editedMovie = [[GPUImageMovie alloc] initWithURL:url];
        assert(!!self.editedMovie);
        [self.editedMovie addTarget:selectedFilter]; // apply the user-selected filter to the file
        NSURL *movieURL = [self generatedMovieURL];
        // A different movie writer than the one I was using for live video capture.
        movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(640.0, 640.0)];
        [selectedFilter addTarget:movieWriter];
        movieWriter.shouldPassthroughAudio = YES;
        self.editedMovie.audioEncodingTarget = movieWriter;
        [self.editedMovie enableSynchronizedEncodingUsingMovieWriter:movieWriter];
        [movieWriter startRecording];
        [self.editedMovie startProcessing];
    
        __weak GPUImageMovieWriter *weakWriter = movieWriter;
        __weak CreateContentViewController *weakSelf = self;
        [movieWriter setCompletionBlock:^{
            [selectedFilter removeTarget:weakWriter];
            [weakWriter finishRecordingWithCompletionHandler:^{
    
                NSArray *urls = [weakSelf.videoURLsByIndexPaths objectForKey:weakSelf.indexPathForDisplayedImage];
                urls = [urls arrayByAddingObject:movieURL];
                NSMutableDictionary *mutableVideoURLs = [weakSelf.videoURLsByIndexPaths mutableCopy];
                [mutableVideoURLs setObject:urls forKey:weakSelf.indexPathForDisplayedImage];
                weakSelf.videoURLsByIndexPaths = mutableVideoURLs;
                dispatch_sync(dispatch_get_main_queue(), ^{
                    [self.filmRoll reloadData];
                    [weakSelf showPlayerLayerForURL:movieURL onTopOfImageView:weakSelf.displayedImageView];
                });
            }];
        }];
    }
    

1 个答案:

答案 0 :(得分:2)

我正在为未来的访问者发布此问题的“答案”。我的代码现在正在运行,但事实是我不确定是什么造成了不同。我不希望上面的代码成为任何人的红鲱鱼。这个问题可能在我的代码库中的其他地方。但是,我想提一下问题中发布的方法与我工作代码中的方法之间的区别。

  1. 我简化了控制器的结构,因此它一次只处理一个媒体项目。没有更多的videoURLsByIndexPath,我只有self.mediaItem。这显然使组织更易于管理。我也怀疑在电影作家完成版块内为movieURL添加一个条目可能与我所看到的意外结果有关。

  2. movieWriter现在是一个强大的属性而不是ivar。这个不应该重要AFAIK,因为ivars默认为强引用。尽管如此,这里发布的内容与我的工作代码之间存在差异。

  3. 几乎肯定没有关联,但我确实在self.editedMovie.audioEncodingTarget = self.movieWriter附近放了一个if-else来检查[self.mediaItem tracksWithType:AVMediaTypeAudio]的计数是否大于0.

  4. 由于不再需要维护视频网址字典,我只需拨打self.mediaItem = [AVURLAsset assetWithURL:movieURL];即可。我在电影作家完成块的这样做。

  5. 我觉得这不是最有价值的答案,但我希望我在这里提到的观点证明是有用的。