NodeJS – pipe道多个FFMPEG进程

我试图编程一个转换器,可以采取任何video源,并将其转换为MP3。 mp3应该保存在我的硬盘上,或者保存在一个缓冲区中,通过电报发送。

目前为止效果不错,我唯一面临的问题是一次只能拍一个video,而我不知道为什么。

// IMPORTS var fs = require('fs'); var https = require('https'); var child_process = require('child_process'); // EVENTEMITER (Not used so far) var util = require('util'); var EventEmitter = require('events').EventEmitter; // STREAMHANDLER var StreamHandler = function(url, name){ // VARIABLES self = this; this.url = url; this.name = name; // CREATE FFMPEG PROCESS var spawn = child_process.spawn; var args = ['-i', 'pipe:0', '-f', 'mp3', '-ac', '2', '-ab', '128k', '-acodec', 'libmp3lame', 'pipe:1']; this.ffmpeg = spawn('ffmpeg', args); // GRAB STREAM https.get(url, function(res) { res.pipe(self.ffmpeg.stdin); }); // WRITE TO FILE this.ffmpeg.stdout.pipe(fs.createWriteStream(name)); //DEBUG this.ffmpeg.stdout.on("data", function (data) { console.error(self.name); }); } util.inherits(StreamHandler, EventEmitter); // TESTING var test1 = new StreamHandler(vidUrl, "test1.mp3"); test1.ffmpeg.on("exit", function (code, name, signal) { console.log("Finished: " + test1.name); }); var test2 = new StreamHandler(vidUrl, "test2.mp3"); test2.ffmpeg.on("exit", function (code, name, signal) { console.log("Finished: " + test2.name); }); 

它跳过test1.mp3,只转换test2.mp3,但创build了2个ffmpeg进程: 在这里输入图像说明

在test2.mp3被转换后,另一个ffmpeg线程保持打开状态,但什么都不做,节点程序被卡住等待(我猜是这样),因为它发送了一些东西。

我希望有一个人可以帮助我 :)

使用你的代码,我有同样的问题。 它会挂在最后,只输出test2.mp3文件的数据。 我不完全确定是什么原因造成了这个问题,但我改变了一下,这对我有用:

 // IMPORTS var fs = require('fs'); //var https = require('https'); var http = require('http'); var child_process = require('child_process'); // EVENTEMITER (Not used so far) var util = require('util'); var EventEmitter = require('events').EventEmitter; // These never change... var spawn = child_process.spawn; var args = ['-i', 'pipe:0', '-f', 'mp3', '-ac', '2', '-ab', '128k', '-acodec', 'libmp3lame', 'pipe:1']; // STREAMHANDLER var StreamHandler = function(url, name){ // CREATE FFMPEG PROCESS var ffmpeg = spawn('ffmpeg', args); // GRAB STREAM http.get(url, function(res) { res.pipe(ffmpeg.stdin); }); // WRITE TO FILE ffmpeg.stdout.pipe(fs.createWriteStream(name)); ffmpeg.on("exit", function() { console.log("Finished:", name); }); //DEBUG ffmpeg.stdout.on("data", function(data) { console.error(name, "received data"); }); } util.inherits(StreamHandler, EventEmitter); // TESTING var vidUrl = 'http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4'; var test1 = new StreamHandler(vidUrl, "test1.mp3"); var test2 = new StreamHandler(vidUrl, "test2.mp3"); 

我使用http而不是https ,因为我没有可用的httpsurl的示例video。 它不应该有所作为。

我将spawnargsvariables移出对象,因为它们不会改变。 我也不用this来存储局部variables。 我只是使用正常的closures。 最后,我移动了对象内部的exit事件处理代码。 我认为把所有这些东西组合在一起会更好 – 另外,它只是被声明一次,而不是你创build的每一个新的stream程。

运行这个给我下面的输出(我把脚本保存为ffmpeg.js ):

 $ node ffmpeg.js test2.mp3 received data Finished: test2.mp3 test1.mp3 received data Finished: test1.mp3 

另外,只是一个小费。 如果你想在StreamHandler使用this对象,如果你的Node版本支持,我会build议使用箭头函数。 这个代码也起作用:

 var StreamHandler = function(url, name){ // CREATE FFMPEG PROCESS this.ffmpeg = spawn('ffmpeg', args); // GRAB STREAM http.get(url, (res) => { res.pipe(this.ffmpeg.stdin); }); // WRITE TO FILE this.ffmpeg.stdout.pipe(fs.createWriteStream(name)); this.ffmpeg.on("exit", () => { console.log("Finished:", name); }); //DEBUG this.ffmpeg.stdout.on("data", (data) => { console.error(name, "received data"); }); } 

请注意,使用箭头函数,我不必使用var self = this; 避免这个问题的原因很多,就是将箭头函数添加到了javascript中。

希望这可以帮助!

– 编辑 –

好的,我明白了。 你的代码中的问题是这一行:

 self = this; 

它应该是:

 var self = this; 

没有var说明符,你正在创build一个全局variables。 所以,第二次调用new StreamHandler ,你正在覆盖selfvariables。 这就是为什么test1.mp3文件挂起和test2.mp3文件是唯一一个完成。 通过添加var ,您的原始脚本现在为我工作。