2017-03-07 77 views
1

我試圖從麥克風錄製音頻+然後將其與來自多個位置的視頻結合以創建具有來自麥克風的音頻的單個視頻。來自AVAudioFile的AVAsset有0個持續時間

使用AVCaptureDevice + AVCaptureSession有點波動,我想做語音識別,所以我已經轉移到AVCaptureSession進行視頻捕獲,我試圖做音頻w/AVAudioEngine(因爲我的理解是,很容易的SFSpeechRecognizer附加到AudioTap)

下面的代碼:在開始+停止之後

class AudioCaptureSession { 

    var engine = AVAudioEngine() 
    var outputFile : AVAudioFile! 

    func initAudioEngine() { 
     engine.stop() 
     engine.reset() 
     engine = AVAudioEngine() 

     do { 
      try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord) 
      let ioBufferDur = 128.0/44100.0 
      try AVAudioSession.sharedInstance().setPreferredIOBufferDuration(ioBufferDur) 
     } catch { 
      print("AVAudioSession setup error: \(error)") 
     } 
     let outputPath = NSTemporaryDirectory().appending(kTempAudioFilename) 
     let outputFile = URL(fileURLWithPath: outputPath, isDirectory: false) 
     if FileManager.default.fileExists(atPath: outputPath) { 
      do { 
       try FileManager.default.removeItem(at: outputFile) 
      } catch { 
       print("Filemanager can't delete the audio file: \(error)") 
      } 
     } 
     do { 
      print("Settings: \(engine.mainMixerNode.outputFormat(forBus: 0).settings)") 
      try self.outputFile = AVAudioFile(forWriting: outputFile, settings: engine.mainMixerNode.outputFormat(forBus: 0).settings) 
     } catch { 
      print("Can't make file for writing: \(error)") 
     } 
     let input = engine.inputNode! 
     let format = input.inputFormat(forBus: 0) 
     engine.connect(input, to: engine.mainMixerNode, format: format) 
     engine.prepare() 
     try! engine.start() 

    } 

    func startRecord() { 
     let mixer = engine.mainMixerNode 
     let format = mixer.outputFormat(forBus: 0) 

     mixer.installTap(onBus: 0, bufferSize: 1024, format: format) { (buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in 
      do { 
       try self.outputFile.write(from: buffer) 
      } catch { 
       print("Can't write audio to file: \(error)") 
      } 
     } 
    } 

    func stopRecord() { 
     print("Audio len: \(self.outputFile.length)") 
     engine.mainMixerNode.removeTap(onBus: 0) 
     do { 
      let f = try AVAudioFile(forReading: outputFile.url) 
      print("Length of reading file: \(f.length)") 
      print("Pos: \(f.framePosition)") 
     } catch { 
      print("Error getting file for reading: \(error)") 
     } 
     let asset = AVAsset(url: outputFile.url) 
     print("Stop recording asset duration: \(asset.duration)") 

    } 
} 

實施例的輸出是:

Audio len: 105840 
Length of reading file: 0 
Stop recording asset: CMTime(value: 0, timescale: 44100, flags: __C.CMTimeFlags(rawValue: 1), epoch: 0) 

所以你可以看到outputFile知道它有N個單位長,但是如果我打開一個文件來讀取它認爲它是0,並且AVAsset也認爲它有0個持續時間。我想知道如果該文件沒有保存?或者其他的東西?我完全不知所措,因爲我見過的所有內容都只是說「製作一個AVAudioFile,file.write(緩衝區),使用文件」,這顯然不起作用。我必須將其導出嗎?或者其他的東西?

回答

2

AVAudioFile沒有明確的關閉,所以當您完成寫入時,您需要通過設置self.outputFile = nil使其超出範圍。

+0

有沒有「finsihedWriting」回調還是它神奇般的罰款? – nickneedsaname

+0

你已經打開/讀/寫,就是這樣。理論上我不會說這很好,因爲它似乎取決於運行時/ ARC何時決定釋放「AVAudioFile」(當_is_那個?沒有人知道的時候)。在實踐中它可能很好。 –

+1

我認爲這個工程!編輯:這100%的作品。沒有「關閉」文件感覺很髒 – nickneedsaname