0

我正在使用AVMutableComposition()添加这样的轨道将多个视频文件拼接成一个:

let compositionVideoTrack = mainComposition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
let soundtrackTrack = mainComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)

private var insertTime = CMTime.zero
     
for videoAsset in arrayVideos {
       try! compositionVideoTrack?.insertTimeRange(CMTimeRangeMake(start: .zero, duration: videoAsset.duration), of: videoAsset.tracks(withMediaType: .video)[0], at: insertTime)
       try! soundtrackTrack?.insertTimeRange(CMTimeRangeMake(start: .zero, duration: videoAsset.duration), of: videoAsset.tracks(withMediaType: .audio)[0], at: insertTime)
            
       insertTime = CMTimeAdd(insertTime, videoAsset.duration)
}

然后将它们导出AVAssetExportSession(asset: mainComposition, presetName: AVAssetExportPresetMediumQuality)到 .mov 文件中。

这会将拼接的视频保存到 url,我可以使用 AVAsset 访问并显示给用户。之后,我尝试将图像叠加层添加到视频中并再次导出。

在第二种方法中,我从 url 实例化 AVAsset AVAsset(url: fileUrl)。并创造新的AVMutableComposition(). 我将视频和音频轨道添加到资产的合成中:

    compositionTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
    compositionTrack.insertTimeRange(timeRange, of: asset.tracks(withMediaType: .video)[], at: .zero)
...

然后我使用图层将叠加层添加到视频中,AVVideoCompositionCoreAnimationTool()如下所示:

 let videoLayer = CALayer()
 videoLayer.frame = CGRect(origin: .zero, size: videoSize)
 let overlayLayer = CALayer()
 overlayLayer.frame = CGRect(origin: .zero, size: videoSize)
        
 overlayLayer.contents = watermark.cgImage
 overlayLayer.contentsGravity = .resizeAspect
        
 let outputLayer = CALayer()
 outputLayer.frame = CGRect(origin: .zero, size: videoSize)
 outputLayer.addSublayer(videoLayer)
 outputLayer.addSublayer(overlayLayer)
        
 let videoComposition = AVMutableVideoComposition()
 videoComposition.renderSize = videoSize
 videoComposition.frameDuration = CMTime(value: 1, timescale: 30)
 videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: outputLayer)
        
 let instruction = AVMutableVideoCompositionInstruction()
 instruction.timeRange = CMTimeRange(start: .zero, duration: asset.duration)
 videoComposition.instructions = [instruction]
 let layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: assetTrack)
 layerInstruction.setTransform(assetTrack.preferredTransform, at: .zero)
 instruction.layerInstructions = [layerInstruction]

然后我以与第一次导出相同的方式导出视频。

问题是当我结合它时。 如果我只使用第二种方法导出一些示例视频,则会添加到视频的叠加层,并且一切都符合预期。如果我使用第一种方法拼接视频,那么视频就会完美拼接。但是,当我结合这些方法时,生成的视频是黑色的空白屏幕(音频和叠加效果很好,生成的视频持续时间也很合适)。

4

1 回答 1

1

这个问题可能与AVVideoCompositionCoreAnimationTool(). 我能够通过在第二个函数中使用另一种技术在视频中添加叠加来解决这个问题。AVVideoCompositionCoreAnimationTool()我没有使用堆叠图层,而是使用了CIFilter类似的方法:

let watermarkFilter = CIFilter(name: "CISourceOverCompositing")!
let watermarkImage = CIImage(image: watermark)!
let videoComposition = AVVideoComposition(asset: asset) { (filteringRequest) in
    let source = filteringRequest.sourceImage
    watermarkFilter.setValue(source, forKey: kCIInputBackgroundImageKey)
    let widthScale = source.extent.width/watermarkImage.extent.width
    let heightScale = source.extent.height/watermarkImage.extent.height
    watermarkFilter.setValue(watermarkImage.transformed(by: .init(scaleX: widthScale, y: heightScale)), forKey: kCIInputImageKey)
    filteringRequest.finish(with: watermarkFilter.outputImage!, context: nil)
    }
于 2020-08-22T16:23:27.433 回答