В пользовательском интерфейсе моего приложения для iOS отображается сложная иерархия CALayer
с. Один из этих слоев - AVPlayerLayer
, который отображает видео с CIFilter
s, примененным в реальном времени (используя AVVideoComposition(asset:, applyingCIFiltersWithHandler:)
).
Теперь я хочу экспортировать эту композицию слоев в видеофайл. В AVFoundation
есть два инструмента, которые кажутся полезными:
A : AVVideoCompositionCoreAnimationTool
, который позволяет визуализировать видео внутри (возможно анимированной) CALayer
иерархии
B : AVVideoComposition(asset:, applyingCIFiltersWithHandler:)
, который я также использую в пользовательском интерфейсе, чтобы применить CIFilter
s к видеоустройству.
Однако эти два инструмента нельзя использовать одновременно: если я запускаюAVAssetExportSession
, который объединяет эти инструменты, AVFoundation
выдает NSInvalidArgumentException
:
Ожидается, что композиция видео будет содержать только AVCoreImageFilterVideoCompositionInstruction
Я попытался обойти этоограничение следующим образом:
Обходной путь 1
1) Настройте экспорт, используя AVAssetReader
и AVAssetWriter
2) Получите буферы образцов изсчитыватель ресурсов и примените CIFilter
, сохраните результат в CGImage
.
3) Установите CGImage
в качестве content
видеослоя в иерархии слоев. Теперь иерархия слоев «выглядит как» один кадр конечного видео.
4) Получите данные CVPixelBuffer
для каждого кадра от средства записи ресурсов, используя CVPixelBufferGetBaseAddress
, и создайте CGContext
с этимdata.
5) Выполните рендеринг моего слоя в этот контекст, используя CALayer.render(in ctx: CGContext)
.
Эта настройка работает, но очень медленная - экспорт 5-секундного видео иногда занимает минуту. Похоже, что вызовы CoreGraphics
являются здесь узким местом (наверное, потому, что при таком подходе композиция происходит на процессоре?)
Обходной путь 2
Еще одинподход может заключаться в том, чтобы сделать это в два этапа: во-первых, сохранить исходное видео только с фильтрами, примененными к файлу, как в B , а затем использовать этот видео-файл для встраивания видео в композицию слоя, как в A . Тем не менее, поскольку он использует два прохода, я думаю, что это не так эффективно, как могло бы быть.
Резюме
Что является хорошим подходом для экспорта этого видео вфайл, в идеале за один проход? Как я могу использовать CIFilter
s и AVVideoCompositionCoreAnimationTool
одновременно? Есть ли в AVFoundation
собственный способ настройки «конвейера», объединяющего эти инструменты?