1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- //
- // DubbingComposer.swift
- // dubit
- //
- // Created by zack on 16/12/20.
- // Copyright © 2016年 Chengdu Aitu Education Technology Ltd. All rights reserved.
- //
- import Foundation
- import AVFoundation
- class DubbingComposer {
- var timeline: [Double]
- var musicUrl: URL
- var recordsUrl: [String]
- var preTime: Double = 0
-
- init(timeline: [Double], musicUrl: URL, recordsUrl: [String]){
- self.timeline = timeline
- self.musicUrl = musicUrl
- self.recordsUrl = recordsUrl
- }
-
- func compose(_ output: URL, onSuccess successBlock: (()->())?, onFail failBlock:((_ message: String)->())? ) {
-
- //初始化合成器
- let composition = AVMutableComposition()
-
- //添加音乐轨道
- let musicTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid)
- let musicAsset = AVURLAsset(url: musicUrl, options: nil)
- let musicTimeRange = 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 recordTrackA = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid)
- let recordTrackB = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid)
-
- //将配音交替放入两条配音轨道
- for (i, url) in recordsUrl.enumerated() {
- let recordUrl = URL(fileURLWithPath: url)
- let recordAsset = AVURLAsset(url: recordUrl, options: nil)
- let recordRange = CMTimeRangeMake(start: CMTime.zero, duration: recordAsset.duration)
- let currentSec = timeline[i]
- let beginSec = currentSec > preTime ? currentSec - preTime : currentSec
- let beginTime = CMTimeMakeWithSeconds(beginSec, preferredTimescale: 100)
- if(recordAsset.tracks(withMediaType: AVMediaType.audio).count > 0){
- let recordAssetTrack = recordAsset.tracks(withMediaType: AVMediaType.audio).first!
- let recordTrack = i % 2 == 0 ? recordTrackA : recordTrackB
- do {
- try recordTrack?.insertTimeRange(recordRange, of: recordAssetTrack, at: beginTime)
- }
- catch{
- print("Composer error on record: \(i)")
- }
- }
- }
-
- // 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")
- })
- }
- }
- }
|