簡體   English   中英

iOS Swift從網絡流播放音頻(aac)

[英]iOS Swift playing audio (aac) from network stream

我正在開發一個iOS應用程序,我對iOS開發很新。 到目前為止,我已經使用VideoToolbox從網絡流中實現了h264解碼器,這非常困難。 現在我需要播放來自網絡的音頻流,但不涉及文件,只需從套接字直接讀取原始AAC流。 此流來自ffmpeg實例的輸出。 問題是我不知道如何從這開始,似乎關於這個主題的信息很少。 我已經嘗試過AVAudioPlayer但發現只是沉默。 我想我首先需要解壓縮流中的數據包,就像使用h264解碼器一樣。

我一直在嘗試使用AVAudioEngineAVAudioPlayerNode但沒有成功,與AVAudioPlayer相同。 有人可以給我一些指導嗎? 也許AudioToolbox AudioQueue

非常感謝你的幫助 :)

編輯:我正在玩AVAudioCompressedBuffer ,使用AVAudioEngineAVAudioNode沒有錯誤。 但是,我不知道這個輸出意味着什么:

inBuffer: <AVAudioCompressedBuffer@0x6040004039f0: 0/1024 bytes>

這是否意味着緩沖區為空? 我一直試圖以幾種方式提供這個緩沖區,但總是返回類似0/1024的東西。 我想我做得不對:

compressedBuffer.mutableAudioBufferList.pointee = audioBufferList

任何的想法?

謝謝!

編輯2:我正在編輯以反映我的代碼以解壓縮緩沖區。 也許有人可以指出我正確的方向。 注意:由此函數攝取的數據包實際上是在沒有ADTS標頭(9字節)的情況下傳遞的,但我也嘗試使用標頭傳遞它。

func decodeCompressedPacket(packet: Data) -> AVAudioPCMBuffer {

    var packetCopy = packet
    var streamDescription: AudioStreamBasicDescription = AudioStreamBasicDescription.init(mSampleRate: 44100, mFormatID: kAudioFormatMPEG4AAC, mFormatFlags: UInt32(MPEG4ObjectID.AAC_LC.rawValue), mBytesPerPacket: 0, mFramesPerPacket: 1024, mBytesPerFrame: 0, mChannelsPerFrame: 1, mBitsPerChannel: 0, mReserved: 0)
    let audioFormat = AVAudioFormat.init(streamDescription: &streamDescription)
    let compressedBuffer = AVAudioCompressedBuffer.init(format: audioFormat!, packetCapacity: 1, maximumPacketSize: 1024)

    print("packetCopy count: \(packetCopy.count)")
    var audioBuffer: AudioBuffer = AudioBuffer.init(mNumberChannels: 1, mDataByteSize: UInt32(packetCopy.count), mData: &packetCopy)
    var audioBufferList: AudioBufferList = AudioBufferList.init(mNumberBuffers: 1, mBuffers: audioBuffer)
    var mNumberBuffers = 1
    var packetSize = packetCopy.count
    // memcpy(&compressedBuffer.mutableAudioBufferList[0].mBuffers, &audioBuffer, MemoryLayout<AudioBuffer>.size)
    // memcpy(&compressedBuffer.mutableAudioBufferList[0].mBuffers.mDataByteSize, &packetSize, MemoryLayout<Int>.size)
    // memcpy(&compressedBuffer.mutableAudioBufferList[0].mNumberBuffers, &mNumberBuffers, MemoryLayout<UInt32>.size)

    // compressedBuffer.mutableAudioBufferList.pointee = audioBufferList

    var bufferPointer = compressedBuffer.data

    for byte in packetCopy {
        memset(compressedBuffer.mutableAudioBufferList[0].mBuffers.mData, Int32(byte), MemoryLayout<UInt8>.size)
    }

    print("mBuffers: \(compressedBuffer.audioBufferList[0].mBuffers.mNumberChannels)")
    print("mBuffers: \(compressedBuffer.audioBufferList[0].mBuffers.mDataByteSize)")
    print("mBuffers: \(compressedBuffer.audioBufferList[0].mBuffers.mData)")


    var uncompressedBuffer = uncompress(inBuffer: compressedBuffer)
    print("uncompressedBuffer: \(uncompressedBuffer)")
    return uncompressedBuffer
}

因此,您認為您(很可能)需要解壓縮從流中接收的數據包。 我們的想法是將它們轉換為原始PCM格式,以便將其直接發送到音頻輸出。 這樣,您還可以將任何您想要的DSP /音頻操作應用於音頻流。


正如您所提到的,您可能需要查看AudioQueue方向,Apple Docs提供實時流式傳輸音頻的良好示例,盡管這是obj-c(在這種情況下我認為攜帶它可能是個好主意)這個在obj-c)。 這可能是開始的最佳場所(將obj-c連接到swift非常簡單 )。


再看看它在Swift中有AVAudioCompressedBuffer類似乎可以為你的情況處理AAC(如果你讓它工作就不需要解碼AAC),但是沒有直接的方法來設置緩沖區,因為它是用於我相信,只是一個存儲容器。 這是一個使用AVAudioCompressedBuffer和AVAudioFile的人一個工作示例(也許你可以將所有內容緩沖到后台線程中的文件中?我認為這將是過多的IO開銷)。

但是,如果解決這個OBJ中-C有一個崗位上如何設置AVAudioPCMBuffer(可能與AVAudioCompressedBuffer工作?)直接通過memset (那種digusting但在同一時間,可愛的如同一個嵌入式程序員自己)。

// make a silent stereo buffer  
AVAudioChannelLayout *chLayout = [[AVAudioChannelLayout alloc] initWithLayoutTag:kAudioChannelLayoutTag_Stereo];  
AVAudioFormat *chFormat = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32  
                                                          sampleRate:44100.0  
                                                          interleaved:NO  
                                                        channelLayout:chLayout];  

AVAudioPCMBuffer *thePCMBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:chFormat frameCapacity:1024];  

thePCMBuffer.frameLength = thePCMBuffer.frameCapacity;  

for (AVAudioChannelCount ch = 0; ch < chFormat.channelCount; ++ch) {  
    memset(thePCMBuffer.floatChannelData[ch], 0, thePCMBuffer.frameLength * chFormat.streamDescription->mBytesPerFrame);  
}  

我知道這是一個很好的選擇,似乎不是一個簡單的解決方案,但我認為obj-c AudioQueue技術將是我的第一站!

希望這可以幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM