Post

Replies

Boosts

Views

Activity

Reply to Crash When Exporting Video with Text Overlay
Thanks @Kjuly here is a Swift implementation based on your answer func merge(video videoPath: String, withForegroundImage foregroundImage: UIImage, completion: @escaping (URL?) -> Void) -> () {         let videoUrl = URL(fileURLWithPath: videoPath)         let videoUrlAsset = AVAsset(url: videoUrl)                  guard let videoTrack = videoUrlAsset.tracks(withMediaType: .video).first else { return }                  // Prepare watermark layer         let imageLayer = CALayer()         imageLayer.contents = foregroundImage.cgImage         imageLayer.frame = CGRect(x: videoTrack.naturalSize.width - 300, y: 0.0, width: 300, height: 300)         let unusedTrackID = videoUrlAsset.unusedTrackID()         // !!! NOTE#01: Use as additional layer here instead of animation layer.         let videoComposition = AVMutableVideoComposition(propertiesOf: videoUrlAsset)         videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(additionalLayer: imageLayer, asTrackID: unusedTrackID)         // Create video composition instruction         let mutableInstrucitons = AVMutableVideoCompositionInstruction()         mutableInstrucitons.timeRange = CMTimeRange(start: .zero, duration: videoUrlAsset.duration)         // - Watermark layer instruction         // !!! NOTE#02: Make this instruction track watermark layer by the `trackID`.         let mutableLayerInstruction = AVMutableVideoCompositionLayerInstruction()         mutableLayerInstruction.trackID = unusedTrackID         // - Video track layer instruction         let mutableVideoCompostionLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack)         // Watermark layer above video layer here.         mutableInstrucitons.layerInstructions = [mutableLayerInstruction, mutableVideoCompostionLayerInstruction]         videoComposition.instructions = [mutableInstrucitons]         // Export to file         let path = NSTemporaryDirectory().appending("mergedVideo.mp4")         let destinationFilePath = URL.init(fileURLWithPath: path)         do {             if FileManager.default.fileExists(atPath: destinationFilePath.path) {                 try FileManager.default.removeItem(at: destinationFilePath)                 print("removed")             }         } catch {             print(error)         }         let exportSession = AVAssetExportSession( asset: videoUrlAsset, presetName: AVAssetExportPresetHighestQuality)!         exportSession.videoComposition = videoComposition         exportSession.outputURL = destinationFilePath         exportSession.outputFileType = AVFileType.mp4         exportSession.exportAsynchronously { [weak exportSession] in             if let strongExportSession = exportSession {                 completion(strongExportSession.outputURL!)             }         }     } }
Sep ’22