How to Convert an Audio File into Video in NodeJS

Power of FFmpeg with NodeJS

Converting audio files into video files is an everyday use case in the current age of content production.

While there are many ways to do it via some custom websites, we programmers don’t follow that easy, simple path, right?

Today, I will show you how to convert an audio file into a video file in NodeJS.

What Will We Use?

We will use the power of FFmpeg. In their documentation, they identify themselves as:

A complete, cross-platform solution to record, convert and stream audio and video.

This is not something specific to NodeJS. Instead, it’s OS-level documentation that you can install on your machine by running the following commands on

Linux

sudo apt update
sudo apt install ffmpeg

And verifying the version

ffmpeg -version

If you are on macOS, it’s even easier.

brew install ffmpeg

If you want to learn how to use FFMpeg in Docker, you can check the following article. https://javascript.plainenglish.io/how-to-use-ffmpeg-with-node-js-and-docker-c21f56993e14

The problem with NodeJS

The problem is accessing the FFmpeg directly from NodeJS can be tricky. However, several libraries create an abstraction on top of the FFmpeg.

Some of the most notable ones are fluent-ffmpeg and ffcreator .

Today we will use the light version of ffcreator which is called ffcreatorlite

Let’s get started

I am assuming you already have a NodeJS project up and running. If not, then you can use the following boilerplate. https://github.com/Mohammad-Faisal/nodejs-typescript-skeleton Just run the following command:

git clone https://github.com/Mohammad-Faisal/nodejs-typescript-skeleton.git

It will give you a basic NodeJS project.

Install Dependencies

Add the required dependency

yarn add ffcreatorlite

Then add an audio file to the project. You will probably also want a cover image for your generated video, right? So bring that in too.

|- src
|----index.ts
|----source.mp3 // your audio file
|----cover.png // your cover image

That’s the preparation. Let’s build it.

Get the Individual Functions

First, you will need an instance of the FFcreator

import path from 'path';
import { FFScene, FFImage, FFCreator } from 'ffcreatorlite';

const CANVAS_WIDTH = 1246; // play with the dimensions. I am creating a 16:9 canvas for youtube videos
const CANVAS_HEIGHT = 700;
const VIDEO_DURATION = 30;

const getCreatorInstance = () => {
  const outputDir = path.join(__dirname, '../assets/output/'); // you can add anything
  const cacheDir = path.join(__dirname, '../assets/cache/');

  return new FFCreator({
        cacheDir,
        outputDir,
        width: CANVAS_WIDTH,
        height : CANVAS_WIDTH,
  });
}

Now add a function for adding the Audio:

const addAudio = (creator: FFCreator) => {
    const audio = `./source.mp3` // adding the audio
    creator.addAudio(audio);
    return creator
};

Another function to add the cover image:

 addCoverImage = (creator: FFCreator) => {
    const coverImagePath = './cover.png';

    const scene = new FFScene();
    scene.setDuration(VIDEO_DURATION);
    const backgroundImage = new FFImage({
      path: coverImagePath,
      x: 0,
      y: 0,
    });
    scene.addChild(backgroundImage);
    creator.addChild(scene);
    return creator
};

Let’s Combine Them All!

Now let’s combine these functions to create our video file from the audio file.

const generateVideoFromAudioFile = async (): Promise<string> => {
    return new Promise((resolve, reject) => {

      let creator = getCreatorInstance();
      creator = addAudio(creator);
      creator = addCoverImage(creator);

      creator.start();
      creator.closeLog();

      creator.on('start', () => {
        console.log(`FFCreator start`);
      });

      creator.on('error', (e: any) => {
        console.log(`FFCreator error: ${e.error}`);
        reject(e);
      });

      creator.on('progress', (e: any) => {
        console.log(`FFCreator progress: ${(e.percent * 100) >> 0}%`);
      });

      creator.on('complete', async (e: any) => {
        console.info(`FFCreator completed: \n USEAGE: ${e.useage} \n PATH: ${e.output} `);
        resolve(e.output);
      });
    });
  };

The syntax is a little weird because of the structure of the ffcreatorlite library, but what this essentially does:

1. Creates a creator instance
2. Adds a audio
3. Adds a cover image
4. Starts the process and wait's for it's completion
5. after completing returns the generated video file path

So, now you can run the function like the following:

await generateVideoFromAudioFile();

And after everything is finished, you will see a generated video file randomid.mp4 inside your project, which you can use any way you like.

Final Thoughts

I have shown a minimal use case that is possible to do with this awesome library. There are a lot of things that you can do with ffcreatorlite and ffcreator library like adding multiple images with transition and everything.

I encourage you to try that.

That’s it for today. Have a great day!

Profile Image

Who I am

Hi, I amMohammad Faisal, A full-stack software engineer @Cruise , working remotely from a small but beautiful country named Bangladesh.

I am most experienced inReactJS,NodeJS andAWS

Buy Me a Coffee Widget