播放实时音频流 - HTML5

3
我有一个桌面应用程序,通过websocket连接向浏览器流传输原始PCM数据。该流的格式如下:...\\x00\\x00\\x02\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\xff\\xff\\xff\\xff\\...
问题很简单:我能否使用Web Audio API / WebRTC / ...在HTML中播放这样的流?
欢迎任何建议! 代码编辑 这段代码播放随机生成的噪声:
function myPCMSource() { 
    return Math.random() * 2 - 3;
}

var audioContext;

try {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    audioContext = new AudioContext();
} catch(e) {
    alert('Web Audio API is not supported in this browser');
}

var bufferSize = 4096;
var myPCMProcessingNode = audioContext.createScriptProcessor(bufferSize, 1, 1);
myPCMProcessingNode.onaudioprocess = function(e) {
    var output = e.outputBuffer.getChannelData(0);
    for (var i = 0; i < bufferSize; i++) {
     output[i] = myPCMSource(); 
 }
}

所以将myPCMSource()更改为websocket流输入应该能使其正常工作。但是它没有。我没有收到任何错误信息,但API也没有播放任何声音或噪音。


不确定是否有现成的解决方案。但是可以使用WebAudioAPI及其ScriptNode实现。也许我应该坐下来写一个。您是否使用任何特定的框架来发射websocket流? - notthetup
1
我的应用程序是用Python编写的,我正在使用websocket-client库。我还发现了这篇文章,有人试图实现相同的功能(https://code.google.com/p/chromium/issues/detail?id=250989),但仍然没有成功。 - boortmans
2个回答

1
使用ScriptProcessorNode,但要注意如果主线程负载过高(运行您的JavaScript,绘制屏幕等的线程),它会出现故障。
此外,您的PCM流可能是int16格式,而Web Audio API以float32格式工作。请进行以下转换:
output_float[i] = (input_int16[i] / 32767);

即从[0; 65535]范围转换为[-1.0; 1.0]范围。编辑:我之前使用的是output_float[i] = (input_int16[i] / 32767 - 1);文章表明应该使用output_float[i] = (input_int16[i] / 32767);。现在它正常工作了!

好的,我正在尝试将我的流转换为字节数组,但还不正确。我的转换值在1:0和-1:0之间,但仍然存在NaN。我是用(parseInt(str.substring(0, 8)), 16) / 32767) - 1;进行转换的。有什么想法吗? - boortmans
1
从WebSocket获取ArrayBuffer,然后从中获取Uint16Array:var input_int16 = new Uint16Array(event.data);其中event是从websocket获取的事件。然后使用上面的转换代码。 - padenot

0

仅供记录,ScriptProcessorNode已被弃用。详情请参见MDN文章。该功能已被AudioWorkletsAudioWorkletNode接口所取代。

简而言之,ScriptProcessorNode在浏览器内部音频线程之外运行,这会产生至少一个帧(128个样本)的延迟。更糟糕的是,如果线程繁忙,ScriptProcessorNode通常无法及时响应,因此会不时地随机丢失数据。

Worklets基本上是特定任务的工作线程,可以在浏览器的一个内部线程(绘图、布局、音频等)中运行。音频worklets在音频线程中运行,并实现自定义音频节点的核心,然后通过WebAudio API正常公开。

注意:您还可以在worklets中运行WebAssembly来处理处理。

以上提供的解决方案仍然有用,因为基本思路是正确的,但最好使用音频工作线程。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接