2015-09-08 14 views
5

Pracuję z nakładką obrazu na efekt znaku wodnego w wideo przy użyciu Swift. Używam do tego celu AVFoundation, ale jakoś mi się to nie udaje.Nakładanie obrazu/tekstu w wideo swift

Poniżej mój kod nakładki obraz/tekst

let path = NSBundle.mainBundle().pathForResource("sample_movie", ofType:"mp4") 
    let fileURL = NSURL(fileURLWithPath: path!) 

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

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

    var error: NSError? 
    let compositionvideoTrack:AVMutableCompositionTrack = composition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID()) 
    compositionvideoTrack.insertTimeRange(vid_timerange, ofTrack: videoTrack, atTime: kCMTimeZero, error: &error) 

    compositionvideoTrack.preferredTransform = videoTrack.preferredTransform 

    // Watermark Effect 
    let size = videoTrack.naturalSize 

    let imglogo = UIImage(named: "image.png") 
    let imglayer = CALayer() 
    imglayer.contents = imglogo?.CGImage 
    imglayer.frame = CGRectMake(5, 5, 100, 100) 
    imglayer.opacity = 0.6 

    // create text Layer 
    let titleLayer = CATextLayer() 
    titleLayer.backgroundColor = UIColor.whiteColor().CGColor 
    titleLayer.string = "Dummy text" 
    titleLayer.font = UIFont(name: "Helvetica", size: 28) 
    titleLayer.shadowOpacity = 0.5 
    titleLayer.alignmentMode = kCAAlignmentCenter 
    titleLayer.frame = CGRectMake(0, 50, size.width, size.height/6) 

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

    let parentlayer = CALayer() 
    parentlayer.frame = CGRectMake(0, 0, size.width, size.height) 
    parentlayer.addSublayer(videolayer) 
    parentlayer.addSublayer(imglayer) 
    parentlayer.addSublayer(titleLayer) 

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

    // instruction for watermark 
    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 [AnyObject] 
    layercomposition.instructions = NSArray(object: instruction) as [AnyObject] 

    // create new file to receive data 
    let dirPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) 
    let docsDir: AnyObject = dirPaths[0] 
    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: 
      println("failed \(assetExport.error)") 
     case AVAssetExportSessionStatus.Cancelled: 
      println("cancelled \(assetExport.error)") 
     default: 
      println("Movie complete") 


      // play video 
      NSOperationQueue.mainQueue().addOperationWithBlock({() -> Void in 
       self.playVideo(movieDestinationUrl!) 
      }) 
     } 
    })  

przez ten kod, nie jestem osiągnięcia nakładki .... Nie wiem co robię źle ...

Pytania:

  • Czy w tym kodzie brakuje jakiejś rzeczy? Lub jakikolwiek problem z tym kodem?
  • Czy ten kod działa tylko z nagranym wideo lub wszystkimi filmami, w tym z galerii?
+0

Czy twój kiedykolwiek był w stanie rozwiązać ten problem? szukając tej samej odpowiedzi. – schnabler

+0

gdzie możesz to rozwiązać? – random

Odpowiedz

0

Dla mnie (co widzę w twoim kodzie), twój nie dodaje do ekranu parentlayer.

można utworzyć CALayer(), aby dodać videolayer, imglayer i titleLayer do nowej warstwy, ale nie dodać ten ostatni na ekranie.

yourView.layer.addSublayer(parentlayer) 

Nadzieja to pomóc

+0

sprawdź wiersz 'layercomposition.animationTool' ... gdzie przetwarza wideo z parentlayerem –

+0

Spróbuj użyć' layercomposition' zamiast 'composition' w' let assetExport = AVAssetExportSession (asset: composition, presetName: AVAssetExportPresetHighestQuality) ' –

+0

Czy możesz dodać swoje kompletne rozwiązanie jako odpowiedź. – SheffieldKevin

6

kodu podanego przez @El kapitana będzie działać. Brakuje tylko:

assetExport.videoComposition = layercomposition 

Możesz dodać tego prawa po konkretyzacji w AVAssetExportSession

UWAGA: Kod pierwotnie przewidziane będzie eksportować tylko ścieżkę wideo, ale nie ścieżkę dźwiękową. Jeśli potrzebujesz ścieżce audio można dodać coś takiego po skonfigurowaniu compositionvideoTrack:

let compositionAudioTrack:AVMutableCompositionTrack = composition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID()) 
    for audioTrack in audioTracks { 
     try! compositionAudioTrack.insertTimeRange(audioTrack.timeRange, ofTrack: audioTrack, atTime: kCMTimeZero) 
    } 
+0

Tak, znalazłem go, ale zapomniałem dodać tutaj :) –

+1

Słodki! Mam nadzieję, że pomoże to innym osobom z tym samym pytaniem. –

0

@Rey Hernandez to po prostu bardzo mi pomogło! Jeśli ktoś chce uzyskać dodatkowe wyjaśnienie, w jaki sposób dodać zasób audio do tego filmu wideo, to kod, aby je połączyć

Powiązane problemy