我正在尝试在 Swift 中组合图像和视频,然后在 WhatsApp 上分享。但是,我遇到了一个问题,共享视频的质量似乎很低,并且模糊。
有趣的是,当其他具有类似功能的应用程序时,视频质量仍然很好。我的源代码是否存在可能导致此问题的潜在问题?
func mergeVideoWithFullSizeImage(videoURL: URL, image: UIImage, outputURL: URL, completion: @escaping (Bool, Error?) -> Void) {
// Remove the existing output file if it exists
removeFileIfExists(atURL: outputURL)
let videoAsset = AVURLAsset(url: videoURL)
let videoTrack = videoAsset.tracks(withMediaType: .video)[0]
let imageLayer = CALayer()
imageLayer.contents = image.cgImage
let videoSize = videoAsset.tracks(withMediaType: .video)[0].naturalSize
// Calculate the scale factor to fit the image to the video frame
let scaleFactor = max(videoSize.width / image.size.width, videoSize.height / image.size.height)
let scaledImageSize = CGSize(width: image.size.width * scaleFactor, height: image.size.height * scaleFactor)
// Position the image at the center of the video frame
let imagePosition = CGPoint(x: (videoSize.width - scaledImageSize.width) / 2, y: (videoSize.height - scaledImageSize.height) / 2)
// Set the layer's frame and position
imageLayer.frame = CGRect(origin: imagePosition, size: scaledImageSize)
let videoComposition = AVMutableVideoComposition()
videoComposition.renderSize = videoSize
videoComposition.frameDuration = CMTime(value: 1, timescale: 30) // 30 fps
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRange(start: .zero, duration: videoAsset.duration)
let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack)
instruction.layerInstructions = [videoLayerInstruction]
videoComposition.instructions = [instruction]
// Create a parent layer for both video and image layers
let parentLayer = CALayer()
let videoLayer = CALayer()
// Set the video layer's frame to match the video composition size
videoLayer.frame = CGRect(origin: .zero, size: videoSize)
// Add the video and image layers to the parent layer
parentLayer.addSublayer(videoLayer)
parentLayer.addSublayer(imageLayer)
// Set the parent layer as the composition's animation tool
videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer)
let mutableComposition = AVMutableComposition()
let videoTrackComposition = mutableComposition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
try? videoTrackComposition?.insertTimeRange(CMTimeRange(start: .zero, duration: videoAsset.duration), of: videoTrack, at: .zero)
let mainInstruction = AVMutableVideoCompositionInstruction()
mainInstruction.timeRange = CMTimeRange(start: .zero, duration: videoAsset.duration)
mainInstruction.layerInstructions = [videoLayerInstruction]
videoComposition.instructions = [mainInstruction]
// Use a WhatsApp-compatible export preset
let exportPreset = AVAssetExportPresetHighestQuality
guard let exportSession = AVAssetExportSession(asset: mutableComposition, presetName: exportPreset) else {
completion(false, nil)
return
}
exportSession.outputURL = outputURL
exportSession.outputFileType = .mp4
exportSession.shouldOptimizeForNetworkUse = true
exportSession.videoComposition = videoComposition
exportSession.exportAsynchronously {
DispatchQueue.main.async {
switch exportSession.status {
case .completed:
completion(true, nil)
case .failed:
completion(false, exportSession.error)
case .cancelled:
completion(false, nil)
default:
break
}
}
}
}
问题是你的图层,例如
parentLayer
,没有大小。您需要获取视频轨道的自然大小并将其用作图层的大小。