如何实时流式传输音频文件

Posted

技术标签:

【中文标题】如何实时流式传输音频文件【英文标题】:How to stream audio files in real time 【发布时间】:2019-01-17 15:58:37 【问题描述】:

我正在编写一个音频流服务器 - 类似于 Icecast,但我遇到了流音频文件的问题。代理音频工作正常(音频源实时连接并发送音频,然后通过 HTTP 传输到客户端),但是当我尝试流式传输音频文件时,它会快速通过 - 客户端最终将整个音频文件包含在其中他们的本地缓冲区。我希望他们在本地缓冲区中只有几十秒。

基本上,我怎样才能减慢通过 HTTP 发送音频文件的速度? 文件都是MP3。通过尝试硬编码的线程延迟等,我已经设法让它几乎正常工作......但这不是一个可持续的解决方案。

【问题讨论】:

您使用哪些 crate 来读取音频然后进行流式传输? 无,只是标准库文件方法打开文件,以及 TcpStream 流原始二进制数据 如果没有您目前拥有的minimal reproducible example,我们只能猜测。请考虑制作一个,包括您迄今为止为解决问题所做的尝试。 【参考方案1】:

如果您坚持使用 http,则可以使用分块传输编码并延迟发送数据包/块。这确实类似于硬编码thread::sleep,但您可以使用事件循环来确定何时发送下一个块而不是暂停线程。

您可能会遇到时间问题,也许您的睡眠逻辑导致的延迟比歌曲的运行时间更长。 YouTube 的逻辑与您所​​说的类似。看起来他们将视频分成多个 http 请求,当缓冲区太小时,前端客户端请求一个新块。将文件分解为多个 http 正文请求,然后在客户端重新组装它们可能具有您正在寻找的特征。

您可以简单地实现 http Range 标头并允许客户端仅请求 mp3 文件的特定 Range。 https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests

【讨论】:

【参考方案2】:

最简单的方法(到目前为止)是让客户端按需请求音频文件的块。 std::net::TcpStream(你说你正在使用的那个)没有限制传输速率的方法,所以除了使用硬编码的线程延迟之外,你没有很多选择来限制流后端。

例如,您可以让您的客户端存储一段音频,当收听该音频的用户在该段结束之前到达某个点(或向前跳过),客户端向服务器发出请求获取相关段。

这类似于现实世界的流媒体服务(如 Youtube)的工作方式,因为正如您所说,将整个文件存储在客户端是个坏主意。

【讨论】:

以上是关于如何实时流式传输音频文件的主要内容,如果未能解决你的问题,请参考以下文章

具有不同长度的音频文件的 HTTP 实时流式传输

通过 socket.io 流式传输实时音频

Qt 通过 TCP 套接字实时流式传输音频

从 URL 实时流式传输音频的 RadioKit 替代方案

如何在具有单独位置 url 和资源 url 的 swift 中从服务器实时流式传输音频?

将实时 Android 音频流式传输到服务器