Добавление водяного знака к видео происходит очень медленно

Я использую AVComposition для отображения водяного знака на видео. Этот процесс занимает около 15 секунд, что не совсем нормально для 20-секундного видео. Мои настройки экспорта:

let exporter = AVAssetExportSession.init(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)
    exporter?.outputURL = outputPath
    exporter?.outputFileType = AVFileType.mp4
    exporter?.shouldOptimizeForNetworkUse = true
    exporter?.videoComposition = mainCompositionInst
    DispatchQueue.main.async {
        exporter?.exportAsynchronously(completionHandler: {

            if exporter?.status == AVAssetExportSessionStatus.completed {
                completion(true, exporter)
            }else{
                completion(false, exporter)
            }

        })
    }

Вот как я добавляю водяной знак:

    //Creating image layer
    let overlayLayer = CALayer()
    let overlayImage: UIImage = image
    overlayLayer.contents = overlayImage.cgImage
    overlayLayer.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
    overlayLayer.contentsGravity = kCAGravityResizeAspectFill
    overlayLayer.masksToBounds = true

    //Creating parent and video layer
    let parentLayer = CALayer()
    let videoLayer = CALayer()
    parentLayer.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
    videoLayer.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
    parentLayer.addSublayer(videoLayer)
    parentLayer.addSublayer(overlayLayer)

    //Adding those layers to video
    composition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer)
}

и вот как я в итоге трансформирую свое видео:

 let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction.init(assetTrack: videoTrack!)
    let videoAssetTrack = videoAsset.tracks(withMediaType: AVMediaType.video)[0]
    var videoAssetOrientation = UIImageOrientation.up
    var isVideoAssetPortrait = false
    let videoTransform = videoAssetTrack.preferredTransform

    if videoTransform.a == 0 && videoTransform.b == 1.0 && videoTransform.c == -1.0 && videoTransform.d == 0 {
        videoAssetOrientation = .right
        isVideoAssetPortrait = true
    }
    if videoTransform.a == 0 && videoTransform.b == -1.0 && videoTransform.c == 1.0 && videoTransform.d == 0 {
        videoAssetOrientation = .left
        isVideoAssetPortrait = true
    }
    if videoTransform.a == 1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == 1.0 {
        videoAssetOrientation = .up
    }
    if videoTransform.a == -1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == -1.0 {
        videoAssetOrientation = .down
    }

    videoLayerInstruction.setTransform(videoAssetTrack.preferredTransform, at: kCMTimeZero)

    //Add instructions
    mainInstruction.layerInstructions = [videoLayerInstruction]
    let mainCompositionInst = AVMutableVideoComposition()
    let naturalSize : CGSize!
    if isVideoAssetPortrait {
        naturalSize = CGSize(width: videoAssetTrack.naturalSize.height, height: videoAssetTrack.naturalSize.width)
    } else {
        naturalSize = videoAssetTrack.naturalSize
    }

Итак, теперь мой вопрос: как я могу улучшить производительность слияния водяного знака с моим видео? 15 секунд совершенно неприемлемы для любого конечного пользователя. Кроме того, мне нужно передать это видео через Интернет, чтобы экран загрузки показывал его красоту в общей сложности более двадцати секунд.


person thelearner    schedule 08.03.2018    source источник
comment
Может быть, я просто не в курсе видеокодеков, но декодирование, модификация, а затем перекодирование быстрее, чем время воспроизведения на телефоне, мне кажется довольно хорошим. Может быть, у вас есть нереалистичные ожидания производительности? Что заставляет вас думать, что это может быть быстрее?   -  person zneak    schedule 11.03.2018
comment
Это может быть так. Сколько времени обычно требуется для рендеринга 17-мегабайтного видео на iPhone? Я вижу, как Snapchat и Instagram отображают одно и то же видео за 2 секунды. Я сравнил другое время рендеринга со своим, и кажется, что еще много нераскрытого потенциала.   -  person thelearner    schedule 12.03.2018
comment
Если вы рендерите 1080p или более высокое разрешение, это не так неприемлемо. Snapchat и Instagram используют низкое разрешение для скорости рендеринга и размера файла. @JohannaNoobie   -  person Cagatay Kaptanoglu    schedule 12.03.2018


Ответы (1)


Согласно документации Apple, попробуйте использовать класс AVAsynchronousCIImageFilteringRequest

Обзор

Вы используете этот класс при создании композиции для фильтрации Core Image с помощью метода init(asset:applyingCIFiltersWithHandler:). В этом вызове метода вы предоставляете блок, который будет вызываться AVFoundation при обработке каждого кадра видео, а единственным параметром блока является объект AVAsynchronousCIImageFilteringRequest. Используйте этот объект как для изображения видеокадра, которое нужно отфильтровать, так и для возврата отфильтрованного изображения в AVFoundation для отображения или экспорта. В листинге 1 показан пример применения фильтра к активу.

    let filter = CIFilter(name: "CIGaussianBlur")!
    let composition = AVVideoComposition(asset: asset, applyingCIFiltersWithHandler: { request in

    // Clamp to avoid blurring transparent pixels at the image edges
    let source = request.sourceImage.imageByClampingToExtent()
    filter.setValue(source, forKey: kCIInputImageKey)

    // Vary filter parameters based on video timing
    let seconds = CMTimeGetSeconds(request.compositionTime)
    filter.setValue(seconds * 10.0, forKey: kCIInputRadiusKey)

    // Crop the blurred output to the bounds of the original image
    let output = filter.outputImage!.imageByCroppingToRect(request.sourceImage.extent)

    // Provide the filter output to the composition
    request.finishWithImage(output, context: nil)
})

Существует руководство по Objective C, которое также может быть хорошим ресурсом.

person Jake    schedule 14.03.2018
comment
Здравствуйте, большое спасибо за этот ответ. Я посмотрю на это, когда буду дома. - Не беспокойся, ты получишь награду. - person thelearner; 18.03.2018
comment
stackoverflow.com/questions/54652637/ посмотрите, не могли бы вы предложить мне, что я делаю неправильно? - person Deep; 13.02.2019