[英]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
网址示例视频。 它不应该有所作为。
我将spawn
和args
变量移出了对象,因为它们没有变化。 我也不用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.