2017-08-06 43 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