2017-02-07 5 views
1

Ich versuche einen Konverter zu programmieren, der jede Videoquelle aufnehmen und in mp3 konvertieren kann. Das MP3 sollte auf meiner Festplatte oder in einem Puffer gespeichert werden, um es per Telegramm zu senden.NodeJS - Piping mehrere FFMPEG Prozesse

Es funktioniert gut bis jetzt, das einzige Problem, mit dem ich konfrontiert bin, ist, dass es nur ein Video auf einmal aufnehmen kann, und ich weiß nicht warum.

// 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); 
}); 

Es springt test1.mp3 und nur wandelt test2.mp3, aber 2 ffmpeg Prozesse wurden erstellt: enter image description here

Nach test2.mp3 umgewandelt wird der andere ffmpeg Faden bleibt offen, aber tut nichts, und Das Knotenprogramm bleibt hängen (ich denke schon), damit es etwas sendet.

Ich hoffe, jemand kann mir helfen :)

Antwort

2

Code verwenden, ich hatte das gleiche Problem. Es würde am Ende hängen und nur Daten für die Datei test2.mp3 ausgeben. Ich bin mir nicht ganz sicher, was das Problem verursacht, aber ich änderte es ein bisschen und das funktioniert für mich:

// 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"); 

ich http statt https verwenden, weil ich nicht eine Probe Video zu einem https habe URL verfügbar. Es sollte keinen Unterschied machen.

Ich habe die Variablen spawn und args aus dem Objekt entfernt, weil sie sich nicht ändern. Ich verwende auch this nicht, um die lokalen Variablen zu speichern. Ich benutze stattdessen einen normalen Verschluss. Schließlich habe ich den exit Ereignisbehandlungscode in das Objekt verschoben. Ich denke nur, dass es besser ist, all diese Sachen zusammen zu gruppieren - plus, es wird nur einmal deklariert und nicht für jeden neuen Prozess, den du erstellst.

des Lauf gibt mir die folgende Ausgabe (I das Skript als ffmpeg.js gespeichert):

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

Auch nur eine Spitze. Wenn Sie das this Objekt in StreamHandler verwenden möchten, würde ich empfehlen, Pfeilfunktionen zu verwenden, wenn Ihre Version von Node sie unterstützt. Dieser Code funktioniert auch:

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"); 
    }); 
} 

Beachten Sie, dass mit Pfeil Funktionen, ich habe zu var self = this; nicht verwenden zu vermeiden, dass ist so ziemlich der Grund Pfeil Funktionen Javascript hinzugefügt wurden.

Hoffe, das hilft!

- EDIT -

Ok, dachte ich es aus. Das Problem in Ihrem Code ist diese Zeile:

self = this; 

Es sollte sein:

var self = this; 

Ohne die var Spezifizierer, führen Sie eine globale Variable zu schaffen. Wenn Sie zum zweiten Mal new StreamHandler aufrufen, überschreiben Sie die Variable self.Deshalb hängt die Datei test1.mp3 hängt und die test2.mp3 Datei ist die einzige abgeschlossen. Indem Sie var hinzufügen, funktioniert Ihr ursprüngliches Skript jetzt für mich.

+0

Danke. Werde es später anschauen. Ich hoffe wirklich, dass jemand anderes weiß, warum es nicht auf meine Art funktioniert, also kann ich diesem Problem in Zukunft ausweichen – Alaska

+0

@Alaska Siehe den obigen Beitrag. –

+0

Danke. Es funktionierte! – Alaska