Вы никогда не задумывались, как обрабатываются видео? Как на них накладываются эффекты? Тема довольно интересная и сложная. Ниже я постараюсь объяснить в общих словах, как можно добавить эффект на видео в iOS.

В первую очередь рассмотрим набор инструментов, который нам понадобится, а после перейдем к добавлению эффекта.

Core Image

Core Image — это фреймворк для обработки и анализа изображений, разработанный Apple, обеспечивающий высокопроизводительную обработку фотографий и видео. Основными компонентами этого фреймворка являются классы: CIImage, CIFilter, CIContext.

В Core Image можно связывать несколько фильтров (CIFilter) вместе для создания пользовательских эффектов, а также можно создавать пользовательские эффекты, которые работают на GPU. GPU – это графический процессор, перенося обработку эффектов на GPU, мы снижаем нагрузку на CPU (центральный процессор), что увеличивает скорость работы приложения.

AVFoundation

AVFoundation — это фреймворк для работы с медиа на iOS, macOS, watchOS и tvOS. Используя AVFoundation, вы можете легко воспроизводить, создавать и редактировать QuickTime фильмы и файлы MPEG-4 (MP4), воспроизводить потоки HLS (подробнее об HLS можно почитать здесь) и создавать собственные функции для работы с видео и аудио. Например, с помощью AVFoundation можно разработать аудио- и видеоплееры, аудио- и видео редакторы и вообще все, что связано с работой аудио и видео.

Добавление эффекта

Предположим, что Вы хотите добавить эффект взрыва на видео. Что же тогда Вам нужно делать?

Для начала нужно подготовить 3 видео: основное видео (куда будем накладывать эффект), видео эффекта с альфа-каналом и видео эффекта без альфа-канала.

Альфа-канал — это дополнительный канал, который может быть добавлен в рисунок. Он содержит информацию о прозрачности рисунка и в зависимости от типа альфа, он может содержать различные уровни прозрачности.

Альфа-канал нам нужен, чтобы видео эффекта не перекрывало основное видео.

Ниже приведен пример изображения с альфаканалом и без.


Прозрачность считается от чёрного до белого, т.е чем чернее, тем выше прозрачность (черный — полностью прозрачный, белый — не прозрачный)

После наложения эффекта видео, мы будем видеть только сам взрыв (белая часть изображения справа), а все остальное будет прозрачное, это позволит нам видеть основное видео, куда мы накладываем эффект.

Далее смысл состоит в том, что нам нужно прочитать 3 видео одновременно и совместить изображения. Делается это с помощью CIFilter. Про 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 состоит из трех, полученных нами ранее. Отлично, теперь рендерим CIImage в CVPixelBufferRef с помощью CIIContext. Примерный код выглядит так:

 
 CVPixelBufferRef pixelBuffer =[self.contextEffect renderToPixelBufferNew:outputImage]; 
 

Теперь мы имеем готовый пиксельный буффер, нам нужно добавить его в буффер сэмплов видео, для того чтобы получить видео с эффектом.

 
 [self.writerAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:CMTimeMake(self.frameUse, 30)] 
 

После этого эффект успешно добавляется на видео. При этом вся работа выполнялась на GPU (графический процессор), за счет этого удается снять нагрузку с CPU (центральный процессор) и увеличить скорость работы приложения.

Добавление эффекта на видео в iOS — задача довольно сложная и трудоемкая. Но ее можно выполнить, если знать основные фреймворки для работы с мультимедиа в iOS и уметь ими пользоваться.

  • Разработка