Tuesday, 5 June 2018

AVMutableVideoComposition output video shrinked

I'm a newbie to Swift. I'm trying to add a watermark with reference to code from SO. My original video resolution is 1280 X 720, but the output video is a shrinked version.

Here are the before and after pictures

Before

After

Here is my function to create a watermark.

private func watermark(video videoAsset:AVAsset, watermarkText text : String!, image : CGImage!, saveToLibrary flag : Bool, completion : ((_ status : AVAssetExportSessionStatus?, _ session: AVAssetExportSession?, _ outputURL : URL?) -> ())?) {
    DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async {

        let mixComposition = AVMutableComposition()

        let compositionVideoTrack = mixComposition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: Int32(kCMPersistentTrackID_Invalid))
        let clipVideoTrack = videoAsset.tracks(withMediaType: AVMediaTypeVideo)[0]
        do {
            try compositionVideoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: clipVideoTrack, at: kCMTimeZero)
        }
        catch {
            print(error.localizedDescription)
        }

        let videoSize = clipVideoTrack.naturalSize

        print("Video size", videoSize.height) //720
        print("Video size", videoSize.width) //1280

        let parentLayer = CALayer()
        let videoLayer = CALayer()
        parentLayer.frame = CGRect(x: 0.0,
                                   y: 0.0,
                                   width: videoSize.width,
                                   height: videoSize.height)
        videoLayer.frame = CGRect(x: 0.0,
                                  y: 0.0,
                                  width: videoSize.width,
                                  height: videoSize.height)
        parentLayer.addSublayer(videoLayer)

        if text != nil {
            let titleLayer = CATextLayer()
            titleLayer.backgroundColor = UIColor.red.cgColor
            titleLayer.string = text
            titleLayer.font = "Helvetica" as CFTypeRef
            titleLayer.fontSize = 15
            titleLayer.alignmentMode = kCAAlignmentCenter
            titleLayer.bounds = CGRect(x: 0, y: 0, width: videoSize.width, height: videoSize.height)
            parentLayer.addSublayer(titleLayer)
        } else if image != nil {
            let imageLayer = CALayer()
            imageLayer.contents = image

            let width: CGFloat = (self.imageView.image?.size.width)!
            let height: CGFloat = (self.imageView.image?.size.height)!

            print("Video size", height) //720
            print("Video size", width) //1280

            imageLayer.frame = CGRect(x: 0.0, y: 0.0, width: width, height: height)
            imageLayer.opacity = 0.65
            parentLayer.addSublayer(imageLayer)
        }

        let videoComp = AVMutableVideoComposition()
        videoComp.renderSize = videoSize
        videoComp.frameDuration = CMTimeMake(1, Int32(clipVideoTrack.nominalFrameRate))
        videoComp.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer)

        let instruction = AVMutableVideoCompositionInstruction()
        instruction.timeRange = CMTimeRangeMake(kCMTimeZero, mixComposition.duration)
        _ = mixComposition.tracks(withMediaType: AVMediaTypeVideo)[0] as AVAssetTrack

        let layerInstruction = self.videoCompositionInstructionForTrack(track: compositionVideoTrack, asset: videoAsset)

        instruction.layerInstructions = [layerInstruction]
        videoComp.instructions = [instruction]

        let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .long
        dateFormatter.timeStyle = .short
        let date = dateFormatter.string(from: Date())
        let url = URL(fileURLWithPath: documentDirectory).appendingPathComponent("watermarkVideo-\(date).mov")

        let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)
        exporter?.outputURL = url
        exporter?.outputFileType = AVFileTypeQuickTimeMovie
        exporter?.shouldOptimizeForNetworkUse = true
        exporter?.videoComposition = videoComp

        exporter?.exportAsynchronously() {
            DispatchQueue.main.async {

                if exporter?.status == AVAssetExportSessionStatus.completed {
                    let outputURL = exporter?.outputURL
                    if flag {

                        if UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(outputURL!.path) {
                            PHPhotoLibrary.shared().performChanges({
                                PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: outputURL!)
                            }) { saved, error in
                                if saved {
                                    completion!(AVAssetExportSessionStatus.completed, exporter, outputURL)
                                }
                            }
                        }
                    } else {
                        completion!(AVAssetExportSessionStatus.completed, exporter, outputURL)
                    }

                } else {
                    // Error
                    completion!(exporter?.status, exporter, nil)
                }
            }
        }
    }
}

While the size of watermark image is absolutely correct, the video is really shrinked.



from AVMutableVideoComposition output video shrinked

No comments:

Post a Comment