2017-03-20 4 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また、ドキュメントディレクトリにビデオファイルを書き出す際の変更もあります。上記のコードは、ドキュメントディレクトリ内の既存のビデオファイルを削除しません。したがって、別の動画を書き出すと、既存の動画を上書きすることはできません。だから私はファイルを削除します。以下はコードです

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

上記のwhatsの代わりにこのコードを試してみてください。私のようにこの問題に苦しんでいる誰のためにも。また、プリセットをのままにすることができます。AVAssetExportPresetHighestQuality

関連する問題