Как наложить эффект на видео в iOS — обложка

Вы когда-нибудь задумывались, как обрабатываются видео? Как на них накладываются эффекты? Тема интересная и непростая. Ниже я постараюсь в общих чертах объяснить, как добавить эффект на видео в 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 и уметь ими пользоваться.

  • Разработка