将水印图像添​​加到视频中

时间:2015-11-22 13:53:20

标签: ios swift avfoundation watermark video-watermarking

我是AVFoundation的新手,我正在尝试为视频添加图片。但是我一直收到错误:failed Optional(Error Domain=AVFoundationErrorDomain Code=-11823 "Cannot Save" UserInfo={NSLocalizedDescription=Cannot Save, NSLocalizedRecoverySuggestion=Try saving again.}) 。我究竟做错了什么。这是我的代码:

func createVideo() {

    let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString

    let fileURL = NSURL(fileURLWithPath: "\(documentsPath)/\(self.randomVideoFileName).mov")

    let composition = AVMutableComposition()
    let vidAsset = AVURLAsset(URL: fileURL, options: nil)

    // get video track
    let vtrack =  vidAsset.tracksWithMediaType(AVMediaTypeVideo)
    let videoTrack:AVAssetTrack = vtrack[0]
    let vid_timerange = CMTimeRangeMake(kCMTimeZero, vidAsset.duration)


    do {
        let compositionvideoTrack:AVMutableCompositionTrack = composition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID())
        try compositionvideoTrack.insertTimeRange(vid_timerange, ofTrack: videoTrack, atTime: kCMTimeZero)

        compositionvideoTrack.preferredTransform = videoTrack.preferredTransform
    } catch {
        print(error)
    }

    //Get the video
    let fullSizeImage = videoTrack

    let newOverLayHeight = fullSizeImage.naturalSize.width / self.containerView!.frame.width * self.containerView!.frame.height

    UIGraphicsBeginImageContext(CGSizeMake(fullSizeImage.naturalSize.width, newOverLayHeight));
    self.containerView!.drawViewHierarchyInRect(CGRectMake(0, 0, fullSizeImage.naturalSize.width, newOverLayHeight), afterScreenUpdates: true)
    let overlayImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    let imglogo = UIImage(named: "image.png")
    let imglayer = CALayer()
    imglayer.contents = imglogo?.CGImage
    imglayer.frame = CGRectMake(0,fullSizeImage.naturalSize.height - newOverLayHeight, overlayImage.size.width, overlayImage.size.height)

    let videolayer = CALayer()
    videolayer.frame = CGRectMake(0, 0, fullSizeImage.naturalSize.width, fullSizeImage.naturalSize.height)

    let parentlayer = CALayer()
    parentlayer.frame = CGRectMake(0, 0, fullSizeImage.naturalSize.width, fullSizeImage.naturalSize.height)
    parentlayer.addSublayer(imglayer)

    let layercomposition = AVMutableVideoComposition()
    layercomposition.frameDuration = CMTimeMake(1, 30)
    layercomposition.renderSize = fullSizeImage.naturalSize
    layercomposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videolayer, inLayer: parentlayer)

    let instruction = AVMutableVideoCompositionInstruction()
    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, composition.duration)
    let videotrack = composition.tracksWithMediaType(AVMediaTypeVideo)[0] as AVAssetTrack
    let layerinstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videotrack)
    instruction.layerInstructions = NSArray(object: layerinstruction) as! [AVVideoCompositionLayerInstruction]
    layercomposition.instructions = NSArray(object: instruction) as! [AVVideoCompositionInstructionProtocol]


    //  create new file to receive data
    let docsDir: AnyObject = documentsPath
    let movieFilePath = docsDir.stringByAppendingPathComponent("result.mov")
    let movieDestinationUrl = NSURL(fileURLWithPath: movieFilePath)

    // use AVAssetExportSession to export video
    let assetExport = AVAssetExportSession(asset: composition, presetName:AVAssetExportPresetHighestQuality)
    assetExport!.outputFileType = AVFileTypeQuickTimeMovie
    assetExport!.outputURL = movieDestinationUrl
    assetExport!.exportAsynchronouslyWithCompletionHandler({
        switch assetExport!.status{
        case  AVAssetExportSessionStatus.Failed:
            print("failed \(assetExport!.error)")
        case AVAssetExportSessionStatus.Cancelled:
            print("cancelled \(assetExport!.error)")
        default:
            print("Movie complete")


            // save to photoalbum
            NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
                UISaveVideoAtPathToSavedPhotosAlbum(movieDestinationUrl.absoluteString,  self, "image:didFinishSavingWithError:contextInfo:", nil)
            })
        }
    })

}

2 个答案:

答案 0 :(得分:1)

Matt所述,您忘记删除输出文件(AVFoundation因某种原因拒绝覆盖文件)。那样做:

let movieDestinationUrl = NSURL(fileURLWithPath: movieFilePath)
_ = try? NSFileManager().removeItemAtURL(movieDestinationUrl)

这样可以解决错误,但由于您没有设置AVAssetExportSession videoComposition {/ p>},因此您还没有看到自己的水印

assetExport?.videoComposition = layercomposition  // important!

assetExport!.exportAsynchronouslyWithCompletionHandler({...})

答案 1 :(得分:0)

您好我已经在ObjectivC中完成了以下是我的代码...

string _siteURL = "https://intranet.co.uk";

        NetworkCredential _myCredentials = new NetworkCredential("user", "password", "https://intranet");

        ClientContext _clientContext = new ClientContext(_siteURL);

        _clientContext.Credentials = _myCredentials;
相关问题