Merge audio and video Swift

I am trying to merge N audio tracks into a video file. The video is in MP4 format, and all audio is in m4a.

All preparation works well, but when the export ends, it always fails. Here is my code:

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() } }) } 

And the code I get:

 error Optional(Error Domain=NSURLErrorDomain Code=-1 "unknown error" UserInfo={NSLocalizedDescription=unknown error, NSUnderlyingError=0x170056140 {Error Domain=NSOSStatusErrorDomain Code=-12935 "(null)"}}) 
0
source share
1 answer

Swift: 3 first merging N audio tracks

 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)") } }) } 

then combine audio with video

 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)") } } } } 
+1
source

All Articles