繁体   English   中英

NodeJS-用管道传输多个FFMPEG进程

[英]NodeJS - piping multiple FFMPEG processes

我正在尝试对可以使用任何视频源并将其转换为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,但是创建了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 ,因为我没有可用的https网址示例视频。 它不应该有所作为。

我将spawnargs变量移出了对象,因为它们没有变化。 我也不用this来存储局部变量。 我只是使用普通的闭包代替。 最后,我将exit事件处理代码移到了对象内部。 我只是认为最好将所有这些内容归为一类,而且,只声明一次,而不是为您创建的每个新流程声明一次。

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

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

另外,只是小费。 如果要在StreamHandler使用this对象,如果您的Node版本支持的话,我建议使用箭头功能。 此代码也适用:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM