2017-03-19 4 views
0

オーディオをサーバーに流す必要があるアプリを作っています。録音したオーディオをチャンクに分割して録音中にアップロードしたいと思っています。それをするレコーダーは動作しませんが、私はチャンク(数ミリ秒の間停止)の違いを聞くことができます、どうすればいいですか?IOS録音オーディオをリアルタイムでファイルに分割する

答えて

2

あなたの問題は、録音とチャンク(およびアップロード、ただし誰が気にしますか)の2つに分けることができます。

マイクから録音してファイルに書き込む場合は、AVAudioEngineAVAudioFileですばやく開始できます。デバイスのデフォルトの入力サンプリングレートでチャンクを記録するサンプルについては、以下を参照してください(おそらくレート変換したいでしょう)。

"チャンク間の違い"について言えば、オーディオデータをつなぎ合わせて不連続音が聞こえないような方法でオーディオデータを分割することができます。例えばLPCMのオーディオデータはサンプルレベルでチャンクに分割できますが、LPCMのビットレートは高いので、adpcm(iOSではima4と呼ばれます)やmp3やaacなどのパケット化されたフォーマットを使用する可能性が高くなります。これらのフォーマットはパケット境界でしか分割できません。 64サンプル、576サンプル、または1024サンプル。あなたのチャンクがヘッダーなしで書かれている場合(通常のmp3とaac、ima4についてはわからない)、連結は簡単です。ちょうどcatコマンドラインツールと同じように、チャンクの端を終わりにします。悲しいことに、iOSではmp3エンコーダがないので、aacはあなたのための可能性の高いフォーマットですが、それは再生の必要条件に依存します。 iOSデバイスとMacは間違いなくそれを再生することができます。

import AVFoundation 

class ViewController: UIViewController { 

    let engine = AVAudioEngine() 

    struct K { 
     static let secondsPerChunk: Float64 = 10 
    } 

    var chunkFile: AVAudioFile! = nil 
    var outputFramesPerSecond: Float64 = 0 // aka input sample rate 
    var chunkFrames: AVAudioFrameCount = 0 
    var chunkFileNumber: Int = 0 

    func writeBuffer(_ buffer: AVAudioPCMBuffer) { 
     let samplesPerSecond = buffer.format.sampleRate 

     if chunkFile == nil { 
      createNewChunkFile(numChannels: buffer.format.channelCount, samplesPerSecond: samplesPerSecond) 
     } 

     try! chunkFile.write(from: buffer) 
     chunkFrames += buffer.frameLength 

     if chunkFrames > AVAudioFrameCount(K.secondsPerChunk * samplesPerSecond) { 
      chunkFile = nil // close file 
     } 
    } 

    func createNewChunkFile(numChannels: AVAudioChannelCount, samplesPerSecond: Float64) { 
     let fileUrl = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("chunk-\(chunkFileNumber).aac")! 
     print("writing chunk to \(fileUrl)") 

     let settings: [String: Any] = [ 
      AVFormatIDKey: kAudioFormatMPEG4AAC, 
      AVEncoderBitRateKey: 64000, 
      AVNumberOfChannelsKey: numChannels, 
      AVSampleRateKey: samplesPerSecond 
     ] 

     chunkFile = try! AVAudioFile(forWriting: fileUrl, settings: settings) 

     chunkFileNumber += 1 
     chunkFrames = 0 
    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let input = engine.inputNode! 

     let bus = 0 
     let inputFormat = input.inputFormat(forBus: bus) 

     input.installTap(onBus: bus, bufferSize: 512, format: inputFormat) { (buffer, time) -> Void in 
      DispatchQueue.main.async { 
       self.writeBuffer(buffer) 
      } 
     } 

     try! engine.start() 
    } 
} 
+0

スーパー解説仲間:)本当に役立っていること –

+0

感謝の男、「com.apple.coreaudio.avfaudio」:D – user3703910

+0

私は、このエラーで機能をバッファリングする書き込みを呼び出すときにクラッシュし、コードを見て理由: 'エラー-50' – user3703910

関連する問題