Подтвердить что ты не робот

GPUImage фильтрация видео

Это продолжение предыдущей, но только незначительно связанной question

Я использую библиотеку GPUImage для применения фильтров к неподвижным фотографиям и видео в приложении для камеры. Почти все работает красиво. Одна оставшаяся проблема, которую я не смог решить, выглядит следующим образом:

  • Я захватываю GPUImageMovie
  • Я пишу его в файловую систему
  • Я прочитал его из файловой системы и применил новый фильтр
  • Я пишу его на другой URL-адрес в файловой системе

Что сохраняется на этом новом URL-адресе - это видео с правильной продолжительностью, но без движения. Когда я нажимаю игру, это просто неподвижное изображение, я думаю, что первый кадр видео. Это происходит в любое время, когда я применяю какой-либо фильтр к видео, которое я извлекаю из файловой системы. Применение фильтра для записи видео в реальном времени прекрасно работает. Мой код ниже.

Может ли кто-нибудь сказать мне, как я могу изменить это, чтобы сохранить все исходное видео с применением фильтра?

- (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];
            });
        }];
    }];
}
4b9b3361

Ответ 1

Я отправляю ответ на этот вопрос для будущих посетителей. Мой код работает сейчас, но факт в том, что я не уверен, что изменило ситуацию. Я не хочу, чтобы этот код был красной селедкой для всех. Возможно, проблема была в другом месте моей базы кода. Тем не менее, я хочу упомянуть различия между методом, опубликованным в вопросе и методом в моем рабочем коде.

  • Я упростил структуру контроллера, поэтому он обрабатывает только один элемент мультимедиа за раз. Нет больше видеоURLsByIndexPath, у меня просто есть self.mediaItem. Это делает организацию более управляемой, очевидно. У меня также есть подозрение, что добавление записи для movieURL в этот словарь внутри блока завершения писателя фильма может быть связано с неожиданными результатами, которые я видел.

  • movieWriter теперь является сильным свойством вместо ivar. Это не должно иметь значения AFAIK, потому что ivars по умолчанию используют сильные ссылки. Тем не менее, это разница между тем, что размещено здесь и моим рабочим кодом.

  • Почти наверняка несвязанный, но я положил if-else вокруг self.editedMovie.audioEncodingTarget = self.movieWriter, чтобы проверить, превышает ли счет [self.mediaItem tracksWithType:AVMediaTypeAudio] 0.

  • Поскольку больше не нужно было поддерживать словарь видео URL-адресов, я просто вызываю self.mediaItem = [AVURLAsset assetWithURL:movieURL];. Я делаю это за пределами блока завершения записи фильма.

Я чувствую, что это не самые ценные ответы, но я надеюсь, что упомянутые здесь пункты окажутся полезными.