2016-07-11 18 views
6

Ich arbeite an Anwendung, die die mehrere Videos zusammen mit Hintergrund Audiospur kombiniert. Außerdem muss für verschiedene Videos ein anderer Audiopegel eingestellt werden.AVMutableAudioMixInputParameters nicht korrekt auf AudioMiX angewendet

Es folgt der Code für AssetItem Klasse & Assetmanager Klasse

// AssetItem Class 
class AssetItem : NSObject { 

var asset     : Asset! 
var assetEffect    : AssetEffectType! // Enum 
var assetSceneType   : SceneType!   // Enum 
var videoLength    : CMTime! 
var animationLayer   : AnyObject? 
var volumeOfVideoVoice  : Float = 0.0 
var volumeOfBGMusic   : Float = 0.0 

override init() { 
    super.init() 
    } 
} 

// AssetManager Class implementation 

class AssetManager{ 
var assetList = [AssetItem]() 
var composition      : AVMutableComposition! = AVMutableComposition() 
var videoComposition    : AVMutableVideoComposition? = AVMutableVideoComposition() 
var audioMix      : AVMutableAudioMix = AVMutableAudioMix() 

var transitionDuration    = CMTimeMakeWithSeconds(1, 600) // Default transitionDuration is 1 sec 

var compositionTimeRanges   : [NSValue] = [NSValue]() 

var passThroughTimeRangeValue  : [NSValue] = [NSValue]() 
var transitionTimeRangeValue  : [NSValue] = [NSValue]() 

var videoTracks      = [AVMutableCompositionTrack]() 
var audioTracks      = [AVMutableCompositionTrack]() 


// MARK: - Constructor 
override init() { 

    super.init() 

    let compositionTrackA   = self.composition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid)) 
    let compositionTrackB   = self.composition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid)) 

    let compositionTrackAudioA  = self.composition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid)) 
    let compositionTrackAudioB  = self.composition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid)) 

    self.videoTracks    = [compositionTrackA, compositionTrackB] 
    self.audioTracks    = [compositionTrackAudioA, compositionTrackAudioB] 

    } 

    func buildCompositionTrack(forExport : Bool){ 
     // This is the Method to Build Compositions 
    } 
} 

finden Sie die Methode für BuildingCompositions

func buildCompositionTrack(forExport : Bool) { 

    var cursorTIme = kCMTimeZero 
    var transitionDurationForEffect = kCMTimeZero 

    // Create a mutable composition instructions object 
    var videoCompositionInstructions = [AVMutableVideoCompositionInstruction]() 
    var audioMixInputParameters = [AVMutableAudioMixInputParameters]() 

    let timeRanges = calculateTimeRangeForAssetLayer() 
    self.passThroughTimeRangeValue = timeRanges.passThroughTimeRangeValue 
    self.transitionTimeRangeValue = timeRanges.transitionTimeRangeValue 

    let defaultMuteSoundTrackURL: NSURL = bundle.URLForResource("30sec", withExtension: "mp3")! 
    let muteSoundTrackAsset = AVURLAsset(URL: defaultMuteSoundTrackURL, options: nil) 
    let muteSoundTrack = muteSoundTrackAsset.tracksWithMediaType(AVMediaTypeAudio)[0] 

    for (index,assetItem) in self.assetsList.enumerate() { 
     let trackIndex = index % 2 

     let assetVideoTrack = assetItem.asset.movieAsset.tracksWithMediaType(AVMediaTypeVideo)[0] 

     let timeRange = CMTimeRangeMake(kCMTimeZero, assetItem.videoLength) 

     do { 
      try self.videoTracks[trackIndex].insertTimeRange(timeRange, ofTrack: assetVideoTrack, atTime: cursorTime) 
     } catch let error1 as NSError { 
      error = error1 
     } 
     if error != nil { 
      print("Error: buildCompositionTracks for video with parameter index: %@ and VideoCounts: %@ error: %@", ["\(index)", "\(self.assetsList.count)", "\(error?.description)"]) 
      error = nil 
     } 

     if assetItem.asset.movieAsset.tracksWithMediaType(AVMediaTypeAudio).count > 0 { 
      let clipAudioTrack = assetItem.asset.movieAsset.tracksWithMediaType(AVMediaTypeAudio)[0] 

      do { 
       try audioTracks[trackIndex].insertTimeRange(timeRange, ofTrack: clipAudioTrack, atTime: cursorTime) 
      } catch let error1 as NSError { 
       error = error1 
      } 
     }else { 
      do { 
       try audioTracks[trackIndex].insertTimeRange(timeRange, ofTrack: muteSoundTrack, atTime: cursorTime) 
      }catch let error1 as NSError { 
       error = error1 
      } 
     } 

     // The end of this clip will overlap the start of the next by transitionDuration. 
     // (Note: this arithmetic falls apart if timeRangeInAsset.duration < 2 * transitionDuration.) 

     if assetItem.assetEffect == FLIXAssetEffectType.Default { 

      transitionDurationForEffect = kCMTimeZero 
      let timeRange = CMTimeRangeMake(cursorTime, assetItem.videoLength) 
      self.compositionTimeRanges.append(NSValue(CMTimeRange: timeRange)) 
      cursorTime = CMTimeAdd(cursorTime, assetItem.videoLength) 
     } else { 
      transitionDurationForEffect = self.transitionDuration 
      let timeRange = CMTimeRangeMake(cursorTime, CMTimeSubtract(assetItem.videoLength, transitionDurationForEffect)) 
      self.compositionTimeRanges.append(NSValue(CMTimeRange: timeRange)) 
      cursorTime = CMTimeAdd(cursorTime, assetItem.videoLength) 
      cursorTime = CMTimeSubtract(cursorTime, transitionDurationForEffect) 
     } 

      videoCompositionInstructions.appendContentsOf(self.buildCompositionInstructions(index, assetItem : assetItem)) 

    } 

    if self.project.hasProjectMusicTrack() && self.backgroundMusicTrack != nil { 

     let url: NSURL = bundle.URLForResource("Music9", withExtension: "mp3")! 
     bgMusicSound = AVURLAsset(URL: url, options: nil) 
     backgroundAudioTrack = bgMusicSound.tracksWithMediaType(AVMediaTypeAudio)[0] 

     let compositionBackgroundTrack = self.composition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid)) 

     let soundDuration = CMTimeCompare(bgMusicSound.duration, self.composition.duration) 

     if soundDuration == -1 { 

      let bgMusicSoundTimeRange = CMTimeRangeMake(kCMTimeZero, bgMusicSound.duration) 

      let noOftimes = Int(CMTimeGetSeconds(self.composition.duration)/CMTimeGetSeconds(bgMusicSound.duration)) 
      let remainingTime = CMTimeGetSeconds(self.composition.duration) % CMTimeGetSeconds(bgMusicSound.duration) 

      var musicCursorTime = kCMTimeZero 

      for _ in 0..<noOftimes { 

       do { 
        try compositionBackgroundTrack.insertTimeRange(bgMusicSoundTimeRange, ofTrack: backgroundAudioTrack, atTime: musicCursorTime) 
        } catch let error1 as NSError { 
         error = error1 
        } 
       musicCursorTime = CMTimeAdd(bgMusicSound.duration, musicCursorTime) 
       } 
     } 

      let backgroundMusciMixInputParameters = AVMutableAudioMixInputParameters(track: compositionBackgroundTrack) 
      backgroundMusciMixInputParameters.trackID = compositionBackgroundTrack.trackID 

      // setting up music levels for background music track. 

      for index in 0 ..< Int(self.compositionTimeRanges.count) { 

      let timeRange = self.compositionTimeRanges[index].CMTimeRangeValue 
      let scene = self.assetsList[index].assetSceneType 

      let volumeOfBGMusic = self.assetsList[index].volumeOfBGMusic 
      var nextvolumeOfBGMusic : Float = 0.0 

       if let nextAsset = self.assetsList[safe: index + 1] { 
       nextvolumeOfBGMusic = nextAsset.volumeOfBGMusic 
       } 
       backgroundMusciMixInputParameters.setVolume(volumeOfBGMusic, atTime: timeRange.start) 
     backgroundMusciMixInputParameters.setVolumeRampFromStartVolume(volumeOfBGMusic, toEndVolume: nextvolumeOfBGMusic, timeRange: CMTimeRangeMake(CMTimeSubtract(timeRange.end,CMTimeMake(2, 1)), CMTimeMake(2, 1))) 
     } 

     audioMixInputParameters.append(backgroundMusciMixInputParameters) 

    } // End of If for ProjectMusic Check 


    for (index, assetItem) in self.assetsList.enumerate(){ 

     let trackIndex = index % 2 

     let timeRange = self.compositionTimeRanges[index].CMTimeRangeValue 
     let sceneType = assetItem.assetSceneType 
     let volumnOfVideoMusic = assetItem.volumeOfVideoVoice 

     let audioTrackParamater = AVMutableAudioMixInputParameters(track: self.audioTracks[trackIndex]) 

     audioTrackParamater.trackID = self.audioTracks[trackIndex].trackID 
     audioTrackParamater.setVolume(0.0, atTime: kCMTimeZero) // Statement 1 
     audioTrackParamater.setVolume(volumnOfVideoMusic, atTime: timeRange.start) // Statement 2 
     audioTrackParamater.setVolume(0.0, atTime: timeRange.end) // statement 3 
     audioMixInputParameters.append(audioTrackParamater) 
    } 

    self.audioMix.inputParameters = audioMixInputParameters 
    self.composition.naturalSize = self.videoRenderSize 
    self.videoComposition!.instructions = videoCompositionInstructions 
    self.videoComposition!.renderSize = self.videoRenderSize 
    self.videoComposition!.frameDuration = CMTimeMake(1, 30) 
    self.videoComposition!.renderScale = 1.0  // This is a iPhone only option. 

    } 

In obigen Code, Hintergrundmusik Levels gesetzt sind richtig, aber etwas schief läuft für Audiopegel von Videospuren. Ich habe DebugView hinzugefügt, um Debug Compositions zu helfen, alles sieht in der Debug-Ansicht perfekt aus, aber anders als Background Music Track ist Audio of Video nicht mehr hörbar. Gibt es etwas, was ich falsch mache?

Wenn ich Anweisung 1 von oben Code entfernen, dann ist es hörbar, aber jetzt sind sie alle auf Stufe 1.0 hörbar und respektieren nicht die eingestellten Pegel.

DebugView of Compositions and Audio Tracks

Antwort

4

Es sieht aus wie Sie ein neues AVAudioMixInputParameters für jeden „clip“ Objekt verwenden im AVMutableCompositionTrack. Dies wird nicht funktionieren: Das neue Objekt wird mit dem vorherigen Objekt mit der gleichen Track-ID in Konflikt geraten.

Sie sollten stattdessen für jede AVMutableCompositionTrack ein einzelnes AVAudioMixInputParameters-Objekt verwenden und dieses Objekt mit jedem gewünschten Rampenwert aktualisieren.

+0

Mann, Sie waren auf dem Zeichen Mann. Ich fühle mich jetzt so dumm. Ja, das war das Problem. Nach deinem Kommentar löste ich das Problem in 5 Minuten. Befindest du dich außerhalb von Indien? Würde dich gerne Biermann kaufen :-) – Solid