我已经尝试了一段时间,现在如何从iOS中的URLSessionDataTask提供的数据中流式传输实时音频。
我声明了一个用于管理玩家操作的自定义类,它看起来如下所示:
import UIKit
import AVFoundation
class AudioDataPlayer: NSObject {
//MARK:- Variables
//MARK: Constants
enum Status{
case playing
case notPlaying
}
let audioPlayerQueue = DispatchQueue(label: "audioPlayerQueue", qos: DispatchQoS.userInteractive)
//MARK: Vars
private (set) var currentStatus:Status = .notPlaying
private var audioEngine: AVAudioEngine = AVAudioEngine()
private var streamingAudioPlayerNode: AVAudioPlayerNode = AVAudioPlayerNode()
private (set) var streamingAudioFormat: AVAudioFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 48000, channels: 2, interleaved: false)!
//MARK:- Constructor
override init() {
super.init()
}
//MARK:- Private methods
//MARK:- Public methods
func processData(_ data:Data) throws{
if currentStatus == .notPlaying{
do{
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [.allowAirPlay])
try AVAudioSession.sharedInstance().setActive(true)
if #available(iOS 11.0, *) {
try audioEngine.enableManualRenderingMode(.realtime, format: streamingAudioFormat, maximumFrameCount: 3072)
}
audioEngine.attach(streamingAudioPlayerNode)
audioEngine.connect(streamingAudioPlayerNode, to: audioEngine.mainMixerNode, format: streamingAudioFormat)
currentStatus = .playing
}
catch{
print("\(logClassName) ERROR -> \(error.localizedDescription)")
}
}
audioPlayerQueue.async {
if let audioPCMBuffer = data.makePCMBuffer(format: self.streamingAudioFormat){
self.streamingAudioPlayerNode.scheduleBuffer(audioPCMBuffer, completionHandler: {
//TODO
})
if !self.audioEngine.isRunning{
try! self.audioEngine.start()
self.streamingAudioPlayerNode.play()
}
}
else{
print("\(self.logClassName) TEST -> Ignoring data to play ...")
}
}
}
func stop(){
audioEngine.stop()
audioEngine.detach(streamingAudioPlayerNode)
currentStatus = .notPlaying
}
}管理传入数据的函数是'processData(_ data: data )‘,它是这样从另一个类调用的:
let processingQueue = DispatchQueue(label: "processingQueue", qos: DispatchQoS.userInteractive)
var audioDataPlayer:AudioDataPlayer = AudioDataPlayer()
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
processingQueue.async {
try! self.audioDataPlayer.processData(data)
}
}我从论坛和苹果文档网站上得到了代码。然而,也许我仍然不太明白它是如何工作的,没有声音从设备中传出……
音频数据为48K、16bit和2声道格式。
有什么想法吗?
发布于 2019-02-14 01:11:32
如果你的音频数据是16位的(假设是整数),你需要用pcmFormatInt16而不是pcmFormatFloat32来初始化AVAudioFormat。
而且对于这种格式来说,非交错似乎有点奇怪,所以您可能必须将interleaved设置为true。
https://stackoverflow.com/questions/54670067
复制相似问题