直接上代码了
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
}
})
}
}
网友评论