Javascript 用于实时流媒体的Web音频API?

Javascript 用于实时流媒体的Web音频API?,javascript,html,html5-audio,audio-streaming,web-audio-api,Javascript,Html,Html5 Audio,Audio Streaming,Web Audio Api,我们需要以不超过3-5秒的端到端延迟(假设200毫秒或更少的网络延迟)将音频(从医疗设备)流式传输到web浏览器。今天,我们使用浏览器插件(NPAPI)对音频流进行解码,过滤(高、低、带)和播放(通过Web套接字提供) 我们想替换插件。 我正在研究各种各样的功能,我们所需的大部分功能(播放、增益控制、过滤)似乎都可以在中使用。但是,我不清楚Web Audio API是否可以用于流媒体源,因为大多数Web Audio API都使用短声音和/或音频片段 网络音频API可以用于播放实时流式音频吗 更新

我们需要以不超过3-5秒的端到端延迟(假设200毫秒或更少的网络延迟)将音频(从医疗设备)流式传输到web浏览器。今天,我们使用浏览器插件(NPAPI)对音频流进行解码过滤(高、低、带)和播放(通过Web套接字提供)

我们想替换插件。

我正在研究各种各样的功能,我们所需的大部分功能(播放、增益控制、过滤)似乎都可以在中使用。但是,我不清楚Web Audio API是否可以用于流媒体源,因为大多数Web Audio API都使用短声音和/或音频片段

网络音频API可以用于播放实时流式音频吗

更新(2015年2月11日):

经过更多的研究和本地原型制作,我不确定使用Web audio API进行实时音频流是否可行。因为Web Audio API的解码音频数据并不是真正设计用来处理随机的音频数据块(在我们的例子中是通过WebSocket交付的)。它似乎需要整个“文件”才能正确处理它

见stackoverflow:

现在可以使用createMediaElementSource
元素连接到Web音频API,但根据我的经验,
元素会导致大量的端到端延迟(15-30s),并且似乎没有任何方法将延迟减少到3-5秒以下

我认为唯一的解决方案是将WebRTC与Web音频API结合使用。我希望避免WebRTC,因为它需要对服务器端实现进行重大更改

更新(2015年2月12日)第一部分

我还没有完全消除
标记(需要完成我的原型)。一旦我排除了这种可能性,我怀疑createScriptProcessor(已弃用但仍受支持)对于我们的环境来说将是一个不错的选择,因为我可以将ADPCM数据“流”(通过WebSocket)到浏览器,然后(在JavaScript中)将其转换为PCM。类似于使用createScriptProcessor对Scott的库(见下文)所做的操作。这种方法不需要像decodeAudioData方法那样将数据分成大小合适的“块”和关键时间

更新(2015年2月12日)第二部分:

经过更多测试后,我取消了
到Web音频API接口,因为根据源类型、压缩和浏览器的不同,端到端延迟可能为3-30秒。这就剩下了createScriptProcessor方法(参见下面Scott的帖子)或WebRTC。在与决策者讨论后,我们决定采用WebRTC方法。我想它会起作用的。但它需要更改我们的服务器端代码

我将标记第一个答案,这样“问题”就结束了

谢谢收听。您可以根据需要随意添加评论。

是的,Web音频API(以及AJAX或WebSocket)可用于流媒体

基本上,您可以下拉(或发送,在WebSocket的情况下)一些
n
长度的块。然后用Web Audio API对它们进行解码,并将它们依次排队播放


因为Web Audio API具有高精度的定时,如果您正确地进行调度,您将听不到每个缓冲区播放之间的任何“接缝”。

我编写了一个流式Web Audio API系统,在该系统中,我使用Web workers进行所有Web套接字管理,以与node.js通信,这样浏览器线程就可以简单地呈现音频。。。在笔记本电脑上运行很好,因为手机在web workers内部的web套接字实现方面落后了,所以您需要不少于棒棒糖的代码来运行它。。。我发布了

详细说明了如何通过每次移出最新的缓冲区来播放存储在阵列中的一组单独缓冲区:

如果通过
createBufferSource()
创建缓冲区,则它有一个
oneded
事件,您可以将回调附加到该事件,该事件将在缓冲区结束时触发。您可以这样做,一个接一个地播放数组中的各种块:

function play() {
  //end of stream has been reached
  if (audiobuffer.length === 0) { return; }
  let source = context.createBufferSource();

  //get the latest buffer that should play next
  source.buffer = audiobuffer.shift();
  source.connect(context.destination);

  //add this function as a callback to play next buffer
  //when current buffer has reached its end 
  source.onended = play;
  source.start();
}
希望有帮助。我仍在尝试如何让这一切顺利解决,但这是一个良好的开端,在许多在线帖子中都没有。你必须为你想要缓冲的每一个数据创建一个新的和两者(或至少后者)。。。我尝试循环相同的AudioBuffer,但一旦在上设置了
.AudioBuffer
,对AudioBuffer所做的任何修改都将变得无关紧要

(注意:这些类也有您应该查看的基类/父类(在文档中引用)。)


这是我的初步解决方案,我已经开始工作了(请原谅我在花了几个小时才开始工作之后,不想评论每件事),它工作得很好:

类主输出{
构造函数(computeSamplesCallback){
this.computeSampleCallback=computeSampleCallback.bind(this);
this.oncomputertimeoutbound=this.oncomputertimeout.bind(this);
this.audioContext=新的audioContext();
this.sampleRate=this.audioContext.sampleRate;
这个.channelCount=2;
这个.totalBufferDuration=5;
这个。计算时间=1;
此.bufferDelayDuration=0.1;
this.totalSamplesCount=this.totalBufferDuration*this.sampleRate;
this.computedurations=this.computeDuration*1000.0;
this.computeSamplesCount=this.computeDuration*this.sampleRate;
this.buffersToKeep=Math.ceil((this.totalBufferDuration+2.0*this.bufferDelayDuration)/
这是(计算化);
this.audioBufferSources=[];
this.computeSampleTimeout=null;
}
startPlaying(){
如果(this.audioBufferSources.length>0){
这个。停止铺设();