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

时间:2019-02-21 10:30:41

标签: ios swift audio avfoundation avassetexportsession

我正在研究Video中基于Application的{​​{1}}。根据要求,我必须从Swift中选择多个Videos,为每个Device Gallery设置不同的CIFilter效果和Volume,然后合并所有{ {1}},并且必须保存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。请提出建议。谢谢!

2 个答案:

答案 0 :(得分:2)

这是我的问题的可行解决方案:

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

答案 1 :(得分:1)

我发现,导出预设为AVAssetExportPresetPassthrough的资产不会影响输出量。当我尝试使用AVAssetExportPresetLowQuality时,成功应用了音量更改。

我希望更好地记录在某处:(

工作代码:

// Assume we have:
let composition: AVMutableComposition
var inputParameters = [AVAudioMixInputParameters]()

// We add a track
let trackComposition = composition.addMutableTrack(...)

// Configure volume for this track
let inputParameter = AVMutableAudioMixInputParameters(track: trackComposition)
inputParameter.setVolume(desiredVolume, at: startTime)

// It works even without setting the `trackID`
// inputParameter.trackID = trackComposition.trackID

inputParameters.append(inputParameter)

// Apply gathered `inputParameters` before exporting
let audioMix = AVMutableAudioMix()
audioMix.inputParameters = inputParameters

// I found it's not working, if using `AVAssetExportPresetPassthrough`,
// so try `AVAssetExportPresetLowQuality` first
let export = AVAssetExportSession(..., presetName: AVAssetExportPresetLowQuality)
export.audioMix = audioMix

对同一 compositionTrack 的多个 assetTrack 插入进行了测试,为每个插入设置了不同的音量。似乎正在工作。