Close Menu
Soshace Digital Blog

    Subscribe to Updates

    Get The Latest News, Updates, And Amazing Offers

    What's Hot
    B2B Leads

    Effective Networking Strategies to Boost B2B Lead Generation

    Programming

    9. Уроки Node.js. События, EventEmitter и Утечки Памяти

    Soshace

    Happy New 2020 Year!

    Important Pages:
    • Home
    • About
    • Services
    • Contact Us
    • Privacy Policy
    • Terms & Conditions
    Facebook X (Twitter) Instagram LinkedIn YouTube
    Today's Picks:
    • Scaling Success: Monitoring Indexation of Programmatic SEO Content
    • Leveraging Influencers: Key Drivers in New Product Launches
    • How Privacy-First Marketing Will Transform the Industry Landscape
    • The Impact of Social Proof on Thought Leadership Marketing
    • Balancing Value-Driven Content and Promotional Messaging Strategies
    • Top Influencer Marketing Platforms to Explore in 2025
    • Emerging Trends in Marketing Automation and AI Tools for 2023
    • Strategies to Mitigate Duplicate Content in Programmatic SEO
    Wednesday, September 10
    Facebook X (Twitter) Instagram LinkedIn YouTube
    Soshace Digital Blog
    • Home
    • About
    • Services
    • Contact Us
    • Privacy Policy
    • Terms & Conditions
    Services
    • SaaS & Tech

      Maximizing Efficiency: How SaaS Lowers IT Infrastructure Costs

      August 27, 2025

      Navigating Tomorrow: Innovations Shaping the Future of SaaS

      August 27, 2025

      Maximizing Impact: Strategies for SaaS & Technology Marketing

      August 27, 2025
    • AI & Automation

      Enhancing Customer Feedback Analysis Through AI Innovations

      August 27, 2025

      Navigating the Impact of AI on SEO and Search Rankings

      August 27, 2025

      5 Automation Hacks Every Home Service Business Needs to Know

      May 3, 2025
    • Finance & Fintech

      Critical Missteps in Finance Marketing: What to Avoid

      August 27, 2025

      Analyzing Future Fintech Marketing Trends: Insights Ahead

      August 27, 2025

      Navigating the Complex Landscape of Finance and Fintech Marketing

      August 27, 2025
    • Legal & Compliance

      Exploring Thought Leadership’s Impact on Legal Marketing

      August 27, 2025

      Maximizing LinkedIn: Strategies for Legal and Compliance Marketing

      August 27, 2025

      Why Transparency Matters in Legal Advertising Practices

      August 27, 2025
    • Medical Marketing

      Enhancing Online Reputation Management in Hospitals: A Guide

      August 27, 2025

      Analyzing Emerging Trends in Health and Medical Marketing

      August 27, 2025

      Exploring Innovative Content Ideas for Wellness Blogs and Clinics

      August 27, 2025
    • E-commerce & Retail

      Strategic Seasonal Campaign Concepts for Online and Retail Markets

      August 27, 2025

      Emerging Trends in E-commerce and Retail Marketing Strategies

      August 27, 2025

      Maximizing Revenue: The Advantages of Affiliate Marketing for E-Commerce

      August 27, 2025
    • Influencer & Community

      Leveraging Influencers: Key Drivers in New Product Launches

      August 27, 2025

      Top Influencer Marketing Platforms to Explore in 2025

      August 27, 2025

      Key Strategies for Successful Influencer Partnership Negotiations

      August 27, 2025
    • Content & Leadership

      The Impact of Social Proof on Thought Leadership Marketing

      August 27, 2025

      Balancing Value-Driven Content and Promotional Messaging Strategies

      August 27, 2025

      Analyzing Storytelling’s Impact on Content Marketing Effectiveness

      August 27, 2025
    • SEO & Analytics

      Scaling Success: Monitoring Indexation of Programmatic SEO Content

      August 27, 2025

      Strategies to Mitigate Duplicate Content in Programmatic SEO

      August 27, 2025

      Effective Data Visualization Techniques for SEO Reporting

      August 27, 2025
    • Marketing Trends

      How Privacy-First Marketing Will Transform the Industry Landscape

      August 27, 2025

      Emerging Trends in Marketing Automation and AI Tools for 2023

      August 27, 2025

      Maximizing ROI: Key Trends in Paid Social Advertising

      August 27, 2025
    Soshace Digital Blog
    Blog / JavaScript / Node.js / Express.js / Anime.js to MP4 and GIF with Node.js and FFMPEG
    Express.js

    Anime.js to MP4 and GIF with Node.js and FFMPEG

    JavedBy JavedApril 25, 2023Updated:April 25, 2023No Comments20 Mins Read
    Facebook Twitter Pinterest Telegram LinkedIn Tumblr Email Reddit
    Anime.js to MP4 and GIF with Node.js and FFMPEG
    Share
    Facebook Twitter LinkedIn Pinterest Email Copy Link
    Anime.js to MP4 and GIF with Node.js and FFMPEG
    Anime.js to MP4 and GIF with Node.js and FFMPEG

    Overview

    When it comes to web animations, there are two popular options available: canvas-based animation using pixel-based drawings or CSS-based animation applied on HTML DOM elements.

    While canvas animation is often considered the simpler approach for exporting animations to video and GIF formats, it can also limit the range of animations that can be created. Although complex and advanced animations are a possibility, it can quickly become a memory-intensive operation, especially when exporting to popular animation formats.

    On the other hand, CSS-based animation tools like anime.js offer a more lightweight yet powerful approach to animation, allowing for more complex and visually engaging animations. With anime.js, you can create animations that manipulate CSS properties like colors, opacity, transforms, and more to achieve a wide range of effects. However, exporting these animations to video and GIF formats on the server side can be a more challenging task due to the complexities of translating the CSS-based animation into an accurate video or GIF output.

    What we’re going to build:

    In this article, I will provides a detailed and step-by-step instructions to converting anime.js animations from the client-side to MP4 and GIF formats on the server-side. The process involves utilizing a combination of Node.js modules and FFMPEG executable to successfully achieve the conversion.

    The process starts by first setting up the project’s base structure and configuring the Node.js environment with the necessary modules. Next, it involves creating an anime.js animation on the client-end, as well as writing a combination of server-side scripts to generate an MP4 video of the animated HTML DOM elements.

    Then, by taking it one step further and with minimum of effort, I will demonstrate how you can further enhance the output capabilities by adding an FFMPEG executable in the mix to seamlessly convert the MP4 video output to a GIF file.

    Since handling dynamic animations and video generation is normally a resource-intensive process, I will also be mindful that the solutions offered in this guide not only allow for greater flexibility but also optimize the workflow and minimize resource usage.

    Setting up the Project:

    To get started, let’s set up our project with the necessary dependencies and structure. Express Generator, a widely-used Node.js tool, can help us quickly initialize our project and establish the base.

    First install Express Generator globally by running the following command in your terminal:

    npm install -g express-generator

    Then run the following command on the project’s terminal:

    express --view=hbs anime.js-to-mp4-gif

    This command creates a new directory named “anime.js-to-mp4-gif” with a basic structure for an Express app using the Handlebars (hbs) view engine.

    Here’s a possible diagram of the project’s directory structure created by Express Generator:

    anime.js-to-mp4-gif/
    ├── app.js
    ├── bin
    │ └── www
    ├── node_modules/
    ├── package.json
    ├── public/
    │ ├── images/
    │ ├── javascripts/
    │ └── stylesheets/
    ├── routes/
    │ └── index.js
    └── views/
    ├── error.hbs
    ├── index.hbs
    └── layout.hbs

    In this structure, app.js is the main file for our application. The bin/www file is responsible for starting the server. The public directory contains static assets including images, JavaScript, and CSS files. The views folder is from where the templates are loaded from and rendered by our application.

    Also make sure to that you have installed the necessary dependencies listed in the package.json file:

    npm install

    Adding Elements

    It’s time to start adding elements that we intend to animate. Add the code below to the layout.hbs template file from the /views folder at the root of your project’s directory:

    <!DOCTYPE html>
    <html>
    <head>
      <title>Anime.js to MP4 | GIF</title>
      <link rel='stylesheet' href='/stylesheets/style.css' />
      <link href="https://fonts.googleapis.com/css?family=Graduate:300,400,700" rel="stylesheet">
      <link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@400;700&display=swap" rel="stylesheet">
      <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.0/anime.min.js"></script>
    </head>
    <body>
      {{{body}}}
    </body>
    </html>

    This code snippet sets up the layout structure for the HTML page. In order to style and animate client-side elements, google fonts and anime.js library are imported via link and script tags, respectively, in the head section of our layout.hbs file. The {{{body}}} placeholder in the body section is where the main content of our project’s index.hbs page will be inserted.

    Next, add the following code in the index.hbs template file from the views folder:

    <h1>Anime.js to MP4 Video</h1>
    <p>with FFMPEG & Node.js</p>
    
    <section class="columns">
    <div class="container">
    <div class="svg">.... SVG code for the icon (available on GitHub) ...</div>
    <div class="company">Company Name</div><div class="slogan">Company Slogan</div>
    </div>
    </section>
    
    <section class="columns">
    <button class="button" type="button">Convert</button>
    </section>

    The index.hbs template file now has a div element with the class name container, which will hold the elements that needs to animate. In this case, there are three elements within the parent div: a div with the class name svg, which contains an SVG icon, followed by two more div elements, with the class name company and slogan respectively.

    Finally, in order to ensure that the added elements are visually consistent with the rest of the page, let’s add some CSS in your style.css file located in the /public/stylesheets folder.

    .svg {
        left:220px;
        top:55px;
        position:relative;
        width:130px;
        height:auto;
    }
    .company {
        font-size: 2em;
        color:#FF4F00;
        font-family: 'Graduate', sans-serif;
        left:150px;
        top:60px;
        position:relative;
    }
    .slogan {
        font-size: 1em;
        color:#9E9C98;
        font-family: 'Quicksand', sans-serif;
        left:220px;
        top:65px;
        position:relative;
    }
    .columns {
        display: flex;
        flex-flow: row wrap;
        justify-content: center;
        margin: 5px 0;
    }
    .container {
        flex: 1;
        border: 1px solid gray;
        margin: 2px;
        padding: 0px;
        &:first-child {
             margin-left: 0;
        }
        &:last-child {
             margin-right: 0;
        }
        max-width:600px;
        height:300px;
    }
    .button {
        appearance: none;
        background-color: #FAFBFC;
        border: 1px solid rgba(27, 31, 35, 0.15);
        border-radius: 6px;
        box-shadow: rgba(27, 31, 35, 0.04) 0 1px 0, rgba(255, 255, 255, 0.25) 0 1px 0 inset;
        box-sizing: border-box;
        color: #24292E;
        cursor: pointer;
        display: inline-block;
        font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
        font-size: 14px;
        font-weight: 500;
        line-height: 20px;
        list-style: none;
        padding: 6px 16px;
        position: relative;
        transition: background-color 0.2s cubic-bezier(0.3, 0, 0.5, 1);
        user-select: none;
        -webkit-user-select: none;
        touch-action: manipulation;
        vertical-align: middle;
        white-space: nowrap;
        word-wrap: break-word;
    }
    

    The .svg, .company, and .slogan classes are used to position and style the SVG icon, company name, and slogan, respectively. The .container class is used to set the styling for the container that holds the SVG icon and the related text elements in our layout.

    Run your project using the command npm start.

     

    Launch http://localhost:3000 on your browser to view your page.
    Launch http://localhost:3000 on your browser to view your page.

    Opting to use a professionally styled logo for our project is to demonstrate that by utilizing the methods discussed here, you can easily export animations of highly aesthetic elements to pixel perfect MP4 and GIF outputs.

    Adding Animation

    It is time to start applying animation to the existing elements. Create an index.js file in the /public/javascripts folder, which is where the JavaScript code to initiate and control the client-side animation will be placed:

    window.addEventListener("DOMContentLoaded", () => {
    let timeline = anime.timeline({loop: false,autoplay: true})
    
    function initiate() {
    
    timeline.add({
    targets: '.svg',
    scale: [0, 1],
    opacity: [0,1],
    easing: 'easeOutExpo',
    duration: 1500,
    endDelay: 0
    }).add({
    targets: '.company',
    "translateX": [-150, 0],
    opacity: [0,1],
    duration: 2000,
    endDelay: 0}).add({
    targets: '.slogan',
    "translateY": [50, 0],
    opacity: [0,1],
    duration: 1000,
    endDelay: 0
    })};
    
    initiate();
    
    });

    The above code snippet adds the animation to the timeline and initiates the animation sequence when the DOMContentLoaded event is fired. This ensures that the animation is only initiated once the relevant elements are available in the DOM.

    An anime.timeline object is initiated with the loop property set to false and the autoplay to true. Next, a function initiate is defined responsible for handling the individual animations to the timeline. Finally, a timeline.add method is used to add the animations.

    Read More:  Create simple POS with React, Node and MongoDB #2: Auth state, Logout, Update Profile

    Breakdown:

    • The first animation targets the .svg element and scales it from 0 to 1 while also increasing its opacity. The easing function used is easeOutExpo, and the duration is set to 1500 milliseconds.
    • The second animation targets the .company text element and translates it from -150px to 0px on the X-axis while also increasing its opacity. The duration is set to 2000 milliseconds.
    • The third animation targets the .slogan , also a text element, and translates it from 50px to 0px on the Y-axis while also increasing its opacity. The duration is set to 1000 milliseconds.

    Next, the initiate function is invoked to start the animation sequence.

    Import the index.js file in our index.hbs template.

    <script src="/javascripts/index.js"></script>
    Reload the page to see the animation in action!
    Reload the page to see the animation in action!

    In the next step, I will demonstrate the significance of keeping our animation code within the initiate function and how it ensures an accurate transition of capturing and posting the animation data to the server-side for conversion.

    Exporting to Server-side API

    Until this point, we have established the project, created the DOM elements, and implemented animations. While these tasks are significant, they are relatively straightforward compared to the upcoming critical steps. We have now reached the core of the process that directly impacts the end result.

    As I mentioned earlier in this article, handling dynamic animations and video generation can be a resource-intensive operation. Therefore, it is also crucial to opt for an approach that is minimalist in nature and helps optimize the workflow.

    Add the following code snippet to the index.js file:

    const convert = async () => {
    
    let data = {
        html: document.querySelectorAll('.container')[0].outerHTML,
        animation: initiate.toLocaleString(),
        duration: Number(timeline.duration/1000),
        width: document.querySelectorAll('.container')[0].offsetWidth,
        height: document.querySelectorAll('.container')[0].offsetHeight,
      }
      const response = await fetch("/convert-to-video", {
        method: "POST",
        headers: {
          "content-type": "application/json",
        },
        body: JSON.stringify(data),
      });
    
    };
    
    

    A convert function is defined, along with an object data with a following set of parameters:

    Breakdown:

    • The html parameter uses document.querySelectorAll to store the entire HTML content of the container element withholding the animated objects, including the parent element itself.
    • Since initiate is a function that contains the animation timeline, toLocaleString() is used to convert the initiate function to a string so that it can be included in the animation parameter being sent to the server.
    • The duration parameter is being set to the duration of the animation timeline created using anime.js. The timeline duration is measured in milliseconds, but the server-side conversion expects the duration to be provided in seconds. Hence, the duration value is divided by 1000 and converted to a number using the Number() method.
    • The width parameter is being set to the width of the container element. The offsetWidth property is used to retrieve the width of the element in pixels.
    • For the height parameter, similar to it’s offsetWidth counterpart, the offsetHeight property is used to retrieve the height of the container element in pixels.

    Including the aforementioned parameters in the data object ensures that the server API receives the accurate animation data required to convert the animation to MP4 and GIF formats. Moreover, utilizing JavaScript’s toLocaleString() method to stringify the initiate function also keeps the payload greatly reduced to achieve faster load times and improved overall performance.

    Next, the data object is passed as the body of the request, and sent as a POST request to a /convert-to-video endpoint by utilizing a fetch API.

    Finally, let’s bind the convert function to the onclick event of the submit button.

    document.querySelectorAll('.button')[0].onclick = convert;

    The Conversion Process

    • Creating the videoRouter:

    To handle the POST request sent from the client, a new route in our server-side code needs to be created. This route will receive the animation data sent from the fetch api and process it for conversion.

    Open the app.js file from the project’s root directory and add the following code:

    var videoRouter = require('./routes/video');
    app.use('/', videoRouter);
    

    Your app.js should now look like this.

    var createError = require('http-errors');
    var express = require('express');
    var path = require('path');
    
    var indexRouter = require('./routes/index');
    var videoRouter = require('./routes/video');
    
    var app = express();
    
    app.set('views', path.join(__dirname, 'views'));
    app.set('view engine', 'hbs');
    
    app.use(express.json());
    app.use(express.urlencoded({ extended: false }));
    app.use(express.static(path.join(__dirname, 'public')));
    
    app.use('/', indexRouter);
    app.use('/', videoRouter);
    
    app.use(function(req, res, next) {
      next(createError(404));
    });
    
    app.use(function(err, req, res, next) {
      res.locals.message = err.message;
      res.locals.error = req.app.get('env') === 'development' ? err : {};
    
      res.status(err.status || 500);
      res.render('error');
    });
    
    module.exports = app;
    
    

    Creating the videoRouter route allows us to handle requests at the root endpoint. Next, create a video.js file in the routes directory of our project.

    var express = require('express');
    var router = express.Router();
    
    router.post('/convert-to-video', async function(req, res) {
      
    let data = req.body;
      
    // Process animation data here
    
    });
    
    module.exports = router;

    Our videoRouter route now listens for a POST request at the /convert-to-video endpoint. It also retrieves the animation data sent in the request body using the req.body object.

    • Replicating the Animation on Server-side:

    To create a precise MP4 version of our animation, the server-side scripts will need to be served with an identical copy of our client-side animated DOM elements and structure. This is where toHTML.js module comes into play, ensuring that animated DOM elements are duplicated and saved on the server-side as an HTML file.

    Starting by create a new folder called modules at the root of our project where all the server-side code conversion will be stored. Next, create your first module, toHTML.js, inside the modules folder with the following code:

    const fs = require('fs');
    
    exports.toHTML = async(data) => {
      return new Promise(function(resolve, reject) {
    
        let html = `<html>
        <body style="margin:0px">
        <link rel="stylesheet" href="../stylesheets/style.css" />
        <link href="https://fonts.googleapis.com/css?family=Graduate:300,400,700" rel="stylesheet">
        <link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@400;700&display=swap" rel="stylesheet">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.0/anime.min.js"></script>
        ${data.html}
        <script>
          window.addEventListener("DOMContentLoaded", () => {
            let timeline = anime.timeline({ loop: false, autoplay: true });
            ${data.animation} initiate();
          });
        </script>
        </body>
        </html>`;
    
        fs.writeFileSync("./public/output/animation.html", html);
    
        resolve('success');
    
      });
    };

    The toHTML module takes in parameters data.html and data.animation, containing the animated DOM element’s HTML markup and the initiate function code in an stringify form respectively. By utilizing these params, toHTML module is able to generate an HTML code similar to the one created on the client, and then write it to an HTML file called animation.html in the /public/output folder of the project.

    We now have a file that will enable us to replicate the animation on the server-side. If you open the server-side generated animation.html in your browser, it will play the exact same animation as created on the client end.

    Here’s the code of the generated animation.html file for a quick comparison:

    <html>
      <body style="margin:0px">
        <link rel="stylesheet" href="../stylesheets/style.css" />
        <link href="https://fonts.googleapis.com/css?family=Graduate:300,400,700" rel="stylesheet">
        <link href="https://fonts.googleapis.com/css?family=Graduate:300,400,700" rel="stylesheet">
        <link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@400;700&display=swap" rel="stylesheet">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.0/anime.min.js"></script>
        <div class="container">
    
    <div class="svg">
    .... SVG code for the icon (available on GitHub) ...
    </svg>
    
    </div>
    
    <div class="company">Company Name</div>
    <div class="slogan">Company Slogan</div>
    
    </div>
        
    <script>
    
    window.addEventListener("DOMContentLoaded", () => {
    
    let timeline = anime.timeline({ loop: false, autoplay: true });
            
    function initiate() { 
     
    timeline.add({
        targets: '.svg',
        scale: [0, 1],
        opacity: [0,1],
        easing: 'easeOutExpo',
        duration: 1500,
        endDelay: 0
    }).add({
        targets: '.company',
         "translateX": [-150, 0],
        opacity: [0,1],
        duration: 2000,
        endDelay: 0
    }).add({
        targets: '.slogan',
        "translateY": [50, 0],
        opacity: [0,1],
        duration: 1000,
        endDelay: 0
    })
    
    } 
    
    initiate();
          
    });
        
    </script>
      
    </body>
    </html>

    By drawing parallels in terms of code structure to the client side equivalent of our generated animation.html file, you will find that there are only a few minor differences such as the animation script is now inline, and the body margin set to zero to avoid any unwanted margins in the output. Additionally, the timeline is declared with its scope set to global to avoid code breaks since it was defined outside the scope of the original initiate function.

    Next, call toHTML module inside the video.js route file:

    var express = require('express');
    var router = express.Router();
    
    const { toHTML } = require('../modules/toHTML.js');
    
    router.post('/convert-to-video', async function(req, res) {
      let data = req.body;
      await toHTML(data);
      res.send('success');
    });

    Our server-side is now ready to proceed with the conversion process.

    • Conversion to MP4 using timecut:

    The timecut module of Node.js is specifically developed to capture videos of web pages that use JavaScript animations with smooth transitions. It works by opening the web page, replacing its time-handling functions, taking snapshots of the page, and sending the results to FFMPEG for encoding the frames into a video. This process enables high-fps capture of frames, ensuring that the resulting videos have smooth transitions.

    Read More:  Data Science Overview: The Bigger Picture

    Install timecut to our project by running the following command:

    npm install timecut

    Then create a folder called “ffmpeg” at the root of our project and place the ffmpeg executable file in it.

    Note: To download the ffmpeg executable for your preferred operating system, you can visit its official website at https://ffmpeg.org/download.html.

    Next, create a toMP.js module file inside the modules folder, containing the script to perform the MP4 conversion using the timecut module:

    const timecut = require('timecut');
    
    exports.toMP4 = async(data) => {
     
    return new Promise(function(resolve, reject) {
    timecut({
    url: './public/output/animation.html',
    viewport: {
    width: data.width,
    height:data.height
    },
    selector: '.container',
    left: 0, 
    top: 0,
    right: 0, 
    bottom: 0, 
    width: data.width,
    height:data.height,
    fps: 30,  
    launchArguments: ['--no-sandbox', '--disable-setuid-sandbox'],
    duration: data.duration,       
    output: './public/output/animation.mp4',
    ffmpegPath: process.cwd()+'/ffmpeg/ffmpeg'
    }).then(function () {
    resolve('success');
    }); 
    });
    };

    Breakdown

    • The toMP4 module takes in the data object as input, which contains the width, height, and duration of the animation.
    • The timecut function captures the animation from the animation.html file. The viewport object is used to set the width and height of the captured video. The selector specifies the container element that contains the animation. The fps option sets the frames per second of the resulting video, and the duration option specifies the duration of the video in seconds.
    • The launchArguments option is used to pass additional arguments to the browser instance, and the output option specifies the output file path for the MP4 file.
    • The ffmpegPath option specifies the path to the ffmpeg executable file downloaded earlier, and is used to encode the captured frames into an MP4 video.

    This part of the process is comparatively straightforward since all that needs to be done is to serve the server-side animation.html file to the timecut module along with few other essential parameters and timecut will take care of the rest.

    To ensure that the MP4 starts generating only when the animation.html is successfully created, call the toMP4 below the toHTML module:

    var express = require('express');
    var router = express.Router();
    
    const { toHTML } = require('../modules/toHTML.js');
    
    router.post('/convert-to-video', async function(req, res) {
      
    let data = req.body;
      
    await toHTML(data); 
    await toMP4(data);
      
    res.send('success');
    
    });

    Post your animation data and initiate the server-side process by clicking the convert button.

    Frame by frame conversion in real-time in the terminal of your project.
    Frame by frame conversion in real-time in the terminal of your project.

    Our animation is around 4.5 seconds long, hence, at a frame rate of 30 fps, it will produce a total of 135 frames. These frames will be converted into an animation.mp4 file and saved in the /public/outputfolder using FFMPEG executable.

    The view of the generated MP4 video
    The view of the generated MP4 video
    • Conversion to GIF with FFMPEG

    Since we already have the MP4 file, generating a GIF version of the same becomes a straightforward process that involves running couple of FFMPEG commands.

    Please bear in mind that the FFMPEG library needs to first generate a palette file that will be used to create the GIF output. The palette file is an essential prerequisite used by FFMPEG to map colors in the video to colors in the GIF.

    In order to achieve that, first create a toPalette.js module file inside the modules folder.

    exports.toPalette = async() => {
    	
    return new Promise(function(resolve, reject) {
    		
    var exec = require('child_process').exec;
    
    var cmd = process.cwd()+'/ffmpeg/ffmpeg -i ./public/output/animation.mp4 -filter_complex "[0:v] palettegen" -preset veryfast ./public/output/palette.png';
        exec(cmd, function(err, stdout, stderr) {
          if (err)
            reject(err);
          else
            resolve('success');
        });
      }); 
    };

    The FFMPEG command in the code takes the MP4 file as input and applies the “palettegen” filter to generate the palette file. The filter analyzes the colors in the MP4 file and creates a palette file that maps these colors to a smaller set of colors that can be used in the GIF. The resulting palette file is saved as a PNG file in the /public/output folder.

    It’s worth noting that FFMPEG needs to create a palette file before creating a GIF file because GIFs are limited to 256 colors. FFMPEG generates a palette file from the MP4 output that contains the 256 most used colors in the animation. This palette file is then used to map the colors in the MP4 output to the 256 colors available in the GIF format.

    Our final step is to create a module file called toGif.js, also placed inside the modules folder:

    exports.toGif = async() => {
    	
    return new Promise(function(resolve, reject) {
    		
    var exec = require('child_process').exec;
    
    var cmd = process.cwd()+'/ffmpeg/ffmpeg -i ./public/output/animation.mp4 -i ./public/output/palette.png -filter_complex "[0:v][1:v] paletteuse" -preset veryfast -loop 0 ./public/output/animation.gif';
        exec(cmd, function(err, stdout, stderr) {
          if (err)
            reject(err);
          else
            resolve('success');
        });
      }); 
    };

    This file exports a function containing the child_process module to execute an FFMPEG command. This command uses the palette file created in the previous step to generate a GIF file from the MP4 output.

    Lastly, make sure that both toPalette and toGif modules are executed only when the MP4 is successfully generated:

    var express = require('express');
    var router = express.Router();
    
    const { toHTML } = require('../modules/toHTML.js');
    router.post('/convert-to-video', async function(req, res) {
      
    let data = req.body;
      
    await toHTML(data);
    await toMP4(data);
    await toPalette();
    await toGif();
      
    res.send('success');
    });

    Application Flow in Nutshell:

    To provide better understanding, the following diagram presents the data flow and processes involved in exporting anime.js animations to MP4 and GIF formats on the server-side, utilizing Node.js modules and FFMPEG.

    +-------------------------------------------------+
    |                                                 |
    |          +------------------------+             |
    |          |  Client-side animation |             |
    |          |  and DOM elements      |             |
    |          +------------------------+             |
    |                         |                       |
    |                         |                       |
    |                         |                       |
    |          +------------------------+             |
    |          |  index.js              |             |
    |          |  (initiate animation)  |             |
    |          +------------------------+             |
    |                         |                       |
    |                         |                       |
    |                         |                       |
    |          +------------------------+             |
    |          |  Client-side API       |             |
    |          |  (communicates with    |             |
    |          |   server-side API)     |             |
    |          +------------------------+             |
    |                         |                       |
    |                         |                       |
    |                         |                       |
    |          +------------------------+             |
    |          | Server-side toHTML API |             |
    |          | (receives animation    |             |
    |          | and saves on server    |             |
    |          | as animation.html)     |             |
    |          +------------------------+             |
    |                         |                       |
    |                         |                       |
    |                         |                       |
    |          +------------------------+             | 
    |          | Server-side toMP4 API  |             | 
    |          | (loads animation.html  |             | 
    |          | and processes to MP4)  |             | 
    |          +------------------------+             | 
    |                         |                       | 
    |                         |                       | 
    |                         |                       |
    |          +------------------------+             |
    |          |   timecut              |             |
    |          |  (converts animation   |             |
    |          |   to MP4 format)       |             |
    |          +------------------------+             |
    |                         |                       |
    |                         |                       |
    |                         |                       |
    |          +------------------------+             |
    |          | Server-side toGIF API  |             |
    |          | utilizing FFMPEG       |             |
    |          | (converts MP4 to GIF)  |             |
    |          +------------------------+             |
    |                         |                       |
    |                         |                       |
    |                         |                       |
    |          +------------------------+             |
    |          | Server sends success   |             |
    |          | message back to client |             |
    |          +------------------------+             |
    |                                                 |
    +-------------------------------------------------+
    

    Conclusion

    This article offers a complete walkthrough on how to export client-side anime.js animations to MP4 and GIF formats using a combination of Node.js modules and FFMPEG on the server-side. By following the steps discussed, you can develop dynamic and cutting-edge online animation tools with the capabilities to export to both video and GIF formats.

    Download

    • Download the project from GitHub

    Resources

    • https://www.npmjs.com/package/timecut
    • https://ffmpeg.org/ffmpeg.html
    • SVG Icon used in the demo is courtesy Rochak Shukla on Freepik
    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
    Javed

      Related Posts

      Mastering REST APIs: Essential Techniques for Programmers

      December 18, 2024

      Streamlining Resource Allocation for Enhanced Project Success

      December 18, 2024

      Crafting Interactive User Interfaces Using JavaScript Techniques

      December 17, 2024
      Leave A Reply Cancel Reply

      You must be logged in to post a comment.

      Stay In Touch
      • Facebook
      • Twitter
      • Pinterest
      • Instagram
      • YouTube
      • Vimeo
      Don't Miss
      Programming December 1, 2024

      Essential Role of Debugging in Effective Programming Practices

      Debugging is a critical aspect of effective programming, serving as a systematic approach to identifying and resolving errors. By employing debugging techniques, developers enhance code quality, improve functionality, and ensure robust software performance.

      This Is How I Created a Simple App Using React Routing

      February 19, 2020

      Understanding Flutter Bloc Pattern

      September 18, 2019

      React Lesson 5: React Devtools and Reusable Open-Source Components

      December 20, 2019

      Categories

      • AI & Automation
      • Angular
      • ASP.NET
      • AWS
      • B2B Leads
      • Beginners
      • Blogs
      • Business Growth
      • Case Studies
      • Comics
      • Consultation
      • Content & Leadership
      • CSS
      • Development
      • Django
      • E-commerce & Retail
      • Entrepreneurs
      • Entrepreneurship
      • Events
      • Express.js
      • Facebook Ads
      • Finance & Fintech
      • Flask
      • Flutter
      • Franchising
      • Funnel Strategy
      • Git
      • GraphQL
      • Home Services Marketing
      • Influencer & Community
      • Interview
      • Java
      • Java Spring
      • JavaScript
      • Job
      • Laravel
      • Lead Generation
      • Legal & Compliance
      • LinkedIn
      • Machine Learning
      • Marketing Trends
      • Medical Marketing
      • MSP Lead Generation
      • MSP Marketing
      • NestJS
      • Next.js
      • Node.js
      • Node.js Lessons
      • Paid Advertising
      • PHP
      • Podcasts
      • POS Tutorial
      • Programming
      • Programming
      • Python
      • React
      • React Lessons
      • React Native
      • React Native Lessons
      • Recruitment
      • Remote Job
      • SaaS & Tech
      • SEO & Analytics
      • Soshace
      • Startups
      • Swarm Intelligence
      • Tips
      • Trends
      • Vue
      • Wiki
      • WordPress
      Top Posts

      Уроки React. Урок 12.

      Programming November 1, 2016

      TOP SQL & Database Courses [Plus a List of Free SQL Courses]

      Beginners December 14, 2019

      Adding backend to CodePen snippet using Python/Django | Question-Answering Application

      Python April 28, 2020

      Maximizing LinkedIn: Strategies for Legal and Compliance Marketing

      Legal & Compliance August 27, 2025

      Subscribe to Updates

      Get The Latest News, Updates, And Amazing Offers

      About Us
      About Us

      Soshace Digital delivers comprehensive web design and development solutions tailored to your business objectives. Your website will be meticulously designed and developed by our team of seasoned professionals, who combine creative expertise with technical excellence to transform your vision into a high-impact, user-centric digital experience that elevates your brand and drives measurable results.

      7901 4th St N, Suite 28690
      Saint Petersburg, FL 33702-4305
      Phone: 1(877)SOSHACE

      Facebook X (Twitter) Instagram Pinterest YouTube LinkedIn
      Our Picks
      Entrepreneurship

      Enhancing Business Success: The Impact of Emotional Intelligence

      Programming

      Mastering REST APIs: Essential Techniques for Programmers

      Beginners

      Node.js Lesson 2: Modules and Exports

      Most Popular

      TOP 5 Books about Silicon Valley that Blew Up the Internet

      JavaScript

      Fundamentals of Programming: A Beginner’s Guide

      Programming

      Node.js Lesson 4: NPM Package Structure

      Node.js
      © 2025 Soshace Digital.
      • Home
      • About
      • Services
      • Contact Us
      • Privacy Policy
      • Terms & Conditions

      Type above and press Enter to search. Press Esc to cancel.