AWESOME MAGIC

This commit is contained in:
hydrabolt
2015-11-07 17:21:05 +00:00
parent 4bab0a6bbc
commit be1f5064c2
6 changed files with 311 additions and 140 deletions

48
lib/Voice/AudioEncoder.js Normal file
View File

@@ -0,0 +1,48 @@
"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var cpoc = require("child_process");
var opus = require("node-opus");
var VoicePacket = require("./VoicePacket.js");
var AudioEncoder = (function () {
function AudioEncoder() {
_classCallCheck(this, AudioEncoder);
this.opus = new opus.OpusEncoder(48000, 1);
}
AudioEncoder.prototype.opusBuffer = function opusBuffer(buffer) {
return this.opus.encode(buffer, 1920);
};
AudioEncoder.prototype.encodeFile = function encodeFile(file) {
var callback = arguments.length <= 1 || arguments[1] === undefined ? function (err, buffer) {} : arguments[1];
var self = this;
return new Promise(function (resolve, reject) {
var enc = cpoc.spawn("ffmpeg", ["-i", file, "-f", "s16le", "-ar", "48000", "-ac", "1", "-af", "volume=1", "pipe:1"]);
enc.stdout.on("readable", function () {
callback(null, enc.stdout);
resolve(enc.stdout);
});
enc.stdout.on("end", function () {
callback("end");
reject("end");
});
enc.stdout.on("close", function () {
callback("close");
reject("close");
});
});
};
return AudioEncoder;
})();
module.exports = AudioEncoder;

View File

@@ -9,23 +9,9 @@ var Lame = require("lame");
var Opus = require('node-opus');
var Wav = require('wav');
var fs = require("fs");
function VoicePacket(packet, sequence, timestamp, ssrc) {
var audioBuffer = packet;
var retBuff = new Buffer(audioBuffer.length + 12);
retBuff.fill(0);
retBuff[0] = 0x80;
retBuff[1] = 0x78;
retBuff.writeUIntBE(sequence, 2, 2);
retBuff.writeUIntBE(timestamp, 4, 4);
retBuff.writeUIntBE(ssrc, 8, 4);
for (var i = 0; i < audioBuffer.length; i++) {
retBuff[i + 12] = audioBuffer[i];
}
return retBuff;
}
var ffmpeg = require('fluent-ffmpeg');
var AudioEncoder = require("./AudioEncoder.js");
var VoicePacket = require("./VoicePacket.js");
var VoiceConnection = (function () {
function VoiceConnection(channel, client, session, token, server, endpoint) {
@@ -40,69 +26,91 @@ var VoiceConnection = (function () {
this.vWS = null; // vWS means voice websocket
this.ready = false;
this.vWSData = {};
this.opus = new Opus.OpusEncoder(48000, 1);
this.encoder = new AudioEncoder();
this.udp = null;
this.init();
}
VoiceConnection.prototype.test = function test() {
VoiceConnection.prototype.playRawStream = function playRawStream(stream) {
var self = this;
self.playing = true;
var startTime = Date.now();
var cnt = 0;
function sendAudio(sequence, timestamp, opusEncoder, wavOutput, udpClient, vWS) {
cnt++;
var buff = wavOutput.read(1920);
if (buff && buff.length === 1920) {
sequence + 20 < 65535 ? sequence += 1 : sequence = 0;
timestamp + 9600 < 4294967295 ? timestamp += 960 : timestamp = 0;
var sequence = 0;
var time = 0;
var count = 0;
var encoded = opusEncoder.encode(buff, 1920);
var audioPacket = VoicePacket(encoded, sequence, timestamp, self.vWSData.ssrc);
var length = 20;
var nextTime = startTime + cnt * 20;
function send() {
try {
count++;
sequence + 10 < 65535 ? sequence += 1 : sequence = 0;
time + 9600 < 4294967295 ? time += 960 : time = 0;
self.sendBuffer(stream.read(1920), sequence, time, function (e) {
console.log(e);
});
var nextTime = startTime + count * length;
udpClient.send(audioPacket, 0, audioPacket.length, self.vWSData.port, self.endpoint, function (err) {});
setTimeout(function () {
sendAudio(sequence, timestamp, opusEncoder, wavOutput, udpClient, vWS);
}, 20 + (nextTime - new Date().getTime()));
} else {
var speaking = {
"op": 5,
"d": {
"speaking": false,
"delay": 0
}
};
vWS.send(JSON.stringify(speaking));
}
send();
}, length + (nextTime - Date.now()));
} catch (e) {}
}
var speaking = {
"op": 5,
"d": {
"speaking": true,
"delay": 0
self.vWS.send(JSON.stringify({
op: 5,
d: {
speaking: true,
delay: 0
}
};
}));
send();
};
var vWS = self.vWS;
var stream = fs.createReadStream("c:/users/amish/desktop/audio.wav");
VoiceConnection.prototype.sendPacket = function sendPacket(packet) {
var callback = arguments.length <= 1 || arguments[1] === undefined ? function (err) {} : arguments[1];
vWS.send(JSON.stringify(speaking));
var self = this;
self.playing = true;
try {
self.udp.send(packet, 0, packet.length, self.vWSData.port, self.endpoint, callback);
} catch (e) {
self.playing = false;
callback(e);
return false;
}
};
var rate = 48000;
var opusEncoder = new Opus.OpusEncoder(48000, 1);
var wavReader = new Wav.Reader();
wavReader.on('format', function (format) {
console.log(format);
});
var wavOutput = stream.pipe(wavReader);
var sequence = 0;
var timestamp = 0;
wavOutput.on('readable', function () {
console.log("readable!");
sendAudio(sequence, timestamp, opusEncoder, wavOutput, self.udp, vWS);
VoiceConnection.prototype.sendBuffer = function sendBuffer(buffer, sequence, timestamp, callback) {
var self = this;
self.playing = true;
try {
var buffer = self.encoder.opusBuffer(buffer);
var packet = new VoicePacket(buffer, sequence, timestamp, self.vWSData.ssrc);
return self.sendPacket(packet, callback);
} catch (e) {
self.playing = false;
console.log("etype", e.stack);
return false;
}
};
VoiceConnection.prototype.test = function test() {
var self = this;
this.encoder.encodeFile("C:/users/amish/desktop/audio.mp3")["catch"](error).then(function (stream) {
self.playRawStream(stream);
});
function error() {
console.log("ERROR!");
}
};
VoiceConnection.prototype.init = function init() {

26
lib/Voice/VoicePacket.js Normal file
View File

@@ -0,0 +1,26 @@
"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var VoicePacket = function VoicePacket(data, sequence, time, ssrc) {
_classCallCheck(this, VoicePacket);
var audioBuffer = data,
returnBuffer = new Buffer(audioBuffer.length + 12);
returnBuffer.fill(0);
returnBuffer[0] = 0x80;
returnBuffer[1] = 0x78;
returnBuffer.writeUIntBE(sequence, 2, 2);
returnBuffer.writeUIntBE(time, 4, 4);
returnBuffer.writeUIntBE(ssrc, 8, 4);
for (var i = 0; i < audioBuffer.length; i++) {
returnBuffer[i + 12] = audioBuffer[i];
}
return returnBuffer;
};
module.exports = VoicePacket;

48
src/Voice/AudioEncoder.js Normal file
View File

@@ -0,0 +1,48 @@
"use strict";
var cpoc = require("child_process");
var opus = require("node-opus");
var VoicePacket = require("./VoicePacket.js");
class AudioEncoder{
constructor(){
this.opus = new opus.OpusEncoder(48000, 1);
}
opusBuffer(buffer){
return this.opus.encode(buffer, 1920);
}
encodeFile(file, callback=function(err, buffer){}){
var self = this;
return new Promise((resolve, reject) => {
var enc = cpoc.spawn("ffmpeg" , [
"-i", file,
"-f", "s16le",
"-ar", "48000",
"-ac", "1",
"-af", "volume=1",
"pipe:1"
]);
enc.stdout.on("readable", function() {
callback(null, enc.stdout);
resolve(enc.stdout)
});
enc.stdout.on("end", function() {
callback("end");
reject("end");
});
enc.stdout.on("close", function() {
callback("close");
reject("close");
});
});
}
}
module.exports = AudioEncoder;

View File

@@ -7,23 +7,9 @@ var Lame = require("lame");
var Opus = require('node-opus');
var Wav = require('wav');
var fs = require("fs");
function VoicePacket(packet, sequence, timestamp, ssrc) {
var audioBuffer = packet;
var retBuff = new Buffer(audioBuffer.length + 12);
retBuff.fill(0);
retBuff[0] = 0x80;
retBuff[1] = 0x78;
retBuff.writeUIntBE(sequence, 2, 2);
retBuff.writeUIntBE(timestamp, 4, 4);
retBuff.writeUIntBE(ssrc, 8, 4);
for (var i = 0; i < audioBuffer.length; i++) {
retBuff[i + 12] = audioBuffer[i];
}
return retBuff;
}
var ffmpeg = require('fluent-ffmpeg');
var AudioEncoder = require("./AudioEncoder.js");
var VoicePacket = require("./VoicePacket.js");
class VoiceConnection {
constructor(channel, client, session, token, server, endpoint) {
@@ -36,71 +22,100 @@ class VoiceConnection {
this.vWS = null; // vWS means voice websocket
this.ready = false;
this.vWSData = {};
this.opus = new Opus.OpusEncoder(48000, 1);
this.encoder = new AudioEncoder();
this.udp = null;
this.init();
}
playRawStream(stream){
var self = this;
self.playing = true;
var startTime = Date.now();
var sequence = 0;
var time = 0;
var count = 0;
var length = 20;
function send(){
try{
count++;
sequence + 10 < 65535 ? sequence += 1 : sequence = 0;
time + 9600 < 4294967295 ? time += 960 : time = 0;
self.sendBuffer(stream.read(1920), sequence, time, (e) => {
console.log(e);
});
var nextTime = startTime + (count * length);
setTimeout(function() {
send();
}, length + (nextTime - Date.now()));
}catch(e){
}
}
self.vWS.send(JSON.stringify({
op : 5,
d : {
speaking : true,
delay : 0
}
}));
send();
}
sendPacket(packet, callback=function(err){}){
var self = this;
self.playing = true;
try{
self.udp.send(packet, 0, packet.length, self.vWSData.port, self.endpoint, callback);
}catch(e){
self.playing = false;
callback(e);
return false;
}
}
sendBuffer(buffer, sequence, timestamp, callback){
var self = this;
self.playing = true;
try{
var buffer = self.encoder.opusBuffer(buffer);
var packet = new VoicePacket(buffer, sequence, timestamp, self.vWSData.ssrc);
return self.sendPacket(packet, callback);
}catch(e){
self.playing = false;
console.log("etype", e.stack);
return false;
}
}
test() {
var self = this;
var startTime = Date.now();
var cnt = 0;
function sendAudio(sequence, timestamp, opusEncoder, wavOutput, udpClient, vWS) {
cnt++;
var buff = wavOutput.read(1920);
if (buff && buff.length === 1920) {
sequence + 20 < 65535 ? sequence += 1 : sequence = 0;
timestamp + 9600 < 4294967295 ? timestamp += 960 : timestamp = 0;
var encoded = opusEncoder.encode(buff, 1920);
var audioPacket = VoicePacket(encoded, sequence, timestamp, self.vWSData.ssrc);
var nextTime = startTime + cnt * 20;
udpClient.send(audioPacket, 0, audioPacket.length, self.vWSData.port, self.endpoint, function (err) { });
setTimeout(function () {
sendAudio(sequence, timestamp, opusEncoder, wavOutput, udpClient, vWS);
}, 20 + (nextTime - new Date().getTime()));
} else {
var speaking = {
"op": 5,
"d": {
"speaking": false,
"delay": 0
}
}
vWS.send(JSON.stringify(speaking));
}
this.encoder
.encodeFile("C:/users/amish/desktop/audio.mp3")
.catch(error)
.then( stream => {
self.playRawStream(stream);
} );
function error(){
console.log("ERROR!");
}
var speaking = {
"op": 5,
"d": {
"speaking": true,
"delay": 0
}
}
var vWS = self.vWS;
var stream = fs.createReadStream("c:/users/amish/desktop/audio.wav");
vWS.send(JSON.stringify(speaking));
var rate = 48000;
var opusEncoder = new Opus.OpusEncoder(48000, 1);
var wavReader = new Wav.Reader();
wavReader.on('format', function (format) {
console.log(format);
});
var wavOutput = stream.pipe(wavReader);
var sequence = 0;
var timestamp = 0;
wavOutput.on('readable', function () {
console.log("readable!");
sendAudio(sequence, timestamp, opusEncoder, wavOutput, self.udp, vWS);
});
}
init() {

26
src/Voice/VoicePacket.js Normal file
View File

@@ -0,0 +1,26 @@
"use strict";
class VoicePacket{
constructor(data, sequence, time, ssrc){
var audioBuffer = data,
returnBuffer = new Buffer(audioBuffer.length + 12);
returnBuffer.fill(0);
returnBuffer[0] = 0x80;
returnBuffer[1] = 0x78;
returnBuffer.writeUIntBE(sequence, 2, 2);
returnBuffer.writeUIntBE(time, 4, 4);
returnBuffer.writeUIntBE(ssrc, 8, 4);
for (var i=0; i<audioBuffer.length; i++) {
returnBuffer[i + 12] = audioBuffer[i];
}
return returnBuffer;
}
}
module.exports = VoicePacket;