iOS录制音频并实时将其拆分为文件 [英] IOS record audio and split it into files in real time

查看:477
本文介绍了iOS录制音频并实时将其拆分为文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个需要将音频流传输到服务器的应用程序.我想做的是将录制的音频分成多个块,然后在录制时上传.

I am making an app which needs to stream audio to a server. What I want to do is to divide the recorded audio into chunks and upload them while recording.

我用两个录音机来做,但是效果不佳.我可以听到这些块之间的差异(停顿了几毫秒).

I used two recorders to do that, but it didn't work well; I can hear the difference between the chunks (stops for couple of milliseconds).

我该怎么做?

推荐答案

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

Your problem can be broken into two pieces: recording and chunking (and uploading, but who cares).

要通过麦克风录音并写入文件,可以快速开始使用AVAudioEngineAVAudioFile.请参见下面的示例,该示例以设备的默认输入采样率(您可能需要对其进行速率转换)记录大块.

For recording from the microphone and writing to the file, you can get started quickly with AVAudioEngine and AVAudioFile. See below for a sample, which records chunks at the device's default input sampling rate (you will probably want to rate convert that).

当您谈论块之间的差异"时,您指的是将音频数据分成几部分的能力,这样当您将它们连接在一起时,您不会听到不连续的声音.例如LPCM音频数据可以在样本级别划分为多个块,但是LPCM比特率很高,因此您更有可能使用诸如adpcm(在iOS上称为ima4?),mp3或aac之类的打包格式.这些格式只能在数据包边界上划分,例如比如说64、576或1024个样本.如果您编写的块没有标题(通常用于mp3和aac,不确定ima4),则连接是微不足道的:只需完全像cat命令行工具那样将块首尾相连即可.可悲的是,在iOS上没有mp3编码器,因此aac可能会成为您的格式,但这取决于您的播放要求. iOS设备和Mac肯定可以播放它.

When you talk about the "difference between the chunks" you are referring to the ability to divide your audio data into pieces in such a way that when you concatenate them you don't hear discontinuities. e.g. LPCM audio data can be divided into chunks at the sample level, but the LPCM bitrate is high, so you're more likely to use a packetised format like adpcm (called ima4 on iOS?), or mp3 or aac. These formats can only be divided on packet boundaries, e.g. 64, 576 or 1024 samples, say. If your chunks are written without a header (usual for mp3 and aac, not sure about ima4), then concatenation is trivial: simply lay the chunks end to end, exactly as the cat command line tool would. Sadly, on iOS there is no mp3 encoder, so that leaves aac as a likely format for you, but that depends on your playback requirements. iOS devices and macs can definitely play it back.

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()
    }
}

这篇关于iOS录制音频并实时将其拆分为文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆