MyCode:
class VideoComposeHelper {
static func create(assets: [AVAsset], textSections: [TextSectionView], duration: Double, onDone: @escaping (AVMutableComposition,AVMutableVideoComposition) -> Void) {
let composition = AVMutableComposition()
let videoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID:Int32(kCMPersistentTrackID_Invalid))!
let audioTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID:Int32(kCMPersistentTrackID_Invalid))!
var duration = 0.0
do {
for videoAsset in assets {
print("videoAsset",duration)
let cmTime = CMTimeMakeWithSeconds(duration, preferredTimescale: 1000)
// video
try videoTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: videoAsset.duration),
of: videoAsset.tracks(withMediaType:.video)[0] as AVAssetTrack, at: cmTime)
// audio
try audioTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: videoAsset.duration),
of: videoAsset.tracks(withMediaType:.audio)[0] as AVAssetTrack, at: cmTime)
duration += videoAsset.duraSec()
}
} catch {
print("darn")
}
let size = videoTrack.naturalSize
let fillRect = CGRect(x: 0, y: 0, width: size.height, height: size.width)
print("naturalSize",size)
let parentlayer = CALayer()
parentlayer.frame = fillRect
parentlayer.zPosition = 100
let videolayer = CALayer()
videolayer.frame = fillRect
parentlayer.addSublayer(videolayer)
videolayer.isHidden = false
parentlayer.isHidden = false
for textSection in textSections {
let imglayer = CALayer()
imglayer.contents = textSection.getImage().cgImage
imglayer.frame = fillRect
imglayer.opacity = 1
parentlayer.addSublayer(imglayer)
}
let layercomposition = AVMutableVideoComposition()
layercomposition.frameDuration = CMTimeMake(value: 4, timescale: 30)
layercomposition.renderSize = size
layercomposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videolayer, in: parentlayer)
// instruction for watermark
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRangeMake(start: .zero, duration: composition.duration)
let videotrack = composition.tracks(withMediaType: .video)[0] as AVAssetTrack
let layerinstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videotrack)
instruction.layerInstructions = [layerinstruction]
layercomposition.instructions = [instruction]
let FirstAssetScaleFactor = CGAffineTransform(scaleX: 1, y: 1)
layerinstruction.setTransform(videoTrack.preferredTransform.concatenating(FirstAssetScaleFactor), at: .zero)
onDone(composition,layercomposition)
}
func exportVideo(duration: Double, composition: AVMutableComposition, videoComposition: AVMutableVideoComposition) {
let outputURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
.appendingPathComponent("result.mp4")
if FileManager.default.fileExists(atPath: outputURL.path) {
do {
try FileManager.default.removeItem(at: outputURL)
} catch {
print(error)
}
}
print("outputURL",outputURL)
let exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetPassthrough)!
exporter.videoComposition = videoComposition
exporter.outputURL = outputURL
exporter.outputFileType = .mp4
exporter.shouldOptimizeForNetworkUse = true
let start = CMTimeMakeWithSeconds(0, preferredTimescale: 1000)
let range = CMTimeRangeMake(start: start, duration: CMTimeMakeWithSeconds(duration, preferredTimescale: 1000))
exporter.timeRange = range
exporter.exportAsynchronously {
switch exporter.status {
case .completed:
//self.checkDuration(for: fileName, at: outputURL)
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: outputURL)
}) { completed, error in
if let error = error {
print("Failed to save video in photos", error)
return
}
DispatchQueue.main.async {
//self.view.isUserInteractionEnabled = true
if completed {
print("Video has been saved to your photos.")
} else {
print("Video saving has NOT been completed")
}
}
}
case .failed:
print("failed with:", exporter.error ?? "no error")
case .cancelled: break
default: break
}
}
}
}
When I run the code, it saves plain video with no texts which supposed to be handled by parentlayer.