2017-11-11 90 views
0

我正在研究将多个视频剪辑合并为一个最终视频的应用程序。如果需要,我想让用户能够将单个剪辑静音(因此,只有部分最终合并的视频会被静音)。我已将AVAsset包装在名为“Video”的类中,该类具有“shouldMute”属性。AVMutableAudioMix将多个音量更改为单个轨道

我的问题是,当我将其中一个AVAssetTrack的音量设置为零时,它对于最终视频的剩余部分保持静音。这里是我的代码:

var completeDuration : CMTime = CMTimeMake(0, 1) 
    var insertTime = kCMTimeZero 
    var layerInstructions = [AVVideoCompositionLayerInstruction]() 
    let mixComposition = AVMutableComposition() 
    let audioMix = AVMutableAudioMix() 

    let videoTrack = 
     mixComposition.addMutableTrack(withMediaType: AVMediaType.video, 
             preferredTrackID: kCMPersistentTrackID_Invalid) 
    let audioTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid) 


    // iterate through video assets and merge together 
    for (i, video) in clips.enumerated() { 

     let videoAsset = video.asset 
     var clipDuration = videoAsset.duration 

     do { 
      if video == clips.first { 
       insertTime = kCMTimeZero 
      } else { 
       insertTime = completeDuration 
      } 


      if let videoAssetTrack = videoAsset.tracks(withMediaType: .video).first { 
       try videoTrack?.insertTimeRange(CMTimeRangeMake(kCMTimeZero, clipDuration), of: videoAssetTrack, at: insertTime) 
       completeDuration = CMTimeAdd(completeDuration, clipDuration) 
      } 

      if let audioAssetTrack = videoAsset.tracks(withMediaType: .audio).first { 
       try audioTrack?.insertTimeRange(CMTimeRangeMake(kCMTimeZero, clipDuration), of: audioAssetTrack, at: insertTime) 

       if video.shouldMute { 
        let audioMixInputParams = AVMutableAudioMixInputParameters() 
        audioMixInputParams.trackID = audioTrack!.trackID 
        audioMixInputParams.setVolume(0.0, at: insertTime) 
        audioMix.inputParameters.append(audioMixInputParams) 
       } 
      } 

     } catch let error as NSError { 
      print("error: \(error)") 
     } 

     let videoInstruction = videoCompositionInstructionForTrack(track: videoTrack!, video: video) 
     if video != clips.last{ 
      videoInstruction.setOpacity(0.0, at: completeDuration) 
     } 

     layerInstructions.append(videoInstruction) 
     } // end of video asset iteration 

如果我再添setVolume:atTime指令增大音量回1.0在剪辑的结尾,则第一个卷指令被完全忽略,并且在最大音量的整个视频播放。

换句话说,这是行不通的:

if video.shouldMute { 
        let audioMixInputParams = AVMutableAudioMixInputParameters() 
        audioMixInputParams.trackID = audioTrack!.trackID 
        audioMixInputParams.setVolume(0.0, at: insertTime) 
        audioMixInputParams.setVolume(1.0, at: completeDuration) 
        audioMix.inputParameters.append(audioMixInputParams) 
       } 

我已经设置了audioMix我AVPlayerItem和AVAssetExportSession两者。我究竟做错了什么?我能做些什么来让用户在合并到最终视频之前将单个剪辑的时间范围设为静音?

回答

0

显然我正在讨论这个错误。正如你在上面看到的,我的作品有两个AVMutableCompositionTracks:一个视频轨道和一个音轨。尽管我将一系列其他曲目的时间范围插入到这两个曲目中,但最终还是只有两个曲目。所以,我只需要一个AVMutableAudioMixInputParameters对象与我的一个音轨相关联。

我初始化了一个AVMutableAudioMixInputParameters对象,然后在插入每个剪辑的时间范围之后,我会检查它是否应该静音,并为剪辑的时间范围设置音量斜坡(时间范围的关系到整个音轨)。下面是我的片段迭代内容:

if let audioAssetTrack = videoAsset.tracks(withMediaType: .audio).first { 
       try audioTrack?.insertTimeRange(CMTimeRangeMake(kCMTimeZero, clipDuration), of: audioAssetTrack, at: insertTime) 

       if video.shouldMute { 
        audioMixInputParams.setVolumeRamp(fromStartVolume: 0.0, toEndVolume: 0.0, timeRange: CMTimeRangeMake(insertTime, clipDuration)) 
       } else { 
        audioMixInputParams.setVolumeRamp(fromStartVolume: 1.0, toEndVolume: 1.0, timeRange: CMTimeRangeMake(insertTime, clipDuration)) 
       } 
      }