2017-08-06 46 views
2

我正在學習AVFoundation,並且在嘗試使用Swift 3中的疊加圖像保存視頻時遇到問題。使用AVMutableComposition我可以將圖像添加到視頻中,但是,視頻被放大和不約束自己的畫像尺寸的視頻拍攝於我試過:在Swift 3中爲視頻添加疊加層

  • 通過AVAssetTrack設置自然大小。
  • AVMutableVideoComposition renderFrame中將視頻限制爲縱向尺寸。
  • 將新視頻邊界鎖定到錄製的視頻寬度和高度。

下面的代碼除了我需要幫助的問題以外的工作。我試圖添加的圖像覆蓋了整個縱向視圖,並且邊緣周圍都有邊框。該應用程序也只允許肖像。

func processVideoWithWatermark(video: AVURLAsset, watermark: UIImage, completion: @escaping (Bool) -> Void) { 

    let composition = AVMutableComposition() 
    let asset = AVURLAsset(url: video.url, options: nil) 

    let track = asset.tracks(withMediaType: AVMediaTypeVideo) 
    let videoTrack:AVAssetTrack = track[0] as AVAssetTrack 
    let timerange = CMTimeRangeMake(kCMTimeZero, asset.duration) 

    let compositionVideoTrack:AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID()) 

    do { 
     try compositionVideoTrack.insertTimeRange(timerange, of: videoTrack, at: kCMTimeZero) 
     compositionVideoTrack.preferredTransform = videoTrack.preferredTransform 
    } catch { 
     print(error) 
    } 

//  let compositionAudioTrack:AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID()) 
//  
//  for audioTrack in asset.tracks(withMediaType: AVMediaTypeAudio) { 
//   do { 
//    try compositionAudioTrack.insertTimeRange(audioTrack.timeRange, of: audioTrack, at: kCMTimeZero) 
//   } catch { 
//    print(error) 
//   } 
//   
//  } 
//  
    let size = videoTrack.naturalSize 

    let watermark = watermark.cgImage 
    let watermarklayer = CALayer() 
    watermarklayer.contents = watermark 
    watermarklayer.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight) 
    watermarklayer.opacity = 1 

    let videolayer = CALayer() 
    videolayer.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight) 

    let parentlayer = CALayer() 
    parentlayer.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height) 
    parentlayer.addSublayer(videolayer) 
    parentlayer.addSublayer(watermarklayer) 

    let layercomposition = AVMutableVideoComposition() 
    layercomposition.frameDuration = CMTimeMake(1, 30) 
    layercomposition.renderSize = CGSize(width: screenWidth, height: screenHeight) 
    layercomposition.renderScale = 1.0 
    layercomposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videolayer, in: parentlayer) 

    let instruction = AVMutableVideoCompositionInstruction() 
    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, composition.duration) 

    let videotrack = composition.tracks(withMediaType: AVMediaTypeVideo)[0] as AVAssetTrack 
    let layerinstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videotrack) 

    layerinstruction.setTransform(videoTrack.preferredTransform, at: kCMTimeZero) 

    instruction.layerInstructions = [layerinstruction] 
    layercomposition.instructions = [instruction] 

    let filePath = NSTemporaryDirectory() + self.fileName() 
    let movieUrl = URL(fileURLWithPath: filePath) 

    guard let assetExport = AVAssetExportSession(asset: composition, presetName:AVAssetExportPresetHighestQuality) else {return} 
    assetExport.videoComposition = layercomposition 
    assetExport.outputFileType = AVFileTypeMPEG4 
    assetExport.outputURL = movieUrl 

    assetExport.exportAsynchronously(completionHandler: { 

     switch assetExport.status { 
     case .completed: 
      print("success") 
      print(video.url) 
      self.saveVideoToUserLibrary(fileURL: movieUrl, completion: { (success, error) in 
       if success { 
        completion(true) 
       } else { 
        completion(false) 

       } 
      }) 

      break 
     case .cancelled: 
      print("cancelled") 
      break 
     case .exporting: 
      print("exporting") 
      break 
     case .failed: 
      print(video.url) 
      print("failed: \(assetExport.error!)") 
      break 
     case .unknown: 
      print("unknown") 
      break 
     case .waiting: 
      print("waiting") 
      break 
     } 
    }) 

} 

回答

0

如果視頻層應填寫父層,你的videoLayer的frame不正確。您需要設置大小等於size而不是screenSize