【问题标题】:Adding watermark to video is extremely slow向视频添加水印非常慢
【发布时间】:2018-08-17 04:20:08
【问题描述】:

我正在使用 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 秒是完全不可接受的。此外,我需要通过 Internet 传输此视频,因此加载屏幕显示其美丽的时间将超过总共大约 20 秒。

【问题讨论】:

  • 也许我只是不了解视频编解码器的最新情况,但解码、修改、然后重新编码比手机上的播放时间更快对我来说似乎相当不错。会不会是你对业绩的期望不切实际?是什么让您认为它可以更快?
  • 可能是这种情况。在 iPhone 上渲染 17MB 视频通常需要多长时间?我看到 snapchat 和 Instagram 在 2 秒内渲染了相同的视频。我将其他渲染时间与我的进行了比较,似乎仍有很大的潜力可以释放。
  • 如果您要渲染 1080p 或更高的分辨率,这并不是那么不可接受。 Snapchat 和 Instagram 使用低分辨率来提高渲染速度和文件大小。 @JohannaNoobie

标签: ios swift avfoundation avcomposition avvideocomposition


【解决方案1】:

根据Apple Documentation,尝试使用类AVAsynchronousCIImageFilteringRequest

概述

在使用 init(asset:applyingCIFiltersWithHandler:) 方法为 Core Image 过滤创建合成时使用此类。在该方法调用中,您提供一个块以供 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)
})

tutorial in Objective C 也可能是一个很好的资源。

【讨论】:

  • 您好,非常感谢您的回答。我会研究这个,当我在家的时候。 - 不用担心,你会收到赏金的。
  • stackoverflow.com/questions/54652637/… 看看你能告诉我我做错了什么吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-13
  • 2012-09-06
  • 2018-01-28
相关资源
最近更新 更多