Streaming 如何在浏览器中使用JavaScript播放音频字节数组(不是文件!)

Streaming 如何在浏览器中使用JavaScript播放音频字节数组(不是文件!),streaming,web,wav,Streaming,Web,Wav,主要是出于安全原因,我不允许在服务器上存储WAV文件以供浏览器访问。我拥有的是一个字节数组,它包含服务器上的音频数据(我相信是WAV文件的数据部分),我希望通过JavaScript(或小程序,但最好是JS)在浏览器上播放,我可以使用JSON-PRC发送整个字节[],或者我可以打开一个套接字来流式传输,但在任何一种情况下,我都不知道谁来播放字节[]在浏览器中?我想您可以通过HTML5音频API轻松实现这一点: 这个库可能也会派上用场,但我不确定它是否反映了最新的浏览器行为: 以下代码将在0.5和

主要是出于安全原因,我不允许在服务器上存储WAV文件以供浏览器访问。我拥有的是一个字节数组,它包含服务器上的音频数据(我相信是WAV文件的数据部分),我希望通过JavaScript(或小程序,但最好是JS)在浏览器上播放,我可以使用JSON-PRC发送整个字节[],或者我可以打开一个套接字来流式传输,但在任何一种情况下,我都不知道谁来播放字节[]在浏览器中?

我想您可以通过HTML5音频API轻松实现这一点:

这个库可能也会派上用场,但我不确定它是否反映了最新的浏览器行为:


以下代码将在0.5和2.0下播放正弦波。在您的按钮中或任意位置调用函数
play\u buffersource()

使用启用Web音频标志的Chrome进行测试。对于您的情况,您所需要做的只是将音频字节洗牌到
buf

<script type="text/javascript">
const kSampleRate = 44100; // Other sample rates might not work depending on the your browser's AudioContext
const kNumSamples = 16834;
const kFrequency  = 440;
const kPI_2       = Math.PI * 2;

function play_buffersource() {
    if (!window.AudioContext) {
        if (!window.webkitAudioContext) {
            alert("Your browser sucks because it does NOT support any AudioContext!");
            return;
        }
        window.AudioContext = window.webkitAudioContext;
    }

    var ctx = new AudioContext();

    var buffer = ctx.createBuffer(1, kNumSamples, kSampleRate);
    var buf    = buffer.getChannelData(0);
    for (i = 0; i < kNumSamples; ++i) {
        buf[i] = Math.sin(kFrequency * kPI_2 * i / kSampleRate);
    }

    var node = ctx.createBufferSource(0);
    node.buffer = buffer;
    node.connect(ctx.destination);
    node.noteOn(ctx.currentTime + 0.5);

    node = ctx.createBufferSource(0);
    node.buffer = buffer;
    node.connect(ctx.destination);
    node.noteOn(ctx.currentTime + 2.0);
}
</script>

const kSampleRate=44100;//其他采样率可能不起作用,具体取决于浏览器的音频上下文
常数kNumSamples=16834;
常数k频率=440;
常数kPI_2=Math.PI*2;
函数play_buffersource(){
如果(!window.AudioContext){
如果(!window.webkitadiocontext){
警报(“您的浏览器很糟糕,因为它不支持任何音频上下文!”);
返回;
}
window.AudioContext=window.webkitadiocontext;
}
var ctx=新的AudioContext();
var buffer=ctx.createBuffer(1,kNumSamples,kSampleRate);
var buf=buffer.getChannelData(0);
对于(i=0;i
参考资料:

如果需要对音频进行重采样,可以使用JavaScript重采样器:


如果您需要解码base64数据,有很多JavaScript base64解码器:

如果您在服务器上有字节,那么我建议您在服务器上创建某种处理程序,将字节作为wav文件流式传输到响应。此“文件”将只在服务器的内存中,而不在磁盘上。然后浏览器可以像处理普通wav文件一样处理它。
需要更多关于服务器堆栈的详细信息,以提供有关如何在您的环境中完成此操作的更多信息。

我通过以下代码实现了这一点。我将包含wav文件数据的字节数组传递给函数playByteArray。我的解决方案与Peter Lee的类似,但我无法让他在我的案例中工作(输出是乱码的),而这个解决方案对我来说效果很好。我验证了它可以在Firefox和Chrome中工作

window.onload = init;
var context;    // Audio context
var buf;        // Audio buffer

function init() {
    if (!window.AudioContext) {
    if (!window.webkitAudioContext) {
        alert("Your browser does not support any AudioContext and cannot play back this audio.");
        return;
    }
        window.AudioContext = window.webkitAudioContext;
    }

    context = new AudioContext();
}

function playByteArray(byteArray) {

    var arrayBuffer = new ArrayBuffer(byteArray.length);
    var bufferView = new Uint8Array(arrayBuffer);
    for (i = 0; i < byteArray.length; i++) {
      bufferView[i] = byteArray[i];
    }

    context.decodeAudioData(arrayBuffer, function(buffer) {
        buf = buffer;
        play();
    });
}

// Play the loaded file
function play() {
    // Create a source node from the buffer
    var source = context.createBufferSource();
    source.buffer = buf;
    // Connect to the final output node (the speakers)
    source.connect(context.destination);
    // Play immediately
    source.start(0);
}
window.onload=init;
变量上下文;//音频上下文
变量buf;//音频缓冲区
函数init(){
如果(!window.AudioContext){
如果(!window.webkitadiocontext){
警报(“您的浏览器不支持任何音频上下文,无法播放此音频。”);
返回;
}
window.AudioContext=window.webkitadiocontext;
}
上下文=新的AudioContext();
}
函数playbetarray(byteArray){
var arrayBuffer=新的arrayBuffer(byteArray.length);
var bufferView=新的Uint8Array(arrayBuffer);
对于(i=0;i
谢谢!但这似乎使用了浮动样本,我的wav音频原始数据是mono 16K Hz和base64字节,我需要转换它吗?怎么做?第一个链接说此功能现在已被弃用,Internet Explorer不支持替换!有没有适合所有浏览器的解决方案?@Pi当然没有。现在这是一个标准。IE为什么要实施标准?别傻了!这在firefox上不起作用!难道没有办法让它工作吗?bufferView打算做什么?@patrickdamery它是缓冲区上的一个组合,用来改变它的内容(这就是为什么在迭代结束后你看不到它的进一步使用)