From 2194632b7df7e26a812e76a0955be479e400d220 Mon Sep 17 00:00:00 2001 From: Programmix Date: Fri, 27 May 2016 23:09:16 -0700 Subject: [PATCH] Potential FFMPEG process fix (#381) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I am by no means sure that this will work. This is an experimental fix. Please review it carefully; I’m not the best at working with audio/streams. --- lib/Client/InternalClient.js | 6 +- lib/Util/TokenCacher-shim.js | 24 +++---- lib/Voice/AudioEncoder.js | 130 ++++++++++++++--------------------- src/Voice/AudioEncoder.js | 129 ++++++++++++++-------------------- 4 files changed, 118 insertions(+), 171 deletions(-) diff --git a/lib/Client/InternalClient.js b/lib/Client/InternalClient.js index 5e22b756f..118f7063c 100644 --- a/lib/Client/InternalClient.js +++ b/lib/Client/InternalClient.js @@ -1605,9 +1605,9 @@ var InternalClient = (function () { data = { name: data.name || channel.name, topic: data.topic || channel.topic, - position: data.position || channel.position, - user_limit: data.userLimit || channel.userLimit, - bitrate: data.bitrate || channel.bitrate + position: data.position ? data.position : channel.position, + user_limit: data.userLimit ? data.userLimit : channel.userLimit, + bitrate: data.bitrate ? data.bitrate : channel.bitrate }; if (data.position < 0) { diff --git a/lib/Util/TokenCacher-shim.js b/lib/Util/TokenCacher-shim.js index 53412d365..f483e9575 100644 --- a/lib/Util/TokenCacher-shim.js +++ b/lib/Util/TokenCacher-shim.js @@ -6,23 +6,23 @@ exports.__esModule = true; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var TokenCacher = (function () { - function TokenCacher() { - _classCallCheck(this, TokenCacher); - } + function TokenCacher() { + _classCallCheck(this, TokenCacher); + } - TokenCacher.prototype.setToken = function setToken() {}; + TokenCacher.prototype.setToken = function setToken() {}; - TokenCacher.prototype.save = function save() {}; + TokenCacher.prototype.save = function save() {}; - TokenCacher.prototype.getToken = function getToken() { - return null; - }; + TokenCacher.prototype.getToken = function getToken() { + return null; + }; - TokenCacher.prototype.init = function init(ind) { - this.done = true; - }; + TokenCacher.prototype.init = function init(ind) { + this.done = true; + }; - return TokenCacher; + return TokenCacher; })(); exports["default"] = TokenCacher; diff --git a/lib/Voice/AudioEncoder.js b/lib/Voice/AudioEncoder.js index a757b5b98..c3cf6b939 100644 --- a/lib/Voice/AudioEncoder.js +++ b/lib/Voice/AudioEncoder.js @@ -91,34 +91,7 @@ var AudioEncoder = (function () { stream.pipe(enc.stdin); - var ffmpegErrors = ""; - - enc.stdout.pipe(_this.volume); - enc.stderr.on("data", function (data) { - ffmpegErrors += "\n" + new Buffer(data).toString().trim(); - }); - enc.once("exit", function (code, signal) { - if (code) { - reject(new Error("FFMPEG: " + ffmpegErrors)); - } - }); - - _this.volume.once("readable", function () { - resolve({ - proc: enc, - stream: _this.volume, - instream: stream, - channels: 2 - }); - }); - - _this.volume.on("end", function () { - reject("end"); - }); - - _this.volume.on("close", function () { - reject("close"); - }); + hookEncodingProcess(resolve, reject, enc, stream); }); }; @@ -130,33 +103,7 @@ var AudioEncoder = (function () { var enc = _child_process2["default"].spawn(_this2.getCommand(), ['-i', file, '-f', 's16le', '-ar', '48000', '-ss', options.seek || 0, '-ac', 2, 'pipe:1']); - var ffmpegErrors = ""; - - enc.stdout.pipe(_this2.volume); - enc.stderr.on("data", function (data) { - ffmpegErrors += "\n" + new Buffer(data).toString().trim(); - }); - enc.once("exit", function (code, signal) { - if (code) { - reject(new Error("FFMPEG: " + ffmpegErrors)); - } - }); - - _this2.volume.once("readable", function () { - resolve({ - proc: enc, - stream: _this2.volume, - channels: 2 - }); - }); - - _this2.volume.on("end", function () { - reject("end"); - }); - - _this2.volume.on("close", function () { - reject("close"); - }); + hookEncodingProcess(resolve, reject, enc); }); }; @@ -170,33 +117,60 @@ var AudioEncoder = (function () { var options = ffmpegOptions.concat(['-f', 's16le', '-ar', '48000', '-ac', 2, 'pipe:1']); var enc = _child_process2["default"].spawn(_this3.getCommand(), options); - var ffmpegErrors = ""; + hookEncodingProcess(resolve, reject, enc); + }); + }; - enc.stdout.pipe(_this3.volume); - enc.stderr.on("data", function (data) { - ffmpegErrors += "\n" + new Buffer(data).toString().trim(); - }); - enc.once("exit", function (code, signal) { - if (code) { - reject(new Error("FFMPEG: " + ffmpegErrors)); - } - }); + AudioEncoder.prototype.hookEncodingProcess = function hookEncodingProcess(resolve, reject, enc, stream) { + var _this4 = this; - _this3.volume.once("readable", function () { - resolve({ - proc: enc, - stream: _this3.volume, - channels: 2 - }); - }); + var processKilled = false; - _this3.volume.on("end", function () { - reject("end"); - }); + function killProcess() { + if (processKilled) return; - _this3.volume.on("close", function () { - reject("close"); - }); + enc.stdin.pause(); + enc.kill("SIGINT"); + + processKilled = true; + } + + var ffmpegErrors = ""; + + enc.stdout.pipe(this.volume); + enc.stderr.on("data", function (data) { + ffmpegErrors += "\n" + new Buffer(data).toString().trim(); + }); + enc.once("exit", function (code, signal) { + if (code) { + reject(new Error("FFMPEG: " + ffmpegErrors)); + } + }); + + this.volume.once("readable", function () { + var data = { + proc: enc, + stream: _this4.volume, + channels: 2 + }; + + if (stream) { + data.instream = stream; + } + + resolve(data); + }); + + this.volume.on("end", function () { + killProcess(); + + reject("end"); + }); + + this.volume.on("close", function () { + killProcess(); + + reject("close"); }); }; diff --git a/src/Voice/AudioEncoder.js b/src/Voice/AudioEncoder.js index 253e1b58b..ef887e2f7 100644 --- a/src/Voice/AudioEncoder.js +++ b/src/Voice/AudioEncoder.js @@ -73,34 +73,7 @@ export default class AudioEncoder { stream.pipe(enc.stdin); - var ffmpegErrors = ""; - - enc.stdout.pipe(this.volume); - enc.stderr.on("data", (data) => { - ffmpegErrors += "\n" + new Buffer(data).toString().trim(); - }); - enc.once("exit", (code, signal) => { - if (code) { - reject(new Error("FFMPEG: " + ffmpegErrors)); - } - }) - - this.volume.once("readable", () => { - resolve({ - proc: enc, - stream: this.volume, - instream: stream, - channels: 2 - }); - }); - - this.volume.on("end", () => { - reject("end"); - }); - - this.volume.on("close", () => { - reject("close"); - }); + hookEncodingProcess(resolve, reject, enc, stream); }); } @@ -117,33 +90,7 @@ export default class AudioEncoder { 'pipe:1' ]); - var ffmpegErrors = ""; - - enc.stdout.pipe(this.volume); - enc.stderr.on("data", (data) => { - ffmpegErrors += "\n" + new Buffer(data).toString().trim(); - }); - enc.once("exit", (code, signal) => { - if (code) { - reject(new Error("FFMPEG: " + ffmpegErrors)); - } - }) - - this.volume.once("readable", () => { - resolve({ - proc: enc, - stream: this.volume, - channels: 2 - }); - }); - - this.volume.on("end", () => { - reject("end"); - }); - - this.volume.on("close", () => { - reject("close"); - }); + hookEncodingProcess(resolve, reject, enc); }); } @@ -160,33 +107,59 @@ export default class AudioEncoder { ]); var enc = cpoc.spawn(this.getCommand(), options); - var ffmpegErrors = ""; + hookEncodingProcess(resolve, reject, enc); + }); + } - enc.stdout.pipe(this.volume); - enc.stderr.on("data", (data) => { - ffmpegErrors += "\n" + new Buffer(data).toString().trim(); - }); - enc.once("exit", (code, signal) => { - if (code) { - reject(new Error("FFMPEG: " + ffmpegErrors)); - } - }) + hookEncodingProcess(resolve, reject, enc, stream) { + var processKilled = false; - this.volume.once("readable", () => { - resolve({ - proc: enc, - stream: this.volume, - channels: 2 - }); - }); + function killProcess() { + if (processKilled) + return; - this.volume.on("end", () => { - reject("end"); - }); + enc.stdin.pause(); + enc.kill("SIGINT"); - this.volume.on("close", () => { - reject("close"); - }); + processKilled = true; + } + + var ffmpegErrors = ""; + + enc.stdout.pipe(this.volume); + enc.stderr.on("data", (data) => { + ffmpegErrors += "\n" + new Buffer(data).toString().trim(); + }); + enc.once("exit", (code, signal) => { + if (code) { + reject(new Error("FFMPEG: " + ffmpegErrors)); + } + }); + + this.volume.once("readable", () => { + var data = { + proc: enc, + stream: this.volume, + channels: 2 + }; + + if (stream) { + data.instream = stream; + } + + resolve(data); + }); + + this.volume.on("end", () => { + killProcess(); + + reject("end"); + }); + + this.volume.on("close", () => { + killProcess(); + + reject("close"); }); } }