Skip to content

Commit

Permalink
docs(example): update ffmpeg example (#818)
Browse files Browse the repository at this point in the history
* remove audioonly and videoonly from ytdl calls
* start the progressbar when ffmpeg outputs data
* simplify ffmpeg arguments to represent a simple audio & video merge into file
* adjust parsing of the key=value pairs
* force close the program when done
  • Loading branch information
TimeForANinja committed Dec 11, 2020
1 parent 6554d05 commit 15d24f1
Showing 1 changed file with 33 additions and 25 deletions.
58 changes: 33 additions & 25 deletions example/ffmpeg.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
* Reencode audio & video without creating files first
*
* Requirements: ffmpeg, ether via a manual installation or via ffmpeg-static
*
* If you need more complex features like an output-stream you can check the older, more complex example:
* https://github.com/fent/node-ytdl-core/blob/cc6720f9387088d6253acc71c8a49000544d4d2a/example/ffmpeg.js
*/

// Buildin with nodejs
const fs = require('fs');
const cp = require('child_process');
const readline = require('readline');
// External modules
Expand All @@ -20,18 +22,20 @@ const tracker = {
merged: { frame: 0, speed: '0x', fps: 0 },
};

// Get audio and video stream going
const audio = ytdl(ref, { filter: 'audioonly', quality: 'highestaudio' })
// Get audio and video streams
const audio = ytdl(ref, { quality: 'highestaudio' })
.on('progress', (_, downloaded, total) => {
tracker.audio = { downloaded, total };
});
const video = ytdl(ref, { filter: 'videoonly', quality: 'highestvideo' })
const video = ytdl(ref, { quality: 'highestvideo' })
.on('progress', (_, downloaded, total) => {
tracker.video = { downloaded, total };
});

// Get the progress bar going
const progressbar = setInterval(() => {
// Prepare the progress bar
let progressbarHandle = null;
const progressbarInterval = 1000;
const showProgress = () => {
readline.cursorTo(process.stdout, 0);
const toMB = i => (i / 1024 / 1024).toFixed(2);

Expand All @@ -46,51 +50,55 @@ const progressbar = setInterval(() => {

process.stdout.write(`running for: ${((Date.now() - tracker.start) / 1000 / 60).toFixed(2)} Minutes.`);
readline.moveCursor(process.stdout, 0, -3);
}, 1000);
};

// Start the ffmpeg child process
const ffmpegProcess = cp.spawn(ffmpeg, [
// Remove ffmpeg's console spamming
'-loglevel', '0', '-hide_banner',
// Redirect/enable progress messages
'-loglevel', '8', '-hide_banner',
// Redirect/Enable progress messages
'-progress', 'pipe:3',
// 3 second audio offset
'-itsoffset', '3.0', '-i', 'pipe:4',
// Set inputs
'-i', 'pipe:4',
'-i', 'pipe:5',
// Rescale the video
'-vf', 'scale=320:240',
// Choose some fancy codes
'-c:v', 'libx265', '-x265-params', 'log-level=0',
'-c:a', 'flac',
// Define output container
'-f', 'matroska', 'pipe:6',
// Map audio & video from streams
'-map', '0:a',
'-map', '1:v',
// Keep encoding
'-c:v', 'copy',
// Define output file
'out.mkv',
], {
windowsHide: true,
stdio: [
/* Standard: stdin, stdout, stderr */
'inherit', 'inherit', 'inherit',
/* Custom: pipe:3, pipe:4, pipe:5, pipe:6 */
'pipe', 'pipe', 'pipe', 'pipe',
/* Custom: pipe:3, pipe:4, pipe:5 */
'pipe', 'pipe', 'pipe',
],
});
ffmpegProcess.on('close', () => {
process.stdout.write('\n\n\n\n');
clearInterval(progressbar);
console.log('done');
// Cleanup
process.stdout.write('\n\n\n\n');
clearInterval(progressbarHandle);
// Close the programm
process.exit(0);
});

// Link streams
// FFmpeg creates the transformer streams and we just have to insert / read data
ffmpegProcess.stdio[3].on('data', chunk => {
// Start the progress bar
if (!progressbarHandle) progressbarHandle = setInterval(showProgress, progressbarInterval);
// Parse the param=value list returned by ffmpeg
const lines = chunk.toString().trim().split('\n');
const args = {};
for (const l of lines) {
const [key, value] = l.trim().split('=');
args[key] = value;
const [key, value] = l.split('=');
args[key.trim()] = value.trim();
}
tracker.merged = args;
});
audio.pipe(ffmpegProcess.stdio[4]);
video.pipe(ffmpegProcess.stdio[5]);
ffmpegProcess.stdio[6].pipe(fs.createWriteStream('./out.mkv'));

0 comments on commit 15d24f1

Please sign in to comment.