【问题标题】:Webaudio Playback from WebSocket has drop-outs来自 WebSocket 的 Webaudio Playback 有丢失
【发布时间】:2014-12-12 07:00:57
【问题描述】:

我有一个软件定义的收音机播放来自 WebSocket 服务器的音频流,以及一个使用数据并使用 AudioBufferSourceNode 播放的客户端。

它主要是有效的。唯一的问题是每隔几秒就会出现一次瞬时丢失,这可能是由创建每个连续的 AudioBufferSourceNode 实例所涉及的开销引起的。 WebAudio 草案规范说 AudioBuffer 应该用于播放不超过一分钟左右的声音,并且应该使用 MediaElementSourceNode 播放更长的声音。这对我不起作用,因为我需要从 WebSocket 源播放音频,而且我不知道如何让媒体元素(例如 HTML5 音频元素)与 WebSocket 一起工作。

也许我正在尝试通过将 AudioBufferSourceNode 实例串在一起并期望它们无缝地一个接一个地播放来做 WebAudio 无法支持的事情。但似乎应该有一种方法可以通过 WebAudio 播放 WebSocket 数据,而且确实auroa.js(连同aurora-websocket.js 插件)似乎可以做到这一点。我使用 aurora.js 编写了一个客户端,但遇到了其他问题,为此我在 Github 上创建了一个 auroa.js 问题。同时,我希望我可以在我的客户端中完成他们似乎已经完成的工作,使用 WebAudio 从 WebSocket 无缝播放数据。

这是我的代码的省略视图,以显示我正在使用的实现。

var context = ...
var gainNode = ...

var playBuffer = function(buf) {
   var source = context.createBufferSource();
   source.buffer = buf;
   source.connect(gainNode);
   source.start();
};

var socket = ...
socket.binaryType = 'arraybuffer';
socket.addBinaryListener(function (data) {
     context.decodeAudioData(data, playBuffer);
});
socket.connect...

我还尝试了一个实现,其中我跟踪来自 WebSocket 的传入缓冲区,并在从前一个 AudioBufferSourceNode 接收到“结束”事件之后通过 AudioBufferSourceNode 接收到的顺序播放它们。这与上述实现具有相同的丢失问题。

【问题讨论】:

    标签: javascript websocket web-audio-api aurora.js


    【解决方案1】:

    您的流真的保证在每个网络块中获得完整的音频文件吗? (decodeAudioData 不适用于部分 MP3 块。)

    看起来(从上面的代码 sn-p)您只是依靠网络计时来让流块在正确的时间开始?保证不会正确排列;您需要在流中保留一点延迟(以处理不一致的网络),并仔细安排每个块。 (上面让我畏缩的一点是 source.start() - 没有时间参数可以让块一个接一个地安排。即:

    var nextStartTime = 0;
    
    function addChunkToQueue( buffer ) {
        if (!nextStartTime) {
            // we've not yet started the queue - just queue this up,
            // leaving a "latency gap" so we're not desperately trying
            // to keep up.  Note if the network is slow, this is going
            // to fail.  Latency gap here is 1 second.
            nextStartTime = audioContext.currentTime + 1; 
        }
        var bsn = audioContext.createBufferSource();
        bsn.buffer = buffer;
        bsn.connect( audioContext.destination );
        bsn.start( nextStartTime );
    
        // Ensure the next chunk will start at the right time
        nextStartTime += buffer.duration;
    }
    

    此外,根据您的块有多大,我想知道垃圾收集是否不会导致问题。您应该在分析器中检查它。

    onended 路径不会很好地工作;它依赖于 JS 事件处理,并且仅在音频系统播放完毕后触发;所以总会有差距。

    最后 - 如果声音流与默认音频设备的采样率不匹配,这将无法正常工作;总会有点击,因为 decodeAudioData 将重新采样到设备速率,这不会有一个完美的持续时间。它会工作,但可能会在块的边界处出现诸如点击之类的伪影。您需要一个尚未指定或实施的功能 - 可选的 AudioContext 采样率 - 才能解决此问题。

    【讨论】:

    • 谢谢。正如您所展示的那样,我确实处理了开始时间;我把它作为我试图让它工作的东西之一拿出来,却忘了把它放回去。所以我仍然有适当的时间辍学。我从 ogg/vorbis 切换到 wav/lpcm 数据,一切都很好。我同事写的 vorbis 编码器可能有问题;但我在使用 aurora.js 和 vorbis.js 时没有退出(但 vorbis.js 会在 13 分 25 秒后退出并出现内存错误)。未压缩的数据适用于我们的应用程序。
    • 至于采样率,我们的源采样率为 32000,AudioContext 报告的采样率为 41100。我在缓冲区边界上没有听到任何伪影,但这不是高保真音频。这是使用 RTL 设备的概念验证软件无线电,我们只是流式传输单声道。
    • 啊。大多数有损编码器都会填充数据,因此您可能会得到不一致的长度。
    • 你可能想在 web worker 中进行 ogg 解码
    • 如何在 web worker 中进行解码?网络工作者无法获取音频上下文来解码音频数据?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-05
    • 2019-08-07
    • 1970-01-01
    • 1970-01-01
    • 2016-03-25
    • 2013-12-14
    • 1970-01-01
    相关资源
    最近更新 更多