2017-05-13 2 views
0

AVAssetExportSession을 사용하여 mutablecomposition을 내보내려고합니다. MTAudioProcessingTap을 사용하여 mutable 컴포지션의 오디오 데이터를 처리하고 오디오 데이터를 기반으로 AVVideoCompositionCoreAnimationTool을 사용하여 mutable 컴포지션의 일부 애니메이션을 수정합니다. 애니메이션이 오디오 데이터에 의존하기 때문에 실시간으로이 작업을 수행하고 싶습니다. AVPlayer를 사용하면 잘 작동하지만 AVAssetExportSession에서는 그렇지 않습니다. MTAudioProcessingTapProcessCallback에 수신 된 오디오 데이터가 AVAssetExportSession의 비디오와 동기화되지 않은 것 같습니다. 그래서 여기에 질문은, 그들이 AVAssetExportSession 동안 동기화가되기로되어 있는지 알 수 있습니까?AVAssetExportSession에 MTAudioProcessingTap 사용

여기 아래는 내 MTAudioProcessingTapProcessCallback

var tapProcess: MTAudioProcessingTapProcessCallback = { 
    (tap, numberFrames, flags, bufferListInOut, numberFramesOut, flagsOut) in 
      let status = MTAudioProcessingTapGetSourceAudio(tap, numberFrames, bufferListInOut, flagsOut, nil, numberFramesOut) 

      let viewController = MTAudioProcessingTapGetStorage(tap) 

      let viewController = Unmanaged<CanvasViewController>.fromOpaque(viewController).takeUnretainedValue() 

      DispatchQueue.main.sync { 
       // update my CALayer in viewController based on the audio data 
      } 
     } 

입니다 audiomix 설정하기위한 코드입니다

func setupAudioMix(audioTrack: AVAssetTrack) -> AVAudioMix { 
     var callbacks = MTAudioProcessingTapCallbacks(
      version: kMTAudioProcessingTapCallbacksVersion_0, 
      clientInfo: UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()), 
      init: tapInit, 
      finalize: tapFinalize, 
      prepare: tapPrepare, 
      unprepare: tapUnprepare, 
      process: tapProcess) 

     var tap: Unmanaged<MTAudioProcessingTap>? 
     let err = MTAudioProcessingTapCreate(kCFAllocatorDefault, &callbacks, kMTAudioProcessingTapCreationFlag_PreEffects, &tap) 

     print("err: \(err)\n") 
     if err == noErr { 
     } 

     let inputParams = AVMutableAudioMixInputParameters(track: audioTrack) 
     inputParams.audioTapProcessor = tap?.takeUnretainedValue() 

     let audioMix = AVMutableAudioMix() 
     audioMix.inputParameters = [inputParams] 

     return audioMix 
    } 

을 그리고 AVAssetExportSession에 audiomix를 첨부 :

exporter = AVAssetExportSession(asset: mutableComposition!, presetName: AVAssetExportPresetMediumQuality)! 
     exporter!.outputURL = exportUrl as URL 
     exporter!.videoComposition = videoComposition! 
     exporter!.audioMix = audioMix! 

     exporter!.outputFileType = AVFileTypeMPEG4 
     exporter!.shouldOptimizeForNetworkUse = true 

답변

0

아니, AVAssetExportSession 아무 약속도하지 않습니다이 오디오 탭은 이전, 이후 또는 이후에 호출됩니다. 유사하게 타이밍 된 비디오 프레임의 처리.

생각해 보지도 않고 AVAudioPlayer (AVPlayer?) - 어쩌면 당신은 그저 운이 좋았을 것입니다.

프레임을 생성하는 방법에 따라 AVAssetExportSession이 보통 재생 속도의 1 배보다 빠릅니다.

오디오와 동기화 된 비디오를 내보내려면 낮은 레벨 AVAssetWriter API가 필요할 것입니다.

+0

답변 해 주셔서 감사합니다. 작은 수정, 당신이 지적한 것처럼, 나는 AVAlayer 대신 AVAlayer를 의미했습니다. 내가 참조. AVAssetWriter를 사용하려고합니다. AVAssetWriter는 비디오 위의 CALayer 애니메이션 작성을 지원할 수 있어야합니까? 또한 AVPlayer는 오디오와 비디오가 뷰어와 동기화되어야한다고 생각합니다. 내 애니메이션도 동기화 된 것처럼 보입니다. – karyboy

+0

AVAssetWriter가 파일에 동시에 쓰는 것 같지 않습니다. 두 개의 AVAssetWriterInput (하나의 오디오 및 비디오)을 만들어 AVAssetWriter에 추가했습니다. AVAssetReaderAudioMixOutput 및 AVAssetReaderVideoCompositionOutput을 사용하여 copyNextSampleBuffer로 자산에서 읽습니다. AudioMix를 AVAssetReaderAudioMixOutput에 연결합니다. MTAudioProcessingTapProcessCallback은 CALayer를 업데이트합니다. 하지만 내 보낸 파일에서 동기화되지 않습니다. – karyboy

+0

CMSampleBufferGetOutputPresentationTimeStamp를 사용하여 각각의 CMSampleBuffer를 추가하기 전에 두 AVAssetWriterInput의 프레젠테이션 시간을 기록 했으므로 오디오 버퍼가 비디오 버퍼보다 ​​약 6 초 앞당겨졌습니다. 어떻게 든 동기화 된 상태로 유지할 수 있습니까? 내 코드가 어떻게 보이는지 https://pastebin.com/kTzpzm1D – karyboy