//
//  VideoComposer.swift
//  dubbing_lib
//
//  Created by weihong huang on 2020/9/18.
//

import Foundation
import AVFoundation

class VideoComposer {
    var videoUrl: URL
    var musicUrl: URL
    
    init(videoUrl: URL, musicUrl: URL){
        self.videoUrl = videoUrl
        self.musicUrl = musicUrl
    }
    
    func compose(_ output: URL, onSuccess successBlock: (()->())?, onFail failBlock:((_ message: String)->())? ) {
        
        //初始化合成器
        let composition = AVMutableComposition()
        
        var videoTimeRange:CMTimeRange?
        
        //为合成器添加视频轨道
        let videoTrack = composition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: kCMPersistentTrackID_Invalid)
        let videoAsset = AVURLAsset(url: videoUrl, options: nil)
        videoTimeRange = CMTimeRangeMake(start: CMTime.zero, duration: videoAsset.duration)
        do {
            try videoTrack?.insertTimeRange(videoTimeRange!, of: videoAsset.tracks(withMediaType: AVMediaType.video).first!, at: CMTime.zero)
        }
        catch {
            DispatchQueue.main.async(execute: {
                failBlock?("Fail on load video")
            })
            return
        }
            
        
        //添加音乐轨道
        let musicTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid)
        let musicAsset = AVURLAsset(url: musicUrl, options: nil)
        let musicTimeRange = videoTimeRange ?? CMTimeRangeMake(start: CMTime.zero, duration: musicAsset.duration)
        do {
            try musicTrack?.insertTimeRange(musicTimeRange, of: musicAsset.tracks(withMediaType: AVMediaType.audio).first!, at: CMTime.zero)
            print("创建音乐音轨成功")
        }
        catch {
            print("创建音乐音轨失败")
        }
        
        let manager = FileManager.default
        do {
            try manager.removeItem(at: output)
            print("删除旧输出成功")
        }
        catch {
            print("删除旧输出失败")
        }
        
        //输出到文件
        if let assetExport = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality) {
            assetExport.outputFileType = AVFileType.mp4
            assetExport.outputURL = output
            assetExport.shouldOptimizeForNetworkUse = true
            assetExport.exportAsynchronously(completionHandler: {
                if((assetExport.error) != nil){
                    print(assetExport.error!)
                    DispatchQueue.main.async(execute: {
                        failBlock?("Something wrong on composition")
                    })
                }else{
                    successBlock?()
                }
                return
            })

        }
        else {
            DispatchQueue.main.async(execute: {
                failBlock?("Something wrong on composition")
            })
        }
    }
}
