How to Build a Video Thumbnail Generator Tool Using React and Bannerbear

Improve users' workflow by integrating a video thumbnail generator that adds text to an image uploaded by them using Bannerbear API.
by Josephine Loo ·

Contents

    A great video thumbnail is essential for attracting attention to your video and helping it to stand out from the crowd. It needs to be eye-catching and informative, to entice viewers to click on the video but manually creating one that fulfils these requirements can be time-consuming and requires extra effort from the video creator.

    Wouldn't it be cool if we can generate and add a well-designed video thumbnail automatically by simply uploading a background image for the thumbnail? Well with the correct tool, you can do that on your video hosting site!

    In this tutorial, we’ll learn how to make a video thumbnail generator that adds text to an image uploaded by the user using Bannerbear API and display it on the video automatically.

    Let's turn this image…

    sample base image

    …into this video thumbnail:

    video player with a thumbnail

    What is Bannerbear

    Bannerbear is an automated media generation service that helps you create custom images, videos, and more using API. Depending on the media format that you are creating, you can use different APIs as documented in the Bannerbear API Reference to integrate different functions into your app or create an automated workflow easily.

    The images and videos are generated automatically based on a design template which you can add static and dynamic images, texts, shapes, etc. By passing different data to the API, the values of the dynamic objects can be changed to generate unique images and videos.

    All API requests on Bannerbear are scoped to a project and you can create multiple templates in the same one. The templates can be updated and duplicated from your Bannerbear account dashboard or via API after they have been created.

    Setting up the Project

    Create a Bannerbear Design Template

    You can refer to this tutorial to create a new Bannerbear project and add a template to the project. The current tutorial can be continued from the linked tutorial or worked separately. If you decide to follow the current tutorial independently, enabling Web Sessions can be skipped.

    After creating a template, the API key and template ID can be found in the Settings.

    project and template settings

    Create a React Project

    Follow the instructions from the React Guide to create a new React project. As we will be creating some React components, you can install Generate React CLI to create the components faster.

    Create an AWS S3 Bucket (Optional)

    The image uploaded by users will be stored to an AWS S3 Bucket using the AWS SDK. That said, you can use other methods to host the images too. If you want to use AWS S3, this tutorial provides clear instructions on how to set up and configure your AWS S3 to use the AWS SDK in React.

    Writing the Code

    We will be creating an upload page for users to upload their videos and image for the thumbnail. The page will consist of a few components that each have their own purposes:

    • ImageUploader - to upload the background image for generating a video thumbnail.
    • VideoForm - to fill in the title and description of the video.
    • TemplateForm - to map the fields from the VideoForm to dynamic objects in the template.

    screenshot of the upload page

    Note : As we will be focusing on how to generate a thumbnail automatically from the uploaded image and the mapped values, the code for video uploading will be omitted in this tutorial.

    Step 1. Create a New Page

    Create a new page named UploadPage and declare the constant and state variables below:

    UploadPage.js

    import React, { useState } from 'react';
    import './UploadPage.css';
    
    const TEMPLATE_ID = '7wpnPQZzwrdw5dOgxo'; // Bannerbear template ID (replace with your own ID)
    const videoFormInputArray = ['Title', 'Description']; // fields for the Video Form
    
    const UploadPage = () => {
    
      const [imageObjName, setImageObjName] = useState(null); // name of the image object in the template
    
      const [templatePreview, setTemplatePreview] = useState(null); // URL of the template preview image
      const [thumbnailUrl, setThumbnailUrl] = useState(null); // URL of the thumbnail generated
      const [imageUrl, setImageUrl] = useState(null); // URL of the image uploaded by user
    
      const [videoFormInput, setVideoFormInput] = useState({}); // an object to hold the Video Form fields
      const [modifiableFields, setModifiableFields] = useState(null); // modifiable fields in the template
    
      const [loading, setLoading] = useState(false);
    
      return (
        <div className='UploadPage'>
        </div>
      );
    };
    
    export default UploadPage;
    

    In the next steps, we will be creating some functions and components that can be used in the HTML code of this page.

    Step 2. Retrieve the Design Template

    The first function that we will be creating is the getTemplate() function. The function will make a GET request to /templates with the specified Bannerbear design template ID.

    From the template result returned, we will store its preview image URL, image object/layer name, and modifiable fields to the declared state variables templatePreview, imageObjName, and modifiableFields.

    Then, insert the strings in videoFormInputArray into the videoFormInput object.

    UploadPage.js

    // Get modifiable fields from the template
      React.useEffect(() => {
        async function getTemplate() {
          const res = await fetch(`https://api.bannerbear.com/v2/templates/${TEMPLATE_ID}`, {
            method: 'GET',
            headers: {
              Authorization: `Bearer ${process.env.REACT_APP_BB_API_KEY}`,
            },
          });
    
          const data = await res.json();
          var availableModifications = data.available_modifications
            .filter((modification) => modification.hasOwnProperty('text')) // only allow users to change texts
            .sort((a, b) => (a.name > b.name ? 1 : b.name > a.name ? -1 : 0));
    
          setTemplatePreview(data.preview_url);
          setImageObjName(data.available_modifications.find((x) => x.hasOwnProperty('image_url')).name); // get the name of the image object (image_container)
          setModifiableFields(availableModifications); // for field mapping in Template Value Form
    
          setVideoFormInput(videoFormInputArray.reduce((obj, x) => ({ ...obj, [x]: '' }), {})); // insert the values in the array into an object
        }
        getTemplate();
      }, []);
    

    data.available_modifications will contain all modifiable fields of the template. As users will be uploading the image using the ImageUploader component, we can filter the array to exclude the image object. Only text objects will be added to availableModifications to be shown in the TemplateForm.

    // data.available_modifications
    [
        {
            "name": "image_container", // exclude this from *availableModifications*
            "image_url": null
        },
        {
            "name": "text_1",
            "text": null,
            "color": null,
            "background": null
        }
    ]
    

    The template preview returned:

    selected template's preview

    Step 3. Fill in the Video Details

    Create a VideoForm component that allows users to enter the title and description of the video. The component will receive videoInputArray from the parent, UploadPage via props, and the fields in the array will be used to populate the form.

    VideoForm.js

    import React from 'react';
    import './VideoForm.css';
    
    //props.videoFormInputArray = ['Title', 'Description']; 
    
    const VideoForm = (props) => (
      <div className='VideoForm'>
        <form>
          {props.videoFormInputArray.map((input, i) => (
            <div key={input}>
              <label>
                {input}: <input type='text' name={input} onChange={props.handleInputChange} />
              </label>
            </div>
          ))}
        </form>
      </div>
    );
    
    export default VideoForm;
    

    Add a function named handleInputChange to the parent. When the input element is changed, it will be called to update the value in the videoFormInput object.

    UploadPage.js

    const handleInputChange = (e) => {
        const name = e.target.name;
        const value = e.target.value;
        setVideoFormInput((values) => ({ ...values, [name]: value }));
    };
    

    Example:

    video detail form

    Step 4. Upload an Image for the Thumbnail

    Create a new component named ImageUploader for users to upload an image.

    import React, { useState } from 'react';
    import './ImageUploader.css';
    import AWS from 'aws-sdk';
    
    const BUCKET_NAME = 'your_bucket_name';
    const s3 = new AWS.S3({
      accessKeyId: 'your_access_key_id',
      secretAccessKey: 'your_secret_access_key',
    });
    
    const ImageUploader = (props) => {
      const [selectedFile, setSelectedFile] = useState(null);
      const [imageUrl, setImageUrl] = useState(null);
      const [isUploading, setIsUploading] = useState(false);
    
      const handleFileInput = (e) => {
        setSelectedFile(e.target.files[0]);
      };
    
      const handleUpload = async (file) => {
        setIsUploading(true);
    
        const res = await saveImageToBucket('image', file);
        props.handleImageUrl(res.Location);
    
        setImageUrl(res.Location);
        setIsUploading(false);
      };
    
      const saveImageToBucket = async (fileName, image) => {
        const params = {
          Bucket: BUCKET_NAME,
          Key: `${fileName}`,
          Body: image,
        };
    
        return await s3.upload(params).promise();
      };
    
      return (
        <div className='image-uploader'>
          <input type='file' onChange={handleFileInput} />
          <button onClick={() => handleUpload(selectedFile)}>Upload</button>
          {isUploading && <div>Uploading...</div>}
          {imageUrl && (
            <div>
              <img src={imageUrl} alt='' />
            </div>
          )}
        </div>
      );
    };
    
    export default ImageUploader;
    

    Add handleImageUrl to the parent UploadPage. When the “Upload” button is clicked, the image will be uploaded to AWS S3 and the URL will be returned in the response. Then, props.handleImageUrl will be called to pass the image URL back to the parent.

    UploadPage.js

    const handleImageUrl = (imageUrl) => {
        setImageUrl(imageUrl);
     };
    

    Example:

    image uploader

    Step 5. Map the Video Fields to the Bannerbear Template Fields

    Create a new component named TemplateForm. The modifiable fields in the template will be shown in this form and users can select the fields from the VideoForm to map them to the template fields.

    TemplateForm.js

    import React, { useState } from 'react';
    import './TemplateForm.css';
    
    const TemplateForm = (props) => {
      const [inputs, setInputs] = useState({});
    
      const handleSelectChange = (e) => {
        const name = e.target.name;
        const value = e.target.value;
        setInputs((values) => ({ ...values, [name]: value }));
      };
    
      const handleSubmit = (e) => {
        e.preventDefault();
        const modifications = [];
    
        if (Object.keys(inputs).length === 0) {
          
          props.modifiableFields.forEach((field) => { // use default values from video input
            inputs[field.name] = Object.values(props.videoFormInput)[0];
          });
        }
    
        Object.keys(inputs).forEach((field) => {
          modifications.push({
            name: field,
            text: inputs[field],
          });
        });
        props.handleFields(modifications);
      };
    
      return (
        <div className='template-form'>
          <form onSubmit={handleSubmit}>
            <h3>Template Values</h3>
            {props.modifiableFields.map((field) => {
              return (
                <div key={field.name}>
                  <label>
                    {field.name}:{' '}
                    <select name={field.name} onChange={handleSelectChange}>
                      {Object.keys(props.videoFormInput).map((input) => (
                        <option value={props.videoFormInput[input]} key={input}>
                          {input}
                        </option>
                      ))}
                    </select>
                  </label>
                </div>
              );
            })}
            <input className='save-btn' type='submit' value='Save' />
          </form>
        </div>
      );
    };
    
    export default TemplateForm;
    

    Example:

    template field mapping

    Step 6. Generate and Add the Thumbnail to the Video

    Add the code below to the parent UploadPage. When the “Save” button is clicked, handleFields will be called and a POST request will be sent to Bannerbear’s /images endpoint to generate a thumbnail using the image uploaded by the user and the mapped values.

    UploadPage.js

    const handleFields = async (modifications) => {
        modifications = [...modifications, { name: imageObjName, image_url: imageUrl }]; // add the image object to the array of text objects
        const thumbnail = await generateThumbnail(modifications);
    
        setLoading(false);
        setThumbnailUrl(thumbnail);
      };
    
    const generateThumbnail = async (modifications) => {
        setLoading(true);
        var data = {
          template: TEMPLATE_ID,
          modifications: modifications,
        };
        const res = await fetch('https://sync.api.bannerbear.com/v2/images', {
          method: 'POST',
          body: JSON.stringify(data),
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${process.env.REACT_APP_BB_API_KEY}`,
          },
        });
        const imageData = await res.json();
    
        return imageData.image_url_jpg;
      };
    

    The URL of the thumbnail will be returned in the response and displayed on the video automatically.

    video preview showing the thumbnail generated using Bannerbear

    Add the React components to the HTML of UploadPage and it's done, you have added a video thumbnail generator to your site!

    The full code can be found in this GitHub repo.

    Utilizing API to Improve Workflows

    There are many ways you can use API to offer more functionalities to your users and improve their experience. Instead of uploading a background image for the thumbnail manually, you can try extracting the most representative frame from the video as the thumbnail automatically using FFmpeg.

    If you would like to try something more exciting, why not try using AI to generate the images? Here are 8 artificial intelligence image and video generators built using Stable Diffusion to try out.

    Bannerbear offers other APIs to fulfil the requirements of different use cases, if you're planning to integrate more functionalities to your site using API, check out the Bannerbear API Reference and other tutorials.

    About the authorJosephine Loo
    Josephine is an automation enthusiast. She loves automating stuff and helping people to increase productivity with automation.

    How to Automatically Create Multi-Time Zone Event Posters with Node.js and Bannerbear

    Hosting online events, workshops, or webinars for a global audience? Use Bannerbear in Node.js to automatically generate event posters with the correct time zones for different regions!

    Template Set: Batch-Generate Images in Different Dimensions Using Bannerbear (Node.js)

    Ever found yourself manually resizing images for different platforms? Let’s automate that! With Bannerbear, you can easily generate images in multiple dimensions in one go. This step-by-step tutorial shows you how to use Bannerbear’s template set to create perfectly sized images for any platform.

    Bannerbear Beginner Guide: How to Start Generating Images Dynamically in JavaScript with Bannerbear

    If you want to integrate dynamic image generation into your JavaScript project, this article is for you! Learn how to do it effortlessly with Bannerbear—we’ll walk you through the entire process, from setup and implementation to achieving the final result.

    Automate & Scale
    Your Marketing

    Bannerbear helps you auto-generate social media visuals, banners and more with our API and nocode integrations

    How to Build a Video Thumbnail Generator Tool Using React and Bannerbear
    How to Build a Video Thumbnail Generator Tool Using React and Bannerbear