Node.js NodeJS-管道化多个FFMPEG进程

Node.js NodeJS-管道化多个FFMPEG进程,node.js,process,ffmpeg,pipe,converter,Node.js,Process,Ffmpeg,Pipe,Converter,我试图编程一个转换器,可以采取任何视频源,并将其转换为mp3。mp3应该保存在我的硬盘上,或者保存在一个缓冲区中,以便通过电报发送 到目前为止,它运行良好,我面临的唯一问题是,它一次只能拍摄一个视频,我不知道为什么 // IMPORTS var fs = require('fs'); var https = require('https'); var child_process = require('child_process'); // EVENTEMITER (Not used so fa

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

到目前为止,它运行良好,我面临的唯一问题是,它一次只能拍摄一个视频,我不知道为什么

// 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,但创建了两个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
,因为我没有
https
url上的示例视频。这不应该有什么区别

我将
spawn
args
变量移出了对象,因为它们不会改变。我也不使用
this
来存储局部变量。我只是使用一个普通的闭包。最后,我将
退出
事件处理代码移动到对象内部。我只是认为最好将所有这些东西组合在一起——另外,它只声明一次,而不是为您创建的每个新流程声明一次

运行此命令将获得以下输出(我将脚本保存为
ffmpeg.js
):

还有,只是一个提示。如果要在
StreamHandler
中使用
this
对象,我建议在您的节点版本支持的情况下使用箭头函数。此代码也适用于:

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
说明符,您将创建一个全局变量。因此,第二次调用
newstreamhandler
时,将覆盖
self
变量。这就是为什么
test1.mp3
文件挂起,而
test2.mp3
文件是唯一一个挂起的文件。通过添加
var
,您原来的脚本现在适合我了。

谢谢。我稍后再看。我真的希望其他人知道为什么它不能按我的方式工作,这样我就可以在将来回避这个问题。你知道如何使这些进程并行运行吗?->请看我的新问题:)
var self = this;