JavaScript将arraybuffer作为音频播放。需要帮助解决“解码音频数据无法解码音频数据”

时间:2020-11-01 17:07:08

标签: javascript websocket audio-streaming web-audio-api audiobuffer

我有一个.net核心WebSocket服务器,该服务器从客户端A接收实时流音频,然后需要将该实时音频流传输到客户端B(浏览器)。因此,我已经从客户端A收到了字节数组,然后将字节数组发送给客户端B(浏览器)*该字节数组是正确的,因为我可以将其转换为.wav并可以正常播放。

在客户端B(浏览器)中,我尝试将数组缓冲区解码为音频缓冲区,以便可以将其放入输出并播放。

mediastreamhandler.SendArraySegToAllAsync是我开始从服务器向客户端B发送字节数组的地方。我曾经用于发送至所有方法1st,稍后将被修改并通过匹配websocket连接ID发送数据。

private async Task Echo(HttpContext context, WebSocket webSocket)
        {
            Debug.WriteLine("Start Echo between Websocket server & client");
            var buffer = new byte[1024 * 4];
           
            WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);

            while (!result.CloseStatus.HasValue)
            {
                await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);

                result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);

                await mediastreamhandler.SendArraySegToAllAsync(new ArraySegment<byte>(buffer, 0, result.Count));

            }
            Debug.WriteLine("Close Echo");
            await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
        }

然后我通过Javascript中的websocket.onmessage接收音频字节数组。然后,我将字节数组传递给解码和播放。但是在这里它说“无法解码数据”。在Mozilla中,它确实说内容格式是未知的(我需要重新格式化接收到的字节数组吗?)字节数组本身很好,因为我使用了相同的字节在本地创建.wav文件,而没有有问题。

var ctx = new AudioContext();

    function playSound(arrBuff) {

        var myAudioBuffer;

        var src = ctx.createBufferSource();

        ctx.decodeAudioData(arrBuff, function (buffer) {
            myAudioBuffer = buffer;
        });

        src.buffer = myAudioBuffer;
        src.connect(ctx.destination);
        src.start();

    }

然后我尝试另一种方法来解码和播放音频,这一次,它播放了一些白噪声,而不是从客户端A流出音频。

var ctx = new AudioContext();

    function playSound(arrBuff) {

        var myAudioBuffer;

        var src = ctx.createBufferSource();

        myAudioBuffer = ctx.createBuffer(1, arrBuff.byteLength, 8000);
        var nowBuffering = myAudioBuffer.getChannelData(0);
        for (var i = 0; i < arrBuff.byteLength; i++) {
            nowBuffering[i] = arrBuff[i];
        }

        src.buffer = myAudioBuffer;
        src.connect(ctx.destination);
        src.start();

    }

我认为我确实需要这方面的帮助,试图在几周内发挥阵列缓冲区的作用,但仍然没有任何突破。卡在这里。不知道我做了什么,你们能否请我指导或告诉我其他解决方法?预先非常感谢,真的是真的。

2 个答案:

答案 0 :(得分:1)

decodeAudioData()需要完整的文件,因此当从网络套接字接收到部分数据块时,不能将其用于解码。如果您可以通过websocket流化Opus音频文件,则可以使用可用的WebAssembly解码器进行播放。参见:

答案 1 :(得分:0)

我几个月前解决了这个问题,只是在这里发布我的解决方案。

步骤:

  1. 服务器从 Twilio 接收负载字符串
  2. 将负载字符串从服务器发送到客户端(浏览器)。
 public async Task SendMessageAsync(WebSocket socket, string message)
 {
     if (socket.State != WebSocketState.Open)
         return;

     await socket.SendAsync(buffer: new ArraySegment<byte>(array: Encoding.ASCII.GetBytes(message),
                                                                  offset: 0,
                                                                  count: message.Length),
                                   messageType: WebSocketMessageType.Text,
                                   endOfMessage: true,
                                   cancellationToken: CancellationToken.None);
 }
  1. 在播放音频之前,将 wavheader 添加到客户端的负载字符串中。
function playSound(payloadBase64) {

     /* You can generate the wav header here --> https://codepen.io/mxfh/pen/mWLMrJ */
     var Base64wavheader = "UklGRgAAAABXQVZFZm10IBIAAAAHAAEAQB8AAEAfAAABAAgAAABmYWN0BAAAAAAAAABkYXRh";

     var audio = new Audio('data:audio/wav;base64,' + Base64wavheader + payloadBase64);
     audio.play();
};