合并音频和视频 Swift
Posted
技术标签:
【中文标题】合并音频和视频 Swift【英文标题】:Merging audio and video Swift 【发布时间】:2016-11-03 14:51:57 【问题描述】:我正在尝试将 N 个音轨合并到一个视频文件中。 视频为 MP4 格式,所有音频均为 m4a。
所有的准备工作都很好,但是当导出完成时,总是失败。 这是我的代码:
func mixAudioAndVideo()
self.player?.pause()
let mixComposition = AVMutableComposition()
let paths = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
let docsDirect = paths[0]
for audioTrack in self.audioTracks
let musicFile = docsDirect.URLByAppendingPathComponent(audioTrack.audioName)
let audioAsset = AVURLAsset(URL: musicFile!, options: nil)
let audioTimeRange = CMTimeRangeMake(audioTrack.audioTime!, audioAsset.duration)
let compositionAudioTrack:AVMutableCompositionTrack = mixComposition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid)
do
try compositionAudioTrack.insertTimeRange(audioTimeRange, ofTrack: audioAsset.tracksWithMediaType(AVMediaTypeAudio).first!, atTime: audioTrack.audioTime!)
catch let error
print(error)
let videoAsset = AVURLAsset(URL: video!.movieURL, options: nil)
let videoTimeRange = CMTimeRangeMake(kCMTimeZero, videoAsset.duration)
let compositionVideoTrack = mixComposition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)
do
try compositionVideoTrack.insertTimeRange(videoTimeRange, ofTrack: videoAsset.tracksWithMediaType(AVMediaTypeVideo).first!, atTime: kCMTimeZero)
catch let error
print(error)
let videoName = "video\(self.audioTracks.count).mov"
let outputFilePath = docsDirect.URLByAppendingPathComponent(videoName)
let assetExport = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)
assetExport!.outputFileType = AVFileTypeQuickTimeMovie
assetExport!.outputURL = outputFilePath!
assetExport?.exportAsynchronouslyWithCompletionHandler(
dispatch_async(dispatch_get_main_queue())
print("finished exporting \(outputFilePath)")
print("status \(assetExport?.status)")
print("error \(assetExport?.error)")
SVProgressHUD.dismiss()
)
我得到的代码:
error Optional(Error Domain=NSURLErrorDomain Code=-1 "unknown error" UserInfo=NSLocalizedDescription=unknown error, NSUnderlyingError=0x170056140 Error Domain=NSOSStatusErrorDomain Code=-12935 "(null)")
【问题讨论】:
【参考方案1】:斯威夫特:3 先合并N个音轨
var mergeAudioURL = NSURL()
func mergeAudioFiles(audioFileUrls: NSArray)
let composition = AVMutableComposition()
for i in 0 ..< audioFileUrls.count
let compositionAudioTrack :AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID())
let asset = AVURLAsset(url: (audioFileUrls[i] as! NSURL) as URL)
let track = asset.tracks(withMediaType: AVMediaTypeAudio)[0]
let timeRange = CMTimeRange(start: CMTimeMake(0, 600), duration: track.timeRange.duration)
try! compositionAudioTrack.insertTimeRange(timeRange, of: track, at: composition.duration)
let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! as NSURL
self.mergeAudioURL = documentDirectoryURL.appendingPathComponent("Merge Audio.m4a")! as URL as NSURL
let assetExport = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A)
assetExport?.outputFileType = AVFileTypeAppleM4A
assetExport?.outputURL = mergeAudioURL as URL
removeFileAtURLIfExists(url: mergeAudioURL)
assetExport?.exportAsynchronously(completionHandler:
switch assetExport!.status
case AVAssetExportSessionStatus.failed:
print("failed \(assetExport?.error)")
case AVAssetExportSessionStatus.cancelled:
print("cancelled \(assetExport?.error)")
case AVAssetExportSessionStatus.unknown:
print("unknown\(assetExport?.error)")
case AVAssetExportSessionStatus.waiting:
print("waiting\(assetExport?.error)")
case AVAssetExportSessionStatus.exporting:
print("exporting\(assetExport?.error)")
default:
print("-----Merge audio exportation complete.\(self.mergeAudioURL)")
)
然后将音频与视频合并
var mergedAudioVideoURl = NSURL()
func mergeMutableVideoWithAudio(videoUrl:NSURL, audioUrl:NSURL)
let mixComposition : AVMutableComposition = AVMutableComposition()
var mutableCompositionVideoTrack : [AVMutableCompositionTrack] = []
var mutableCompositionAudioTrack : [AVMutableCompositionTrack] = []
let totalVideoCompositionInstruction : AVMutableVideoCompositionInstruction = AVMutableVideoCompositionInstruction()
//start merge
let aVideoAsset : AVAsset = AVAsset(url: videoUrl as URL)
let aAudioAsset : AVAsset = AVAsset(url: audioUrl as URL)
mutableCompositionVideoTrack.append(mixComposition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid))
mutableCompositionAudioTrack.append( mixComposition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid))
let aVideoAssetTrack : AVAssetTrack = aVideoAsset.tracks(withMediaType: AVMediaTypeVideo)[0]
let aAudioAssetTrack : AVAssetTrack = aAudioAsset.tracks(withMediaType: AVMediaTypeAudio)[0]
do
try mutableCompositionVideoTrack[0].insertTimeRange(CMTimeRangeMake(kCMTimeZero, aVideoAssetTrack.timeRange.duration), of: aVideoAssetTrack, at: kCMTimeZero)
try mutableCompositionAudioTrack[0].insertTimeRange(CMTimeRangeMake(kCMTimeZero, aVideoAssetTrack.timeRange.duration), of: aAudioAssetTrack, at: kCMTimeZero)
catch
totalVideoCompositionInstruction.timeRange = CMTimeRangeMake(kCMTimeZero,aVideoAssetTrack.timeRange.duration )
let mutableVideoComposition : AVMutableVideoComposition = AVMutableVideoComposition()
mutableVideoComposition.frameDuration = CMTimeMake(1, 30)
mutableVideoComposition.renderSize = CGSize(width: 1280, height: 720)
mergedAudioVideoURl = NSURL(fileURLWithPath: NSHomeDirectory() + "/Documents/FinalVideo.mp4")
let assetExport: AVAssetExportSession = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)!
assetExport.outputFileType = AVFileTypeMPEG4
assetExport.outputURL = mergedAudioVideoURl as URL
removeFileAtURLIfExists(url: mergedAudioVideoURl)
assetExport.shouldOptimizeForNetworkUse = true
assetExport.exportAsynchronously () -> Void in
switch assetExport.status
case AVAssetExportSessionStatus.completed:
print("-----Merge mutable video with trimmed audio exportation complete.\(self.mergedAudioVideoURl)")
case AVAssetExportSessionStatus.failed:
print("failed \(assetExport.error)")
case AVAssetExportSessionStatus.cancelled:
print("cancelled \(assetExport.error)")
default:
print("complete")
func removeFileAtURLIfExists(url: NSURL)
if let filePath = url.path
let fileManager = FileManager.default
if fileManager.fileExists(atPath: filePath)
do
try fileManager.removeItem(atPath: filePath)
catch let error as NSError
print("-----Couldn't remove existing destination file: \(error)")
【讨论】:
所以我的音频文件是 3 秒,我想将它添加到前后 30 秒的视频中,但它总是显示在前面,尝试编辑这个以尝试 mutableCompositionAudioTrack[0].insertTimeRange( CMTimeRangeMake(kCMTimeZero, 3, preferredTimescale: 1)), of: aAudioAssetTrack, at: kCMTimeZero)以上是关于合并音频和视频 Swift的主要内容,如果未能解决你的问题,请参考以下文章