2017-11-11 87 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)) 
       } 
      }