Open pyldin601 opened 7 years ago
You'd have to write some wrapper code for that. But as I recall, using both input and output streams with an external process in nodejs can lead to deadlocks.
In case anyone needed I manage to use it with Transform streams (I need to encode audio to ogg and pass to Google Storage without saving locally). Here is my code:
const ffmpeg = require('fluent-ffmpeg')
const transformStream = require('stream')
const oggstream = new transformStream.Transform()
oggstream._transform = function (data, encoding, done) {
this.push(data)
done()
}
// stream is any readableStream
const transcode = ffmpeg(stream).audioCodec('libopus').format('ogg').audioFilters('loudnorm').outputOptions(['-ar 16000', '-b:a 24000'])
.on('error', function(err) {
console.log('an error happened: ' + err.message);
})
.on('end', function() {
console.log('file has been converted succesfully');
})
// save to stream
.pipe(oggstream)
then you can consume oggstream again as any readable stream
To wrap fluent-ffmpeg as a Transform, basically we use a PassThrough for fluent-ffmpeg's input and output respectively, and the combine the two PassThrough as a Duplex, such that when the previous stream (input) writes to the Duplex it goes to ffmpeg's input, and when next stream (output) reads from the Duplex it actually takes data from ffmpeg's output.
Environment: NodeJS 18
const { pipeline, PassThrough, Duplex } = require('stream');
const fs = require('fs');
const ffmpeg = require('fluent-ffmpeg');
// Returns a Duplex stream whose input and output are connected (basically a Transform)
//
function getFfmpegTransform() {
const input = new PassThrough();
const output = new PassThrough();
ffmpeg(input)
.on('stderr', function(stderrLine) {
console.log('Stderr output: ' + stderrLine);
})
// Stream input requires manually specifying input format
.inputFormat('mp4')
// Stream output requires manually specifying output format
.format('mp4')
// Stream output requires fragmented output
// https://github.com/fluent-ffmpeg/node-fluent-ffmpeg/issues/346#issuecomment-67299526
.outputOptions('-movflags dash')
.pipe(output);
return Duplex.from({
// previous stream writes to input
writable: input,
// next stream reads from output
readable: output,
});
}
// Use getFfmpegTransform() as a Transform stream:
pipeline(
fs.createReadStream('input.mp4'),
getFfmpegTransform(),
fs.createWriteStream('output.mp4'),
console.log
);
ffmpeg can use Readable stream for input and Writable stream as output, but I can't see is it possible to use ffmpeg as Transform stream?