Web browser support for the opus audio codec is normally utilized by delivering an entire opus-encoded file to the browser, and this is known to work for firefox and chrome, for example. My scenario is different in that I stream opus packets from server to browser. On a linux server I encode audio with opus_encode_float. It is delivered to a web browser client via WebSocket. In the browser I use the Web Audio API's decodeAudioData to try to decode that same data. It fails in firefox and chrome with a null exception.
Seems to me this should work, if not last year then Real Soon Now. Can anyone either tell me the status of the opus implementations in the browsers, or tell me what I'm doing wrong? Thanks in advance.
// .h
#define OPUS_FRAME_SIZE 1920
#define MAX_FRAME_SIZE 6*OPUS_FRAME_SIZE
#define MAX_PACKET_SIZE (4*OPUS_FRAME_SIZE)
class OpusEncoder; // forward declaration as we don't want to include opus.h here
class xxx {
OpusEncoder *encoder; // Holds the state of the opus encoder
unsigned char opusOutBuf[MAX_PACKET_SIZE];
}
// .cpp
#include <opus.h>
#define CHANNELS 2
#define SAMPLE_RATE 48000
#define APPLICATION OPUS_APPLICATION_AUDIO
#define BITRATE 64000
// one time code
// Create a new encoder state
int err;
encoder = opus_encoder_create(SAMPLE_RATE, CHANNELS, APPLICATION, &err);
if (err<0)
{
LogIt(prError) << "Failed to create an Opus encoder: " << opus_strerror(err);
return;
}
err = opus_encoder_ctl(encoder, OPUS_SET_BITRATE(BITRATE));
if (err<0)
{
LogIt(prError) << "Opus failed to set bitrate: " << opus_strerror(err);
return ;
}
// per packet code
int nbBytes = opus_encode_float(encoder, IncomingAudio, OPUS_FRAME_SIZE, opusOutBuf, MAX_PACKET_SIZE);
if (nbBytes < 0)
{
LogIt(prError) << "Opus encode failed: " << opus_strerror(nbBytes);
return;
}
// Client side javascript
// OpusEncodedArrayBuffer is an unmodified binary packet that
// arrived via websocket onmessage(evt); it is evt.data
window.context.decodeAudioData(OpusEncodedArrayBuffer, function(buffer) { // use "classic" callback
if (buffer) { // I would LIKE to arrive here, but so far no joy.
// ...
}
},
function(e){
if (e) {
tell("error in decodeAudioData: " + e) // I haven't seen this case yet
} else { // This ALWAYS happens, using latest firefox or chrome
tell("error in decodeAudioData"); // webaudio api spec says decodeAudioData does not return an object error
}
});
Chrome's decodeAudioData function does not support opus. There's an open bug on this issue.