2016-10-06 2 views
2

Следующий код отлично работает, чтобы добавить логотип и текст в видео с помощью AVVideoCompositionCoreAnimationTool. Затем появился Свифт 3! Теперь иногда видео показывает с логотипом и текстом, иногда видео не отображается, когда оно экспортируется.Swift 3: проблема с AVVideoCompositionCoreAnimationTool для добавления водяного знака на видео

let videoComposition: AVMutableVideoComposition = AVMutableVideoComposition() 

    videoComposition.frameDuration = CMTimeMake(1, 60) 
    videoComposition.renderSize = CGSize(width: clipVideoTrack.naturalSize.height, height: clipVideoTrack.naturalSize.height) 


    let instruction: AVMutableVideoCompositionInstruction = AVMutableVideoCompositionInstruction() 

    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30)) 

    // transformer is applied to set the video in portrait otherwise it is rotated by 90 degrees 
    let transformer: AVMutableVideoCompositionLayerInstruction = 
     AVMutableVideoCompositionLayerInstruction(assetTrack: clipVideoTrack) 

    let t1: CGAffineTransform = CGAffineTransform(translationX: clipVideoTrack.naturalSize.height, y: -(clipVideoTrack.naturalSize.width - clipVideoTrack.naturalSize.height)/2) 

    let t2: CGAffineTransform = t1.rotated(by: CGFloat(M_PI_2)) 

    var finalTransform: CGAffineTransform = t2 

    transformer.setTransform(finalTransform, at: kCMTimeZero) 

    instruction.layerInstructions = NSArray(object: transformer) as! [AVVideoCompositionLayerInstruction] 

    videoComposition.instructions = NSArray(object: instruction) as! [AVVideoCompositionInstructionProtocol] 



    let mixComposition = AVMutableComposition() 
    let compositionVideoTrack = mixComposition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid) 


    do { 
     try compositionVideoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, asset.duration), of: clipVideoTrack, at: kCMTimeZero) 
    } catch { 
     print(error) 
    } 


    //Add watermark 


    let myImage = UIImage(named: "logo") 

    let aLayer = CALayer() 
    aLayer.contents = myImage!.cgImage 
    aLayer.frame = CGRect(x: (clipVideoTrack.naturalSize.height*(self.view.bounds.width-45))/self.view.bounds.width, y: (clipVideoTrack.naturalSize.height*(self.view.bounds.width-40))/self.view.bounds.width, width: (clipVideoTrack.naturalSize.height*40)/self.view.bounds.width, height: (clipVideoTrack.naturalSize.height*40)/self.view.bounds.width) 

    let titleLayer = CATextLayer() 
    titleLayer.string = "text" 
    titleLayer.font = UIFont(name: "helvetica", size: 0) 
    titleLayer.fontSize = clipVideoTrack.naturalSize.height/16 
    titleLayer.shadowOpacity = 0.5 
    titleLayer.alignmentMode = kCAAlignmentCenter 
    titleLayer.frame = CGRect(x: 0, y: 0, width: clipVideoTrack.naturalSize.height, height: clipVideoTrack.naturalSize.height/6) 
    titleLayer.display() 


    let videoSize = asset.tracks(withMediaType: AVMediaTypeVideo)[0].naturalSize 
    let parentLayer = CALayer() 
    let videoLayer = CALayer() 
    parentLayer.frame = CGRect(x: 0, y: 0, width: videoSize.height, height: videoSize.height) 
    videoLayer.frame = CGRect(x: 0, y: 0, width: videoSize.height, height: videoSize.height) 

    parentLayer.addSublayer(videoLayer) 
    parentLayer.addSublayer(aLayer) 
    parentLayer.addSublayer(titleLayer) 


    videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer) 



    do { try FileManager.default.removeItem(at: filePath) } 
    catch let error as NSError { 
     NSLog("\(error), \(error.localizedDescription)") 
    } 



    var exportUrl: URL = filePath 
    self.videoUrl = filePath as NSURL 


    var exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetMediumQuality) 

    exporter!.videoComposition = videoComposition 
    exporter!.outputFileType = AVFileTypeQuickTimeMovie 
    exporter!.outputURL = URL(fileURLWithPath: exportUrl.path) 


    exporter!.exportAsynchronously(completionHandler: { 

     DispatchQueue.main.async { 


      self.view.layer.addSublayer(self.avPlayerLayer) 

      let item = AVPlayerItem(url: exportUrl) 
      self.player.replaceCurrentItem(with: item) 

      if (self.player.currentItem != nil) { 
       print("Starting playback!") 
       self.player.play() 
      } 

     } 

    }) 

Это безупречно работало с предыдущей версией Swift, но теперь с быстрым 3 не работает.

ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАНИЕ: если я прокомментирую videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer), тогда видео будет экспортировано и будет успешно исполнено сверхурочно, но без какого-либо наложения.

+0

Что такое «трансформатор» в 'NSArray (object: transformer)'? и попробовали ли вы использовать код на устройствах iOS9? –

+0

@RhythmicFistman Я редактировал вопрос о трансформаторе. Вы сделали хороший вывод об устройствах iOS9, на самом деле я только что попробовал устройства iOS9 и, похоже, все работает нормально. Почему вы спросили об устройствах iOS9? Вы что, это проблема, связанная с iOS10? Большое спасибо :) – Sam

+1

Я спросил, потому что, похоже, в iOS 10 есть ошибки с 'AVAssetExportSession и композицией для видео. http://stackoverflow.com/a/39605744/22147 Помимо ожиданий iOS 10.1 http://stackoverflow.com/a/39746140/22147, есть некоторые обходные пути: http://stackoverflow.com/a/39780044/ 22147 –

ответ

1

Увидев, что код работает на iOS 9, это, вероятно, a bug in iOS 10.0, где AVAssetExportSessions не работают должным образом, когда у них есть videoComposition.

Некоторые из них сообщили, что все выглядит лучше в iOS 10.1 beta, а у других есть worked around the problem.

+0

Спасибо за помощь, соответствующее замечание и прямо к делу! – Sam

+0

Добро пожаловать! –

Смежные вопросы