Setting multiple Volumes to each Video tracks using AudioMixInputParameters AVFoundation is not working in Swift iOS

前端 未结 2 507
余生分开走
余生分开走 2020-12-18 13:28

I am working on Video based Application in Swift. As per the requirement I have to select multiple Videos from Devi

相关标签:
2条回答
  • 2020-12-18 13:44

    Here is the working solution for my question:

    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)
            })
        }
    
    0 讨论(0)
  • 2020-12-18 14:07

    I found, that exporting an asset with preset of AVAssetExportPresetPassthrough doesn't have an impact on output volume. When I tried to use AVAssetExportPresetLowQuality, volume change successfully applied.

    I wish it is better documented somewhere :(

    The working code:

    // 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
    

    Tested this with multiple assetTrack insertions to the same compositionTrack, setting different volume for each insertion. Seems to be working.

    0 讨论(0)
提交回复
热议问题