This tutorial will show you how to use the FFmpeg from a Node.js app.
FFmpeg is a versatile open-source tool for encoding video files and performing basic editing operations such as stitching, cropping, and resizing. You probably know it can run from the terminal, but did you know it can also be invoked from an application in Node.js, for example, to automate video processing?
Would you prefer to use an API rather than managing your own server infrastructure? Check out our Video Editing API for developers. It allows you to design your own templates using a drag-and-drop video editor and automate them through a simple REST API. Better yet, it's less expensive than hosting your own video servers.
Make sure you install the ffmpeg-static and ffmpeg-fluent NPM packages first. The ffmpeg-static package provides a static build of FFmpeg, so you don't need to worry about installing it manually on the machine where you will deploy your application, and ffmpeg-fluent gives us a simple interface to run FFmpeg commands from JavaScript.
1$ npm i ffmpeg-static fluent-ffmpeg
In order to extract audio from a video file and store it as an MP3, we can use the following code:
1const ffmpegStatic = require('ffmpeg-static');
2const ffmpeg = require('fluent-ffmpeg');
3
4// Tell fluent-ffmpeg where it can find FFmpeg
5ffmpeg.setFfmpegPath(ffmpegStatic);
6
7// Run FFmpeg
8ffmpeg()
9
10 // Input file
11 .input('video.mp4')
12
13 // Audio bit rate
14 .outputOptions('-ab', '192k')
15
16 // Output file
17 .saveToFile('audio.mp3')
18
19 // Log the percentage of work completed
20 .on('progress', (progress) => {
21 if (progress.percent) {
22 console.log(`Processing: ${Math.floor(progress.percent)}% done`);
23 }
24 })
25
26 // The callback that is run when FFmpeg is finished
27 .on('end', () => {
28 console.log('FFmpeg has finished.');
29 })
30
31 // The callback that is run when FFmpeg encountered an error
32 .on('error', (error) => {
33 console.error(error);
34 });
35
Here's how to resize a video while maintaining its aspect ratio:
1const ffmpegStatic = require('ffmpeg-static');
2const ffmpeg = require('fluent-ffmpeg');
3
4// Tell fluent-ffmpeg where it can find FFmpeg
5ffmpeg.setFfmpegPath(ffmpegStatic);
6
7// Run FFmpeg
8ffmpeg()
9
10 // Input file
11 .input('video.mp4')
12
13 // Scale the video to 720 pixels in height. The -2 means FFmpeg should figure out the
14 // exact size of the other dimension. In other words, to make the video 720 pixels wide
15 // and make FFmpeg calculate its height, use scale=720:-2 instead.
16 .outputOptions('-vf','scale=-2:720')
17
18 // Output file
19 .saveToFile('video.mp4')
20
21 // Log the percentage of work completed
22 .on('progress', (progress) => {
23 if (progress.percent) {
24 console.log(`Processing: ${Math.floor(progress.percent)}% done`);
25 }
26 })
27
28 // The callback that is run when FFmpeg is finished
29 .on('end', () => {
30 console.log('FFmpeg has finished.');
31 })
32
33 // The callback that is run when FFmpeg encountered an error
34 .on('error', (error) => {
35 console.error(error);
36 });
37
This is how you can remove the audio track from a video without re-encoding. This operation is quite fast, because it doesn't have to process the video. It just copies the video stream but not the audio:
1const ffmpegStatic = require('ffmpeg-static');
2const ffmpeg = require('fluent-ffmpeg');
3
4// Tell fluent-ffmpeg where it can find FFmpeg
5ffmpeg.setFfmpegPath(ffmpegStatic);
6
7// Run FFmpeg
8ffmpeg()
9
10 // Input file
11 .input('video.mp4')
12
13 // Tell FFmpeg to ignore the audio track
14 .noAudio()
15
16 // Copy the video without re-encoding
17 .outputOptions('-codec', 'copy')
18
19 // Output file
20 .saveToFile('video.mp4')
21
22 // Log the percentage of work completed
23 .on('progress', (progress) => {
24 if (progress.percent) {
25 console.log(`Processing: ${Math.floor(progress.percent)}% done`);
26 }
27 })
28
29 // The callback that is run when FFmpeg is finished
30 .on('end', () => {
31 console.log('FFmpeg has finished.');
32 })
33
34 // The callback that is run when FFmpeg encountered an error
35 .on('error', (error) => {
36 console.error(error);
37 });
38
Here's how to grab the frames from a video and save them as PNG:
1const ffmpegStatic = require('ffmpeg-static');
2const ffmpeg = require('fluent-ffmpeg');
3
4// Tell fluent-ffmpeg where it can find FFmpeg
5ffmpeg.setFfmpegPath(ffmpegStatic);
6
7// Run FFmpeg
8ffmpeg()
9
10 // Input file
11 .input('video.mp4')
12
13 // Optional: Extract the frames at this frame rate
14 // .fps(10)
15
16 // Output file format. Frames are stored as frame-001.png, frame-002.png, frame-003.png, etc.
17 .saveToFile('frame-%03d.png')
18
19 // Log the percentage of work completed
20 .on('progress', (progress) => {
21 if (progress.percent) {
22 console.log(`Processing: ${Math.floor(progress.percent)}% done`);
23 }
24 })
25
26 // The callback that is run when FFmpeg is finished
27 .on('end', () => {
28 console.log('FFmpeg has finished.');
29 })
30
31 // The callback that is run when FFmpeg encountered an error
32 .on('error', (error) => {
33 console.error(error);
34 });
35
Like the previous example, but the other way around:
1const ffmpegStatic = require('ffmpeg-static');
2const ffmpeg = require('fluent-ffmpeg');
3
4// Tell fluent-ffmpeg where it can find FFmpeg
5ffmpeg.setFfmpegPath(ffmpegStatic);
6
7// Run FFmpeg
8ffmpeg()
9
10 // FFmpeg expects your frames to be named like frame-001.png, frame-002.png, etc.
11 .input('frame-%03d.png')
12
13 // Tell FFmpeg to import the frames at 10 fps
14 .inputOptions('-framerate', '10')
15
16 // Use the x264 video codec
17 .videoCodec('libx264')
18
19 // Use YUV color space with 4:2:0 chroma subsampling for maximum compatibility with
20 // video players
21 .outputOptions('-pix_fmt', 'yuv420p')
22
23 // Output file
24 .saveToFile('video.mp4')
25
26 // Log the percentage of work completed
27 .on('progress', (progress) => {
28 if (progress.percent) {
29 console.log(`Processing: ${Math.floor(progress.percent)}% done`);
30 }
31 })
32
33 // The callback that is run when FFmpeg is finished
34 .on('end', () => {
35 console.log('FFmpeg has finished.');
36 })
37
38 // The callback that is run when FFmpeg encountered an error
39 .on('error', (error) => {
40 console.error(error);
41 });
42