Как добавить эффект к видео на iPhone

Вы когда-нибудь задумывались, как обрабатываются видео? Как на них накладываются эффекты? Тема интересная и непростая. Ниже я постараюсь в общих чертах объяснить, как добавить эффект на видео в iOS.
В первую очередь рассмотрим набор инструментов, который нам понадобится, а затем перейдём к добавлению эффекта.
Core Image
Core Image — это фреймворк для обработки и анализа изображений, разработанный Apple, обеспечивающий высокопроизводительную обработку фотографий и видео. Основными компонентами этого фреймворка являются классы: CIImage, CIFilter, CIContext.
В Core Image можно соединять несколько фильтров (CIFilter) для создания собственных эффектов, а также разрабатывать пользовательские эффекты, работающие на GPU. GPU — это графический процессор. Перенос обработки эффектов на GPU снижает нагрузку на CPU (центральный процессор) и повышает производительность приложения.
AVFoundation
AVFoundation — это фреймворк для работы с медиа на iOS, macOS, watchOS и tvOS. С его помощью можно легко воспроизводить, создавать и редактировать фильмы в форматах QuickTime и MPEG-4 (MP4), а также работать со стримингом HLS (подробнее об HLS). Кроме того, с помощью AVFoundation можно разрабатывать аудио- и видеоплееры, редакторы и любые другие приложения, связанные с обработкой звука и видео.
Добавление эффекта
Предположим, что вы хотите добавить эффект взрыва на видео. Что тогда нужно сделать?
Для начала подготовьте три видео: основное (на которое будет накладываться эффект), видео эффекта с альфа-каналом и видео эффекта без альфа-канала.
Альфа-канал — это дополнительный канал, который можно добавить к изображению. Он хранит информацию о прозрачности: в зависимости от типа альфа-канала, он может поддерживать разные уровни прозрачности.
Альфа-канал нужен, чтобы видео с эффектом не перекрывало основное видео.
Ниже приведён пример изображения с альфаканалом и без него.

Прозрачность измеряется от чёрного до белого: чем темнее цвет, тем выше прозрачность (чёрный — полностью прозрачный, белый — непрозрачный)
После применения эффекта видео мы увидим только сам взрыв (белая часть изображения справа), а всё остальное станет прозрачным. Это позволит видеть основное видео, на которое накладывается эффект.
Далее нужно одновременно прочитать три видео и объединить их кадры. Для этого используется CIFilter. О нём мы уже говорили ранее, в разделе про Core Image.
Сначала с помощью CMSampleBuffer получаем ссылку на CVImageBuffer — он нужен для работы с различными форматами изображений и является базовым классом для CVPixelBuffer, который понадобится дальше. Из CVImageBuffer создаём CIImage. В коде это выглядит примерно так:
CVImageBufferRef imageRecordBuffer = CMSampleBufferGetImageBuffer(recordBuffer);
CIImage *ciBackground = [CIImage imageWithCVPixelBuffer:imageRecordBuffer];
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(buffer);
CIImage *ciTop = [CIImage imageWithCVPixelBuffer:imageBuffer];
CVImageBufferRef imageAlphaBuffer = CMSampleBufferGetImageBuffer(alphaBuffer);
CIImage *ciMask = [CIImage imageWithCVPixelBuffer:imageAlphaBuffer];
Получили CIImage для каждого видео: основное видео, видео эффекта с альфа-каналом и видео эффекта без альфа-канала.
Далее нам нужно объединить эти три CIImage. Как я уже говорил, для этого понадобится CIFilter. Примерный код выглядит так:
CIFilter *filterMask = [CIFilter filterWithName:@"CIBlendWithMask" keysAndValues:@"inputBackgroundImage", ciBackground, @"inputImage", ciTop, @"inputMaskImage", ciMask, nil];
CIImage *outputImage = [filterMask outputImage];
Мы снова получили CIImage, но теперь он состоит из трёх изображений, которые мы создали ранее. Отлично, теперь преобразуем CIImage в CVPixelBufferRef с помощью CIContext. Примерный код выглядит так:
CVPixelBufferRef pixelBuffer =[self.contextEffect renderToPixelBufferNew:outputImage];
Теперь у нас есть готовый пиксельный буфер, и его нужно добавить в буфер сэмплов видео, чтобы получить видео с эффектом.
[self.writerAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:CMTimeMake(self.frameUse, 30)]
После этого эффект успешно добавляется на видео. Вся обработка выполняется на GPU (графический процессор), что снижает нагрузку на CPU (центральный процессор) и ускоряет работу приложения.
Добавление эффекта на видео в iOS — задача сложная и трудоёмкая. Но её можно выполнить, если знать основные фреймворки для работы с мультимедиа в iOS и уметь ими пользоваться.
