Node.js Express FFMPEG Merge Multiple Videos Web App Project Tutorial For Beginners 2020

Node.js Express FFMPEG Merge Multiple Videos Web App Project Tutorial For Beginners 2020

 

 

 

 

 

Live Demo

 

 

The live demo of the app is given here

 

 

 

Get Started

 

In order to get started by building this project you need to install the below dependencies for your node.js project

 

npm init -y

 

npm i express

 

npm i multer

 

npm i nodemon

 

 

Now we will create the starting point of the application which is index.js and copy paste the following code to it

 

 

const express = require('express')

const app = express()

var dir = 'public';
var subDirectory = 'public/uploads'

if (!fs.existsSync(dir)){
    fs.mkdirSync(dir);

    fs.mkdirSync(subDirectory)

}


const PORT = process.env.PORT || 3000

app.get('/',(req,res) => {

    res.sendFile(__dirname + "/index.html")

})

app.listen(PORT,() => {
    console.log(`App is listening on Port ${PORT}`)
})

 

 

 

Creating Template File

 

 

Now we will create the template file which the user sees when it opens the application i.e. index.html

 

 

<!DOCTYPE html>
<html>
  <head>
    <title>Currency Converter in Javascript</title>
    <link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
    />
  </head>
  <body>
      <div class="container">
          <br><br>
          <h1 class="text-center">
              Merge Videos
          </h1>
          <br>
          <form action="/merge" method="post" enctype="multipart/form-data">
            <div class="form-group">
                <input type="file" name="files" multiple class="form-control" required>
            </div>
            <div class="form-group">
                <button class="btn btn-danger btn-block">
                    Merge Videos
                </button>
            </div>
        </form>
      </div>
</body>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</html>

 

 

 

Uploading Multiple Videos in Node.js Server

 

 

Now the next step is to upload multiple video files to node.js server so that we can process them with ffmpeg library and merge them together. For this we will be using multer library for this

See also  Node.js Send Email Through Gmail Using NodeMailer Library Full Project

 

Now copy paste the below code inside index.js

 

 

const multer = require('multer')


var storage = multer.diskStorage({
    destination: function (req, file, cb) {
      cb(null, 'public/uploads')
    },
    filename: function (req, file, cb) {
      cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname))
    }
})

const videoFilter = function(req, file, cb) {
    // Accept videos only
    if (!file.originalname.match(/\.(mp4)$/)) {
        req.fileValidationError = 'Only video files are allowed!';
        return cb(new Error('Only video files are allowed!'), false);
    }
    cb(null, true);
};

var upload = multer({storage:storage,fileFilter:videoFilter})



app.use(express.static('public'))

 

 

 

Merging Videos in POST Request

 

 

Now the main business logic of the application when we submit the form we need to make the post request and write this code inside index.js

 

 

const fs = require('fs')

const path = require('path')

const { exec } = require('child_process')

var list = ""

var listFilePath = 'public/uploads/' + Date.now() + 'list.txt'

var outputFilePath = Date.now() + 'output.mp4'




app.post('/merge',upload.array('files',1000),(req,res) => {
    if(req.files){
        
        req.files.forEach(file => {

            list += `file ${file.filename}`
            list += "\n"
            
        });

        var writeStream = fs.createWriteStream(listFilePath)

        writeStream.write(list)

        writeStream.end()

        exec(`ffmpeg -safe 0 -f concat -i ${listFilePath} -c copy ${outputFilePath}`, (error, stdout, stderr) => {
          
            if (error) {
                console.log(`error: ${error.message}`);
                return;
            }
            else{
                console.log("videos are successfully merged")
            res.download(outputFilePath,(err) => {
                if(err) throw err

                req.files.forEach(file => {
                    fs.unlinkSync(file.path)                    
                });

                fs.unlinkSync(listFilePath)
                fs.unlinkSync(outputFilePath)

              

            })
        }
            
        })
    }
})

 

 

 

Full Index.js File

 

 

const express = require('express')

const fs = require('fs')

const path = require('path')

const { exec } = require('child_process')

var list = ""

var listFilePath = 'public/uploads/' + Date.now() + 'list.txt'

var outputFilePath = Date.now() + 'output.mp4'

const bodyParser = require('body-parser')

const multer = require('multer')

const app = express()

var dir = 'public';
var subDirectory = 'public/uploads'

if (!fs.existsSync(dir)){
    fs.mkdirSync(dir);

    fs.mkdirSync(subDirectory)

}

var storage = multer.diskStorage({
    destination: function (req, file, cb) {
      cb(null, 'public/uploads')
    },
    filename: function (req, file, cb) {
      cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname))
    }
})

const videoFilter = function(req, file, cb) {
    // Accept videos only
    if (!file.originalname.match(/\.(mp4)$/)) {
        req.fileValidationError = 'Only video files are allowed!';
        return cb(new Error('Only video files are allowed!'), false);
    }
    cb(null, true);
};

var upload = multer({storage:storage,fileFilter:videoFilter})

app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())
app.use(express.static('public'))


const PORT = process.env.PORT || 3000

app.get('/',(req,res) => {

    res.sendFile(__dirname + "/index.html")

})

app.post('/merge',upload.array('files',1000),(req,res) => {

    list = ""
    if(req.files){
        
        req.files.forEach(file => {

            list += `file ${file.filename}`
            list += "\n"
            
        });

        var writeStream = fs.createWriteStream(listFilePath)

        writeStream.write(list)

        writeStream.end()

        exec(`ffmpeg -safe 0 -f concat -i ${listFilePath} -c copy ${outputFilePath}`, (error, stdout, stderr) => {
          
            if (error) {
                console.log(`error: ${error.message}`);
                return;
            }
            else{
                console.log("videos are successfully merged")
            res.download(outputFilePath,(err) => {
                if(err) throw err

                req.files.forEach(file => {
                    fs.unlinkSync(file.path)                    
                });

                fs.unlinkSync(listFilePath)
                fs.unlinkSync(outputFilePath)

              

            })
        }
            
        })
    }
})

app.listen(PORT,() => {
    console.log(`App is listening on Port ${PORT}`)
})

 

See also  JavaScript Program to Merge Property of Two Objects Using Object.assign() Method Full Project For Beginners

 

 

DOWNLOAD SOURCE CODE

 

 

 

Leave a Reply