gpt4 book ai didi

ios - 在 iOS 中播放通过网络连接逐渐流式传输的 WAV 文件

转载 作者:可可西里 更新时间:2023-11-01 03:54:08 27 4
gpt4 key购买 nike

我正在使用行为如下的第三方 API:

  • 我必须连接到它的 URL 并发出我的请求,其中涉及 POST 请求数据;
  • 然后远程服务器一次“分 block ”发回相应的 WAV 数据(我在 NSURLConnectionDataDelegate 的 didReceiveData 回调中收到)。

为了论证,我们所说的“ block ”是指数据的任意“下一部分”,不能保证它对应于音频的任何有意义的划分(例如,它可能不会与特定的多个音频帧对齐,每个 block 中的字节数只是一些任意数字,每个 block 可以不同,等等)。

现在——如果我错了,请纠正我,我不能简单地使用 AVAudioPlayer,因为我需要 POST 到我的 URL,所以我需要通过 NSURLConnection“手动”拉回数据。

那么...鉴于上述情况,当音频通过网络传输时,对我来说最轻松的播放方式是什么? (我很欣赏我可以连接所有字节数组,然后在最后将整个内容传递给 AVAudioPlayer——只是这会延迟播放的开始,因为我必须等待所有数据。)

最佳答案

我将对解决方案进行鸟瞰。我认为这将在很大程度上帮助您找到具体的编码解决方案。

iOS 提供了大量音频 API,其中一些可用于播放音频。您选择其中哪一个取决于您的特定要求。正如您已经写过的,AVAudioPlayer 类不适合您的情况,因为对于这个类,您需要在开始播放音频的那一刻就知道所有音频数据。显然,流媒体不是这种情况,因此我们必须寻找替代方案。

易用性和多功能性之间的良好平衡是 Audio Queue Services ,这是我为您推荐的。另一种选择是音频单元,但它们是低级 C API,因此使用起来不太直观,并且有很多缺陷。所以坚持使用音频队列。

音频队列允许您定义在需要更多音频数据播放时从 API 调用的回调函数 - 类似于您的网络代码的回调,当有可用数据时调用。

现在的难点是如何连接两个回调,一个提供数据,一个请求数据。为此,您必须使用缓冲区。更具体地说,一个队列(不要将此队列与音频队列的东西混淆。音频队列服务是 API 的名称。另一方面,queue I'm talking about next 是一个容器对象)。为清楚起见,我将其称为缓冲区队列。

要将数据填充到缓冲区队列中,您将使用网络回调函数,该函数从网络向您提供数据。数据将通过音频回调函数从缓冲区队列中取出,音频队列服务在需要更多数据时调用该函数。

你必须找到一个支持并发访问的缓冲区队列实现(又名它是线程安全的),因为它将从两个不同的线程访问,音频线程和网络线程。或者找到一个已经线程安全的缓冲区队列实现,你可以自己处理线程安全,例如通过在某个 dispatch queue (3rd kind of queue here; yes, Apple and IT love them) 上执行处理缓冲区队列的所有代码.

现在,如果有的话会发生什么

  • 调用音频回调并且您的缓冲区队列为空,或者

  • 调用网络回调并且您的缓冲区队列已满?

在这两种情况下,各自的回调函数都无法正常进行。如果没有可用的音频数据,则音频回调函数无法提供音频数据;如果缓冲区队列已满,则网络回调函数无法存储传入的数据。

在这些情况下,我会首先尝试阻止进一步执行,直到有更多数据可用或相应的空间可用于存储数据。在网络方面,这很可能会奏效。在音频方面,这可能会导致问题。如果它在音频方面引起问题,您有一个简单的解决方案:如果您没有数据,只需提供静音作为数据。这意味着您需要向音频队列服务提供零帧,它将以静默方式播放以填补空白,直到网络提供更多数据为止。这是所有流媒体播放器在音频突然停止时使用的概念,它会在某种旋转图标旁边告诉您“正在缓冲”,表示您必须等待,没人知道要等多久。

关于ios - 在 iOS 中播放通过网络连接逐渐流式传输的 WAV 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24502197/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com