Reputation: 85
I am trying to send an audio file through a websocket, and I realised that in order to do so i need to convert the mp3 file to a Linear PCM 16-bit code, but i cant find a way to do so.
here is what i want to do:
let mp3File = // the 16-bit pcm file
ws.on('message', async(msg) => {
if (typeof msg === "string") {
} else if (recognizeStream) {
recognizeStream.write(msg);
}
ws.send(mp3File) <== stream back the audio file
});
});
some background, the stream is a phone call (via vonage api) so ny ws connected to phone call and hear the user input, and then after some logic on my server i want to play to the user a mp3 file that is a local file in my server, via ws.send().
-----------update--------
now, if i send the pcm data from the stream (the raw audio from phone call) its works (the server echoing the phone call ) so i want to convert the mp3 file to the same format so i could send it to via ws.send().
-----------update 2--------
after making my audio file at the right format which is: " Linear PCM 16-bit, with either a 8kHz or a 16kHz sample rate, and a 20ms frame size "
i am trying to send the file trough the web socket but i dont know how to do so, i have the file in the project folder but i dont know how to send it via websocket , i looked for how to do so but i dident find anything.
i am trying to do what specified here:
Upvotes: 5
Views: 7775
Reputation: 443
First let's understand what this means:
Linear PCM 16-bit, with either a 8kHz or a 16kHz sample rate, and a 20ms frame size
They are talking about 2 things here:
Based on the audio format, if you choose "16bit Linear PCM with sample rate of 16K" implies:
So an audio chunk of 1 second will contain bytes = (16000 * 2) = 32000 bytes this means a 20ms/0.02s frame of audio will be equivalent to (32000*0.2) = 640 bytes
There are 2 things needed:
convert mp3 to wav. Install ffmpeg on your system and run this command
ffmpeg -i filename.mp3 -ar 16000 -sample_fmt s16 output.wav
This converts your filename.mp3
to output.wav
which will be Linear PCM 16-bit in 16K samplerate
In your code, when you send audio back, you need to stream it as chunks of 640 bytes, not the entire file data in one shot. There are 3 options:
I'm writing this example using npm websocket
package.
var fs = require('fs');
var binaryData = fs.readFileSync('output.wav');
var start = 44 // discard the wav header
var chunkSize = 640
...
// ws is a websocket connection object
connection.on('message', function(message) {
if (message.type === 'utf8') {
// handle a text message here
}
else if (message.type === 'binary') {
// print length of audio sent by nexmo. will be 640 for 16K and 320 for 8K
console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
if (start >= binaryData.length) {
// slice a chunk and send
toSend = binaryData.slice(start, start + chunkSize)
start = start + chunkSize
connection.sendBytes(toSend);
console.log('Sent Binary Message of ' + toSend.length + ' bytes');
}
} ...
});
Remember, there will be some delay from the point you send the audio from your server to nexmo, and you hearing on other side. It can vary from half a second to even more depending on the location of Nexmo's datacentre, of the server where you run your code, network speed etc. I have observed it to be close to 0.5 sec.
Upvotes: 7