2017-03-20 2 views
1

AVFoundation 비디오에 텍스트 오버레이 및 워터 마크를 만들기 위해 사용하고 있습니다. 나는 몇 가지 어려움에 직면하고있다. 나는 Image/Text overlay in video swift 질문의 코드를 사용하고 있습니다. 그러나 나는 그것을 수정했다. 나는 기능 loadVideo 호출 할 때, 동영상이로드되지 않습니다. 나는 그것을 이해할 수 없다. 여기에 내가 뭘 잘못 내 코드신속하게 텍스트/이미지 오버레이로 비디오를로드 할 수 없습니다. 3

@IBAction func loadVideo(_ sender: Any) { 

    let path = Bundle.main.path(forResource: "SampleVideo", ofType:"mp4") 
    let fileURL = URL(fileURLWithPath: path!) 

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

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


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

    do { 
     _ = try compositionvideoTrack.insertTimeRange(vid_timerange, of: videoTrack, at: kCMTimeZero) 
    } catch { 
     print("error") 
    } 

    compositionvideoTrack.preferredTransform = videoTrack.preferredTransform 

    // Watermark Effect 
    let size = videoTrack.naturalSize 

    let imglogo = UIImage(named: "iosIcon.png") 
    let imglayer = CALayer() 
    imglayer.contents = imglogo?.cgImage 
    imglayer.frame = CGRect(x: 5, y: 5, width: 100, height: 100) 
    imglayer.opacity = 0.6 

    // create text Layer 
    let titleLayer = CATextLayer() 
    titleLayer.backgroundColor = UIColor.white.cgColor 
    titleLayer.string = "Subtitle Overlay Text" 
    titleLayer.font = UIFont(name: "Helvetica", size: 28) 
    titleLayer.shadowOpacity = 0.5 
    titleLayer.alignmentMode = kCAAlignmentCenter 
    titleLayer.frame = CGRect(x: 0, y: 50, width: size.width, height: size.height/6) 

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

    let parentlayer = CALayer() 
    parentlayer.frame = CGRect(x: 0, y: 0, width: size.width, height: 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, in: parentlayer) 

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



    // create new file to receive data 
    let dirPaths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) 
    let docsDir = dirPaths[0] as String 
    let movieFilePath = docsDir.appending("result.mov") 

    let movieDestinationUrl = URL(fileURLWithPath: movieFilePath) 
    //remove existing file 
    _ = try? FileManager().removeItem(at: movieDestinationUrl) 


    // use AVAssetExportSession to export video 
    guard let assetExport = AVAssetExportSession(asset: composition, presetName:AVAssetExportPresetHighestQuality) else {return} 
    assetExport.videoComposition = layercomposition 
    assetExport.outputFileType = AVFileTypeQuickTimeMovie 
    assetExport.outputURL = movieDestinationUrl 
    assetExport.exportAsynchronously(completionHandler: { 
     switch assetExport.status{ 
     case AVAssetExportSessionStatus.failed: 
      print("failed \(assetExport.error)") 
     case AVAssetExportSessionStatus.cancelled: 
      print("cancelled \(assetExport.error)") 
     case AVAssetExportSessionStatus.completed: 
      print("Completed") 
     default: 
      print("unknown") 
     } 
    }) 

} 

입니까? ExportAsset을 파일 디렉토리에 저장하는 데 문제가 있습니까? 마침내

답변

1

나는 내 자신의 질문에 대답하기로 결정. 위의 코드는 실패없이 실행되지만 시뮬레이터는 수출 약간의 시간이 소요됩니다. AVAssetExportPresetHighestQualityAVAssetExportPresetMediumQuality : 그래서 presetName을 변경했습니다. 또한 문서 디렉토리에 비디오 파일을 내보내는 수정 사항이 있습니다. 위 코드는 문서 디렉토리에있는 기존 비디오 파일을 제거하지 않습니다. 따라서 다른 비디오를 내보낼 때 기존 비디오를 덮어 쓸 수 없습니다. 그래서 파일을 삭제합니다. 아래 코드는 다음과 같습니다.

let dirPaths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) 
    let docsDir: AnyObject = dirPaths[0] as AnyObject 
    let movieFilePath = docsDir.appending("result.mp4") 
    let movieDestinationUrl = NSURL(fileURLWithPath: movieFilePath) 

    // must delete existing temporary file from file directory, also use try catch 
    do { 
     try FileManager.default.removeItem(at: movieDestinationUrl as URL) 
    } catch _ as NSError { 
     print("Error") 
    } 
0

layerInstuctions를 만든 후 위 코드 대신이 코드를 사용해보십시오. 내가 그랬던 것처럼 이것에 문제가있는 다른 누군가를 위해. 그리고 사전 설정을 유지할 수 있어야합니다. AVAssetExportPresetHighestQuality