Compilation of video and audio

My question is: I use the function below to compose video and audio. I want to keep the video the original sound, but for some reason it goes away, I don’t know.

I got this function from this answer

I tried changing volumes right after adding AVMutableCompositionTrack , but it did not work

For instance:

 mutableVideoCompositionTrack.prefferedVolume = 1.0 mutableAudioCompositionTrack.prefferedVolume = 0.05 

But still you can only hear the audio file.

Function;

 private func mergeAudioAndVideo(audioUrl: URL, videoUrl: URL, completion: @escaping (Bool)->Void){ let mixComposition = AVMutableComposition() var mutableCompositionVideoTrack : [AVMutableCompositionTrack] = [] var mutableCompositionAudioTrack : [AVMutableCompositionTrack] = [] let totalVideoCompositionInstruction = AVMutableVideoCompositionInstruction() let videoAsset = AVAsset(url: videoUrl) let audioAsset = AVAsset(url: audioUrl) mutableCompositionVideoTrack.append(mixComposition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)) mutableCompositionAudioTrack.append(mixComposition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid)) mutableCompositionAudioTrack[0].preferredVolume = 0.05 mutableCompositionVideoTrack[0].preferredVolume = 1.0 let videoAssetTrack = videoAsset.tracks(withMediaType: AVMediaTypeVideo)[0] let audioAssetTrack = audioAsset.tracks(withMediaType: AVMediaTypeAudio)[0] do { try mutableCompositionVideoTrack[0].insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAssetTrack.timeRange.duration), of: videoAssetTrack, at: kCMTimeZero) try mutableCompositionAudioTrack[0].insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAssetTrack.timeRange.duration), of: audioAssetTrack, at: kCMTimeZero) }catch{ print("ERROR#1") } totalVideoCompositionInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, videoAssetTrack.timeRange.duration) let mutableVideoComposition = AVMutableVideoComposition() mutableVideoComposition.frameDuration = CMTimeMake(1, 30) mutableVideoComposition.renderSize = CGSize(width: 1280, height: 720) //exporting savePathUrl = try! FileManager.default.url(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("merged").appendingPathExtension("mov") let assetExport = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)! assetExport.outputFileType = AVFileTypeMPEG4 assetExport.outputURL = savePathUrl assetExport.shouldOptimizeForNetworkUse = true do { try FileManager.default.removeItem(at: savePathUrl) }catch { print(error) } assetExport.exportAsynchronously { switch assetExport.status{ case .completed: print("completed") completion(true) default: print("failed \(assetExport.error!)") completion(false) } } } 
0
source share
2 answers

You can adjust the volume for video and audio separately @Faruk, here is a little code for this.

  //Extract audio from the video and the music let audioMix: AVMutableAudioMix = AVMutableAudioMix() var audioMixParam: [AVMutableAudioMixInputParameters] = [] let assetVideoTrack: AVAssetTrack = assetVideo.tracksWithMediaType(AVMediaTypeAudio)[0] let assetMusicTrack: AVAssetTrack = assetMusic.tracksWithMediaType(AVMediaTypeAudio)[0] let videoParam: AVMutableAudioMixInputParameters = AVMutableAudioMixInputParameters(track: assetVideoTrack) videoParam.trackID = compositionAudioVideo.trackID let musicParam: AVMutableAudioMixInputParameters = AVMutableAudioMixInputParameters(track: assetMusicTrack) musicParam.trackID = compositionAudioMusic.trackID //Set final volume of the audio record and the music videoParam.setVolume(volumeVideo, atTime: kCMTimeZero) musicParam.setVolume(volumeAudio, atTime: kCMTimeZero) //Add setting audioMixParam.append(musicParam) audioMixParam.append(videoParam) //Add audio on final record //First: the audio of the record and Second: the music do { try compositionAudioVideo.insertTimeRange(CMTimeRangeMake(kCMTimeZero, assetVideo.duration), ofTrack: assetVideoTrack, atTime: kCMTimeZero) } catch _ { assertionFailure() } do { try compositionAudioMusic.insertTimeRange(CMTimeRangeMake(CMTimeMake(Int64(startAudioTime * 10000), 10000), assetVideo.duration), ofTrack: assetMusicTrack, atTime: kCMTimeZero) } catch _ { assertionFailure() } //Add parameter audioMix.inputParameters = audioMixParam let completeMovie = "\(docsDir)/\(randomString(5)).mp4" let completeMovieUrl = NSURL(fileURLWithPath: completeMovie) let exporter: AVAssetExportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality)! exporter.outputURL = completeMovieUrl exporter.outputFileType = AVFileTypeMPEG4 exporter.audioMix = audioMix exporter.exportAsynchronouslyWithCompletionHandler({ switch exporter.status { case AVAssetExportSessionStatus.Completed: print("success with output url \(completeMovieUrl)") case AVAssetExportSessionStatus.Failed: print("failed \(String(exporter.error))") case AVAssetExportSessionStatus.Cancelled: print("cancelled \(String(exporter.error))") default: print("complete") } }) 

}

+1
source

I get it. AVAsset , which downloads the video, seems to keep audio and video separate. So you can contact them by writing ``

 videoAsset.tracks(withMediaType: AVMediaTypeAudio)[0] //audio of a video videoAsset.tracks(withMediaType: AVMediaTypeVideo)[0] //video of a video(without sound) 

So, I added these lines to the code and it will work!

 var mutableCompositionBackTrack : [AVMutableCompositionTrack] = [] mutableCompositionBackTrack.append(mixComposition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid)) try mutableCompositionBackTrack[0].insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAssetTrack.timeRange.duration), of: backAssetTrack, at: kCMTimeZero) 

There is still a point that I don’t know how to do, and this sets the volumes of these audio assets. I will update this answer as soon as I find out how to do it.

+1
source

All Articles