Phil
Phil

Reputation: 1107

Add watermark to recorded video and save

So I am trying to add a watermark to a previously recorded video using the following code, but when I view the video, there is no watermark. Can anyone help? I tried following the post at: iPhone Watermark on recorded Video.

    public func addWatermarkToVideo(url: NSURL, completion:(url: NSURL?) -> Void) {
    let videoAsset = AVURLAsset(URL: url)
    let mixComposition = AVMutableComposition()
    let compositionVideoTrack = mixComposition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)
    let clipVideoTrack: AVAssetTrack = videoAsset.tracksWithMediaType(AVMediaTypeVideo)[0]
    do {
        try compositionVideoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), ofTrack: clipVideoTrack, atTime: kCMTimeZero)
    } catch {
        print(error)
    }

    compositionVideoTrack.preferredTransform = videoAsset.tracksWithMediaType(AVMediaTypeVideo)[0].preferredTransform

    //Add watermark
    guard let myImage = UIImage(named: "Logo") else {
        completion(url: nil)
        return
    }
    let aLayer = CALayer()
    aLayer.contents = myImage.CGImage
    aLayer.frame = CGRectMake(5, 25, 100, 57)
    aLayer.opacity = 0.65

    let videoSize = videoAsset.tracksWithMediaType(AVMediaTypeVideo)[0].naturalSize
    let parentLayer = CALayer()
    let videoLayer = CALayer()
    parentLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height)
    videoLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height)
    parentLayer.addSublayer(videoLayer)
    parentLayer.addSublayer(aLayer)

    let videoComp = AVMutableVideoComposition()
    videoComp.renderSize = videoSize
    videoComp.frameDuration = CMTimeMake(1,30)
    videoComp.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, inLayer: parentLayer)

    let instruction = AVMutableVideoCompositionInstruction()
    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, mixComposition.duration)
    let videoTrack = mixComposition.tracksWithMediaType(AVMediaTypeVideo)[0]
    let layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack)
    instruction.layerInstructions = [layerInstruction]
    videoComp.instructions = [instruction]

    let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
    let documentsDirectory: AnyObject = paths[0]
    let dataPath = documentsDirectory.stringByAppendingPathComponent("VideoCache")

    if (!NSFileManager.defaultManager().fileExistsAtPath(dataPath)) {
        do {
            try NSFileManager.defaultManager().createDirectoryAtPath(dataPath, withIntermediateDirectories: false, attributes: nil)
        } catch {
            print("Couldn't create path")
        }
    }
    let tempURL = NSURL(fileURLWithPath: dataPath)
    let completeMovieUrl = tempURL.URLByAppendingPathComponent("tether-\(NSDate()).mov")

    if let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality) {
        exporter.outputURL = completeMovieUrl
        exporter.outputFileType = AVFileTypeMPEG4
        exporter.exportAsynchronouslyWithCompletionHandler({ () -> Void in
            switch exporter.status {
            case  .Failed:
                print("failed \(exporter.error)")
                completion(url: nil)
                break
            case .Cancelled:
                print("cancelled \(exporter.error)")
                completion(url: nil)
                break
            default:
                print("complete")
                completion(url: exporter.outputURL)
            }
        })
    }
}

Upvotes: 4

Views: 1703

Answers (1)

Gordon Childs
Gordon Childs

Reputation: 36072

You've forgotten to add your videoComposition to the AVAssetExportSession:

exporter.outputFileType = AVFileTypeMPEG4 // You had this
exporter.videoComposition = videoComp     // but had forgotten this
exporter.exportAsynchronouslyWithCompletionHandler({ // ...

Upvotes: 3

Related Questions