添加到视频组合并导出时,叠加图像变得像素化

Overlay image becomes pixelated when added to video composition and exported

目标是将图像叠加在视频之上,但使用 AVVideoCompositionCoreAnimationTool 对图像进行像素化处理。

图片尺寸为 640x1136。视频导出尺寸为 320x568(模拟 5S 设备),因此图像应该可以很好地缩小。图像本身很清晰,但在导出过程中出现某些问题导致像素化。

为 AVMutableVideoComposition 使用 renderScale 没有帮助,因为如果值不是 1.0,AVAssetExportSession 会抛出异常。

为包含图像的层设置 contentsGravity 似乎没有效果。

目标是让用户录制视频然后在视频上绘图。 (图像代表用户绘制。)最终,导出的视频应与用户在视频预览中看到的和用户绘制的相匹配,具有相同的质量和尺寸。这个问题有助于叠加图像像素化。

帮忙?

    // Create main composition & its tracks
    let mainComposition = AVMutableComposition()
    let compositionVideoTrack = mainComposition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))
    let compositionAudioTrack = mainComposition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))

    // Get source video & audio tracks
    let videoURL = NSURL(fileURLWithPath: videoURL)
    let videoAsset = AVURLAsset(URL: videoURL, options: nil)
    let sourceVideoTrack = videoAsset.tracksWithMediaType(AVMediaTypeVideo)[0]
    let sourceAudioTrack = videoAsset.tracksWithMediaType(AVMediaTypeAudio)[0]

    // Add source tracks to composition
    do {
        try compositionVideoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), ofTrack: sourceVideoTrack, atTime: kCMTimeZero)
        try compositionAudioTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), ofTrack: sourceAudioTrack, atTime: kCMTimeZero)
    } catch {
        print("Error with insertTimeRange while exporting video: \(error)")
    }

    // Create video composition
    let videoComposition = AVMutableVideoComposition()
    print("Video composition duration: \(CMTimeGetSeconds(mainComposition.duration))")

    // -- Set parent layer & set size equal to device bounds
    let parentLayer = CALayer()
    parentLayer.frame = CGRectMake(0, 0, view.bounds.width, view.bounds.height)
    parentLayer.backgroundColor = UIColor.redColor().CGColor
    parentLayer.contentsGravity = kCAGravityResizeAspectFill

    // -- Set composition equal to capture settings
    videoComposition.renderSize = CGSize(width: view.bounds.width, height: view.bounds.height)
    videoComposition.frameDuration = CMTimeMake(1, Int32(frameRate))

    // -- Add instruction to  video composition object
    let instruction = AVMutableVideoCompositionInstruction()
    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, compositionVideoTrack.asset!.duration)
    let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: compositionVideoTrack)
    instruction.layerInstructions = [videoLayerInstruction]
    videoComposition.instructions = [instruction]

    // -- Create video layer
    let videoLayer = CALayer()
    videoLayer.frame = parentLayer.frame
    videoLayer.contentsGravity = kCAGravityResizeAspectFill

    // -- Create overlay layer
    let overlayLayer = CALayer()
    overlayLayer.frame = parentLayer.frame
    overlayLayer.contentsGravity = kCAGravityResizeAspectFill
    overlayLayer.contents = overlayImage!.CGImage
    overlayLayer.contentsScale = overlayImage!.scale

    // -- Add sublayers to parent layer
    parentLayer.addSublayer(videoLayer)
    parentLayer.addSublayer(overlayLayer)
    //overlayLayer.shouldRasterize = true

    // -- Set animation tool
    videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, inLayer: parentLayer)

    // Create exporter
    let outputURL = getFilePath(getUniqueFilename(gMP4File))
    let exporter = AVAssetExportSession(asset: mainComposition, presetName: AVAssetExportPresetHighestQuality)!
    exporter.outputURL = NSURL(fileURLWithPath: outputURL)
    exporter.outputFileType = AVFileTypeMPEG4
    exporter.videoComposition = videoComposition
    exporter.shouldOptimizeForNetworkUse = true

在对 rasterizationScale 和 contentsScale 进行了多次测试后,将两者结合设置效果最好,但线条仍然不如原来那么清晰。

希望有人能找到与视频合并时如何保持原始图像清晰度的答案。

请注意,如果使用 rasterizationScale,您可能还需要 shouldRasterize。

这些测试是在设备规模(例如,5S 为 2.0)和 2x 设备规模(例如,5S 为 4.0)下进行的。看到其他地方使用了 2 倍的设备比例,所以决定尝试一下,尽管它的效果还不清楚。

contentsScale 2.0:直线清晰,但圆圈包含瑕疵。

contentsScale 4.0:直线还可以,但不如 2.0 清晰,但圆包含的瑕疵更少。整体形象更好。

rasterizationScale 2.0:直线变窄但圆形区域(例如,像字母 "R" 中的那样)很糟糕

rasterizationScale 4.0:直线不那么尖锐但圆形区域更好

rasterizationScale + contentsScale 2.0:最佳折衷,线条仍不如原始图像清晰