36.音轨合成

直接上代码了

class func coalescing(backFile:String,file:String,fromEarphone:Bool,complete:@escaping (_ url:String)->Void) -> Void {
        
        // 第一步,必须创建 AVMutableComposition ,类似于很多 api 这个后缀也为 composition, 意思可以理解为合成物,但不是最终生成d 文件
        let composition:AVMutableComposition = AVMutableComposition.init()
        // 一个音频轨道
        let appendedAudioTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid)
        // 添加一个新的音频轨道
        let newAudioTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid)
        // 一个视频轨道
        let videoTrack = composition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: kCMPersistentTrackID_Invalid)
        
        // 此处创建的为音轨属性,可以理解为合成物所需要的原料,对音轨的加工都在这个方法里面进行,此处为音频合成 MediaType 为 AVMediaTypeAudio
        // 需求中背景 MV
        let backFileAsset = AVURLAsset.init(url: URL.init(fileURLWithPath: backFile))
        // 录制的音频
        let fileAsset = AVURLAsset.init(url: URL.init(fileURLWithPath: file))
        let start = CMTime.init(seconds: 0, preferredTimescale: fileAsset.duration.timescale)
        
        // 视频内容
        let mvTrack = backFileAsset.tracks(withMediaType: AVMediaType.video)[0]
        
        // 音轨
        let backTrack = backFileAsset.tracks(withMediaType: AVMediaType.audio)[0]
        let fileTrack = fileAsset.tracks(withMediaType: AVMediaType.audio)[0]
        // 根据录制时长来确定新的视频时长
        let timeRange = CMTimeRange.init(start: start, end: fileAsset.duration)
        do {
            try newAudioTrack?.insertTimeRange(timeRange, of: backTrack, at: kCMTimeZero)
            try appendedAudioTrack?.insertTimeRange(timeRange, of: fileTrack, at: kCMTimeZero)
            try videoTrack?.insertTimeRange(timeRange, of: mvTrack, at: kCMTimeZero)
        } catch let error {
            
            print("合成出错\(error)")
        }
        
        // 生成新的文件
        let exporSession = AVAssetExportSession.init(asset: composition, presetName: AVAssetExportPresetMediumQuality)
        
        if exporSession == nil {
            return
        } else {
            
            let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first
            let path = String.init(format: "%@/NewMV", paths!)
            let fileManager = FileManager.default
            
            let exists = fileManager.fileExists(atPath: path, isDirectory: nil)
            if !exists {
                
                do {
                    try fileManager.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
                } catch let error {
                    print("录音所在文件夹创建失败\(error)")
                }
            }
            let newPath = String.init(format: "%@/%@.mp4", path,String.getCurrentTimeName())
            
            exporSession?.outputURL = URL.init(fileURLWithPath: newPath)
            exporSession?.outputFileType    = AVFileType.mp4
            exporSession?.shouldOptimizeForNetworkUse   = true
            exporSession?.exportAsynchronously(completionHandler: {
                
                switch exporSession?.status {
                case .some(.completed):
                    print("完成")
                    complete(newPath)
                    break
                case .some(.failed):
                    print("失败")
                    
                    break
                case .some(.cancelled):
                    break
                default:
                    break
                }
            })
        }
    }

你可能感兴趣的:(36.音轨合成)