通过WebSocket将音频流传输到Web音频播放器

问题描述 投票:2回答:1

我有一个可以正常工作的系统

  1. 将服务器上的音频产生到1秒的WAV文件中
  2. 读取WAV文件并通过网络套接字发送它
  3. Websocket将二进制数据发送到AudioContext.decodeAudioData
  4. 解码的音频被缓冲到4个数据包(4秒)
  5. 处理缓冲区并将其发送到AudioBufferSourceNode.start(time),其中时间=(clip_count *持续时间)

因此,如果我有4个音频片段,通话将看起来像

AudioBufferSourceNode.start(0);
AudioBufferSourceNode.start(1);
AudioBufferSourceNode.start(2);
AudioBufferSourceNode.start(3);

我以为这样可以安排4秒钟的音频,但是我似乎面临时钟问题,也许是因为我希望音频时钟是完美的。我已经使用了一个增益节点来消除每个声音片段(1秒)之间的喀嗒声,但是我立即或在很长一段时间后开始遇到计时问题。基本上,在最坏的情况下,我的音频会像这样播放

 ----------------------  -----------     -----------     -----------
| 1 second | 1 second |  |   950ms |     |  900ms  |    |   850ms  |
 ----------------------  -----------     -----------     -----------
                       gap          gap              gap

在此图中,“ 1秒”和“ #ms”是播放的音频量。它应始终为1秒。随着音频的发展,它似乎也在发展差距。我猜想,即使我告诉音频上下文将文件播放为正好为0,也可以,但其他预定的音频片段可能会或可能不会准时播放。

这是正确的吗,还是我的系统出了点问题?我是否可以安排音频剪辑在确切的正确时间播放的100%可靠性,还是我需要添加一些计算以计算出播放时间的+/-几毫秒?

javascript html audio web-audio-api
1个回答
0
投票

看来完成此任务的目的是AudioWorkletNode

根据AudioBufferSourceNode documentation

AudioBufferSourceNode接口是一个AudioScheduledSourceNode,它表示存储在AudioBuffer中的由内存中音频数据组成的音频源。对于回放对定时精度要求特别严格的音频,例如对于必须符合特定节奏并且可以保留在内存中而不是从磁盘或网络中播放的声音,它尤其有用。要播放需要精确定时但必须从网络流传输或从磁盘播放的声音,请使用AudioWorkletNode来实现其播放。

这种情况恰好实现了来自网络的流传输。 AudioBufferSourceNode是not设计的,可以通过网络即时更新。

什么可能导致不同步

  1. 根据javascript调度程序的性质,不能保证在准确的时间执行代码。该节点可能同时执行其他作业,这导致发送信息的延迟
  2. 计时器在发送所有数据后运行下一个刻度,这可能需要一些时间
  3. 客户端调度程序比服务器端的限制更多。通常,浏览器每秒可以执行约250个计时器(每4毫秒执行一次)。
  4. 使用的API不适用于该流程

建议

  1. 始终保留缓冲区。如果由于某种原因,缓冲区中的帧已经播放过,则可以更快地请求新帧。
  2. 动态增加缓冲区。收到两条消息后,就可以开始播放了,但是可以将动态缓冲消息的数量增加到大约15秒可能是合理的。]
  3. 首选其他工具来进行连接和数据传输。 Nginx将为您提供完美的服务。如果客户端连接速度较慢,它将“保留”节点,直到传输数据为止。
  4. [如果连接断开一秒钟(例如,在移动网络上),应该有一些东西可以从适当的帧中恢复状态,更新缓冲区,并在不中断的情况下进行所有操作。
© www.soinside.com 2019 - 2024. All rights reserved.