JavaScript reproduce arraybuffer como audio. Necesita ayuda para resolver "decodeaudiodata incapaz de decodificar datos de audio"
Tengo un servidor WebSocket .net core que recibe transmisión de audio en vivo del cliente A, luego necesito transmitir este audio en vivo al cliente B (navegador). Así que recibí la matriz de bytes del cliente A y envié la matriz de bytes al cliente B (navegador) * La matriz de bytes es correcta, ya que puedo convertirla a .wav y reproducirla sin problemas.
En el cliente B (navegador), trato de decodificar el búfer de matriz en el búfer de audio para que se pueda poner en salida y reproducir.
El mediastreamhandler.SendArraySegToAllAsync es donde comienzo a enviar la matriz de bytes desde el servidor al cliente B. Utilizo para enviar a todos los métodos primero, luego se modificarán y enviarán datos haciendo coincidir el ID de conexión de websocket.
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);
}
Luego recibo la matriz de bytes de audio a través de websocket.onmessage en Javascript. Luego paso la matriz de bytes para decodificar y reproducir. Pero aquí dice "incapaz de decodificar datos". Mientras estaba en Mozilla, dijo que el formato del contenido era desconocido (¿necesito reformatear la matriz de bytes que recibo?) La matriz de bytes en sí está bien porque he usado el mismo byte para crear un archivo .wav localmente y reproducirlo sin algún problema.
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();
}
Luego pruebo otro método para decodificar y reproducir el audio, esta vez, ha reproducido algunos sonidos blanquecinos en lugar de transmitir el audio desde el Cliente 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();
}
Creo que realmente necesito ayuda aquí, chicos, tratando de jugar con el búfer de matriz en semanas y aún así, no pude lograr ningún avance. Atrapado aquí. No estoy seguro de lo que he hecho, ¿podrían guiarme amablemente o decirme cualquier otro enfoque para esto? Muchas gracias de antemano, de verdad.
Respuestas
decodeAudioData()requiere archivos completos, por lo que no se puede utilizar para decodificar fragmentos parciales de datos a medida que se reciben de un websocket. Si puede transmitir archivos de audio Opus a través de su websocket, puede reproducirlos con un decodificador de WebAssembly disponible. Ver:
- https://fetch-stream-audio.anthum.com/
- https://github.com/AnthumChris/fetch-stream-audio
Resolví el problema hace meses, solo aquí para publicar mi solución.
Pasos:
- El servidor recibe la cadena de carga útil de Twilio
- Envíe la cadena de carga útil del servidor al cliente (navegador).
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);
}
- Agregue wavheader a la cadena de carga útil en el lado del cliente antes de reproducir el audio.
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();
};