这是我的问题的工作解决方案:
func addVolumeToIndividualVideoClip(_ assetURL: URL, video: VideoFileModel, completion : ((_ session: AVAssetExportSession?, _ outputURL : URL?) -> ())?){ //Create Asset from Url let filteredVideoAsset: AVAsset = AVAsset(url: assetURL) video.fileID = String(video.videoID) //Get the path of App document Directory let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] let url = URL(fileURLWithPath: documentDirectory).appendingPathComponent("(video.fileID)_("FilterVideo").mov") let filePath = url.path let fileManager = FileManager.default do { if fileManager.fileExists(atPath: filePath) { print("FILE AVAILABLE") try fileManager.removeItem(atPath:filePath) } else { print("FILE NOT AVAILABLE") } } catch _ { } let composition: AVMutableComposition = AVMutableComposition() let compositionVideo: AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID()) let compositionAudioVideo: AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID()) //Add video to the final record do { try compositionVideo.insertTimeRange(CMTimeRangeMake(kCMTimeZero, filteredVideoAsset.duration), of: filteredVideoAsset.tracks(withMediaType: AVMediaTypeVideo)[0], at: kCMTimeZero) } catch _ { } //Extract audio from the video and the music let audioMix: AVMutableAudioMix = AVMutableAudioMix() var audioMixParam: [AVMutableAudioMixInputParameters] = [] let assetVideoTrack: AVAssetTrack = filteredVideoAsset.tracks(withMediaType: AVMediaTypeAudio)[0] let videoParam: AVMutableAudioMixInputParameters = AVMutableAudioMixInputParameters(track: assetVideoTrack) videoParam.trackID = compositionAudioVideo.trackID //Set final volume of the audio record and the music videoParam.setVolume(video.videoVolume, at: kCMTimeZero) //Add setting audioMixParam.append(videoParam) //Add audio on final record //First: the audio of the record and Second: the music do { try compositionAudioVideo.insertTimeRange(CMTimeRangeMake(kCMTimeZero, filteredVideoAsset.duration), of: assetVideoTrack, at: kCMTimeZero) } catch _ { assertionFailure() } //Fading volume out for background music let durationInSeconds = CMTimeGetSeconds(filteredVideoAsset.duration) let firstSecond = CMTimeRangeMake(CMTimeMakeWithSeconds(0, 1), CMTimeMakeWithSeconds(1, 1)) let lastSecond = CMTimeRangeMake(CMTimeMakeWithSeconds(durationInSeconds-1, 1), CMTimeMakeWithSeconds(1, 1)) videoParam.setVolumeRamp(fromStartVolume: 0, toEndVolume: video.videoVolume, timeRange: firstSecond) videoParam.setVolumeRamp(fromStartVolume: video.videoVolume, toEndVolume: 0, timeRange: lastSecond) //Add parameter audioMix.inputParameters = audioMixParam //Remove the previous temp video if exist let filemgr = FileManager.default do { if filemgr.fileExists(atPath: "(video.fileID)_("FilterVideo").mov") { try filemgr.removeItem(atPath: "(video.fileID)_("FilterVideo").mov") } else { } } catch _ { } //Exporte the final record’ let exporter: AVAssetExportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality)! exporter.outputURL = url exporter.outputFileType = AVFileTypeMPEG4 exporter.audioMix = audioMix exporter.exportAsynchronously(completionHandler: { () -> Void in completion!(exporter, url)// self.saveVideoToLibrary(from: filePath) }) }


