ios - 使 AVMutableComposition 与图像(方面填充)和视频在方面适合
问题描述
我正在尝试使用始终大小为 CGSize(375, 667) 的图像制作新视频,但视频的大小将不同,并且 contentMode 为 .`aspectFit'。问题是我无法弄清楚如何使整个视频合成具有正确的大小(即图像大小),而是视频的自然大小和一堆奇怪的结果。(编辑说明:视频应该在视图中居中,就像普通 aspectFit 对 UIImageView 所做的那样......)
这是我要实现的目标的示例...请注意,我已经有了图像和视频,我需要做的就是用它们制作新视频。这就是它的样子(在图片中):
这是我目前正在尝试的代码,带有“背景”的占位符图像(资产中的随机 375、667 图像..):我想我可能在评论“重要的东西”周围做的事情不正确......但是我目前无法弄清楚:/
func makeVideo(fromVideoAt videoURL: URL, forName name: String, onComplete: @escaping (URL?) -> Void) {
let asset = AVURLAsset(url: videoURL)
let composition = AVMutableComposition()
guard
let compositionTrack = composition.addMutableTrack(
withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid),
let assetTrack = asset.tracks(withMediaType: .video).first
else {
print("Something is wrong with the asset.")
onComplete(nil)
return
}
do {
let timeRange = CMTimeRange(start: .zero, duration: asset.duration)
try compositionTrack.insertTimeRange(timeRange, of: assetTrack, at: .zero)
if let audioAssetTrack = asset.tracks(withMediaType: .audio).first,
let compositionAudioTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid) {
try compositionAudioTrack.insertTimeRange(timeRange, of: audioAssetTrack, at: .zero)
}
} catch {
print(error)
onComplete(nil)
return
}
compositionTrack.preferredTransform = assetTrack.preferredTransform
let videoInfo = orientation(from: assetTrack.preferredTransform)
//Important stuff potentially? general below:
let videoSize: CGSize
if videoInfo.isPortrait {
videoSize = CGSize(width: 720, height: 1280)
} else {
videoSize = CGSize(width: 720, height: 1280) //720.0, 1280 tiktok default..?
}
//the Background image:
let backgroundLayer = CALayer()
backgroundLayer.frame = CGRect(origin: .zero, size: videoSize) //videosize
backgroundLayer.contents = UIImage(named: "background")?.cgImage
backgroundLayer.contentsGravity = .resizeAspectFill
backgroundLayer.backgroundColor = UIColor.red.cgColor
//Video layer:
let videoLayer = CALayer()
// videoLayer.frame = CGRect(origin: .zero, size: CGSize(width: composition.naturalSize.width, height: composition.naturalSize.height)) //videosize
videoLayer.backgroundColor = UIColor.yellow.cgColor
print(composition.naturalSize, "<-- composition.naturalSize")
videoLayer.frame = CGRect(origin: .zero, size: CGSize(width: videoSize.width, height: composition.naturalSize.height))//CGRect(x: 0, y: 0, width: videoSize.width, height: composition.naturalSize.height)
//OutPutlayer putting the together?
let outputLayer = CALayer()
outputLayer.frame = CGRect(origin: .zero, size: CGSize(width: 720, height: 1280)) //videosize
outputLayer.backgroundColor = UIColor.white.cgColor
outputLayer.addSublayer(backgroundLayer)
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)
//Setting Up Instructions
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRange(start: .zero, duration: composition.duration)
videoComposition.instructions = [instruction]
let layerInstruction = compositionLayerInstruction(for: compositionTrack, assetTrack: assetTrack)
instruction.layerInstructions = [layerInstruction]
//EXPORTING
guard let export = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality) else {
print("Cannot create export session.")
onComplete(nil)
return
}
let videoName = UUID().uuidString
let exportURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(videoName).appendingPathExtension("mp4")
export.videoComposition = videoComposition
export.outputFileType = .mov
export.outputURL = exportURL
export.exportAsynchronously {
DispatchQueue.main.async {
switch export.status {
case .completed:
onComplete(exportURL)
default:
print("Something went wrong during export.")
print(export.error ?? "unknown error")
onComplete(nil)
break
}
}
}
}
解决方案
尝试使用此代码https://github.com/vabe1337/VBVideoEditor。它可以渲染像 TikTok、Instagram 这样的视频。
推荐阅读
- python - 使用 django usercreationform 的问题,而不是在 HTML 中呈现表单
- sql - 计算层次结构
- c++ - c ++交换数组的内容 - 选择排序
- amazon-web-services - 是否可以将 AWS cognito 托管 UI 与 Amazon Pinpoint 集成以进行分析?
- vb.net - 如何从具有可变数量的其他数字的数字中减去?
- c++ - 包含定义预处理器变量的不同文件
- python - 隔离出现术语的句子
- sql - 将子句添加到 case 语句会导致查询拖动
- python - Streamlit Multiselect - 使用 DF 的两列作为选项并返回一列
- sql - 编写满足两种情况的单个 SQL 查询