IOS实时录制音频并分割成文件

Posted

技术标签:

【中文标题】IOS实时录制音频并分割成文件【英文标题】:IOS record audio and split it into files in real time 【发布时间】:2017-08-10 15:49:27 【问题描述】:

我正在制作一个需要将音频流式传输到服务器的应用程序。我要做的是将录制的音频分成块并在录制时上传。

我用了两台录音机来做,但效果不好;我可以听到块之间的差异(停止几毫秒)。

我该怎么做?

【问题讨论】:

【参考方案1】:

您的问题可以分为两部分:记录和分块(以及上传,但谁在乎)。

对于从麦克风录制和写入文件,您可以使用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()
    

【讨论】:

超级解释兄弟:) 我查看了代码,当我调用写入缓冲区函数时它崩溃了这个错误:'com.apple.coreaudio.avfaudio',原因:'error -50' @user3703910 抱歉,这是我找到的第一个示例,我会找到更好的 @RhythmicFistman 我搜索了很多,但找不到任何使用 AVAudioEngine 录制音频的示例! , 我希望你能找到一些东西,谢谢你 工作正常。其实我需要什么。

以上是关于IOS实时录制音频并分割成文件的主要内容,如果未能解决你的问题,请参考以下文章

使用语音框架 iOS 从音频文件生成字幕

我可以使用 AVAudioEngine 从文件中读取,使用音频单元处理并写入文件,比实时更快吗?

iOS - 播放录制的音频失败并出现 OSStatus 错误 -43(未找到文件)

iOS:增加录制音频的音量

iOS 中使用 AudioConverterFillComplexBuffer 进行实时音频压缩

将录制的音频保存在文档目录中并创建一个包含所有音频文件的数据库