小编典典

使用AudioMixInputParameters AVFoundation为每个视频轨道设置多个音量在Swift iOS中不起作用

swift

我正在Video根据Application进行工作Swift。按要求我必须选择多个Videos距离Device Gallery,设置不同的不同的CIFilter影响,并Volume为每个Video Asset然后合并所有的Videos并有保存Final Video。作为输出,当我将扮演Final Video那么Video声音volume应该随之改变。

我已经将所有选择的内容合并Video Assets为一个具有不同CIFilter效果的内容,但是我的问题是,当我尝试Volume为每个内容进行设置时,Video Clips则无法正常工作。我正在Volume为我的默认值Final Video。这是我的代码:

func addFilerEffectAndVolumeToIndividualVideoClip(_ assetURL: URL, video: VideoFileModel, completion : ((_ session: AVAssetExportSession?, _ outputURL : URL?) -> ())?){

        let videoFilteredAsset = AVAsset(url: assetURL)

        print(videoFilteredAsset)
        createVideoComposition(myAsset: videoFilteredAsset, videos: video)

        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, videoFilteredAsset.duration), of: videoFilteredAsset.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 = videoFilteredAsset.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.videoClipVolume, at: kCMTimeZero)

        //Add setting
        audioMixParam.append(videoParam)

        //Add audio on final record
        do {
            try compositionAudioVideo.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoFilteredAsset.duration), of: assetVideoTrack, at: kCMTimeZero)

        } catch _ {
            assertionFailure()
        }

        //Fading volume out for background music
        let durationInSeconds = CMTimeGetSeconds(videoFilteredAsset.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.videoClipVolume, timeRange: firstSecond)
        videoParam.setVolumeRamp(fromStartVolume: video.videoClipVolume, toEndVolume: 0, timeRange: lastSecond)

        //Add parameter
        audioMix.inputParameters = audioMixParam

        // Export part, left for facility
        let exporter = AVAssetExportSession(asset: videoFilteredAsset, presetName: AVAssetExportPresetHighestQuality)!
        exporter.videoComposition = videoFilterComposition
        exporter.outputURL = url
        exporter.outputFileType = AVFileTypeQuickTimeMovie

        exporter.audioMix = audioMix

        exporter.exportAsynchronously(completionHandler: { () -> Void in
            completion!(exporter, url)
        })

    }

之后,我再次使用一种方法来合并所有Video Clips使用方法AVAssetExportSession,在此我没有设置任何方法AudioMixInputParameters

Note:当我使用最后的合并方法设置音量时AVAssetExportSession's
AudioMixInputParameters,就会Volume变满Video

我的问题:是否可以volume为每个设置多个Video Clips。请提出建议。谢谢!


阅读 318

收藏
2020-07-07

共1个答案

小编典典

这是我的问题的工作解决方案:

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)
        })
    }
2020-07-07