惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
量子位
博客园 - 叶小钗
Apple Machine Learning Research
Apple Machine Learning Research
U
Unit 42
IT之家
IT之家
F
Fortinet All Blogs
GbyAI
GbyAI
MongoDB | Blog
MongoDB | Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
大猫的无限游戏
大猫的无限游戏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The Register - Security
The Register - Security
NISL@THU
NISL@THU
Webroot Blog
Webroot Blog
A
Arctic Wolf
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
Visual Studio Blog
Recent Announcements
Recent Announcements
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Blog — PlanetScale
Blog — PlanetScale
L
LangChain Blog
P
Palo Alto Networks Blog
Y
Y Combinator Blog
WordPress大学
WordPress大学
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
AWS News Blog
AWS News Blog
有赞技术团队
有赞技术团队
Engineering at Meta
Engineering at Meta
C
Cybersecurity and Infrastructure Security Agency CISA
aimingoo的专栏
aimingoo的专栏
Know Your Adversary
Know Your Adversary
Cyberwarzone
Cyberwarzone
Martin Fowler
Martin Fowler
The Hacker News
The Hacker News
P
Privacy International News Feed
T
Threat Research - Cisco Blogs
G
GRAHAM CLULEY
宝玉的分享
宝玉的分享
博客园 - 聂微东
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The GitHub Blog
The GitHub Blog
S
Securelist
T
The Exploit Database - CXSecurity.com
T
Threatpost
Microsoft Azure Blog
Microsoft Azure Blog
The Cloudflare Blog
F
Full Disclosure

ImageKit.io Blog

Next.js Image Optimization with ImageKit Use Video as a Background in Your Next.js Project How to Fix Autoplay Video in Next.js How Durian Scaled a Visual-First Retail Experience to 350K Monthly Visitors Online How Matsmart accelerated image delivery across countries with ImageKit AI in Digital Asset Management: From Smart Workflows to Agentic Automation How Joseph Joseph unified and secured global video delivery with ImageKit How Modall powers fast, effortless media delivery across 40+ projects with ImageKit Digital Asset Management (DAM) Trends: 2026 Report How to add a poster image to Video.js player (and automate it) HLS streaming with Video.js + React Building the future of storytelling with fast, AI-powered video delivery How PushOwl delivers 100M+ image-rich notifications seamlessly with ImageKit How Homify delivers millions of interior design images seamlessly with ImageKit Better event discovery with lightning‑fast videos & images Adding video player in React Native Video player in Angular applications Crop and resize videos in React Next.js image and video upload React image and video upload React video optimization How we quadrupled our traffic to 625K monthly page views How Apollo 24|7 boosted performance & reduced costs with ImageKit Simplify your media workflows with ImageKit DAM integrations Extending Lighthouse for custom image and video optimization analysis Brand Asset Management: What is it? How does it work? WordPress Digital Asset Management Guide - Manage your WP media assets better Why Shopify retailers need a digital asset management solution DAM vs. SharePoint: Which is best for you? AI-powered Metadata and Tagging in Digital Asset Management How Hopscotch built India's largest online Kids' fashion brand with ImageKit Dropbox Vs. DAM: Which Is The Right Tool For Digital Asset Management Digital Asset Management for Photographers: A Complete Guide Why digital asset management for agencies is essential Helping both Top and Bottom Line: SaffronStays rapid, profitable growth with ImageKit How KreditBee simplified media experiences with ImageKit Google Drive alternatives for businesses (with fast-growing teams) Node.js image upload ImageKit: The Secret Ingredient in Swiggy’s Expansion Journey Streamlining the Design Approval Process: A Comprehensive Guide AV1 Codec - Complete guide for video application devs PHP image and video upload Angular image & video upload AV1 vs VP9: Which codec should you choose? React Video Player VP8 vs VP9 - In the context of online video delivery Exploring WebM vs MP4 7 Free Digital Asset Management Software that are not Open-Source Comparing 9 Top Digital Asset Management Tools in the Market What are Brand Standards and Why do they Matter? Boost Sales and Brand Appeal: Essential Tips for eCommerce Image Management Brand Recall: The Strategy to Create Unforgettable Brands How to upload files in HTML? Branding for Small Businesses (2025 Edition) Everything you need to know about VP9 codec Recent updates from ImageKit and what's next Best Ways to Write RFP For Digital Asset Management (+ with free RFP template) What is Brand Dilution? How to Avoid It? Explained with [Examples] The Importance of Brand Identity: Leveraging Digital Asset Management for Impact From Launch to Scale: How to Launch a Brand Campaign Digital Asset Management Requirements - What do You Need to Evaluate and How? Marketing Collateral Management: A Quick End-to-End Guide Video Content Management System: What Is It And How To Choose One? Dropbox vs. Google Drive vs. Onedrive: The Best Cloud Storage Solution How to Build Brand Trust: Get Started In 2025 Google Drive vs. Box: A Detailed Comparison How Digital Asset Management Solutions Help Protect Brand Equity A DAM Solution Can Safeguard Your Digital Intellectual Property - Here’s How WebP Vs. PNG: Which Image Format Should You Use and Why? How to Resize Images in Bootstrap Easily Progressive jpegs (PJPEG): the key to loading images faster on your website Dropbox vs. Google Drive: The Best Cloud Storage For Digital Assets Dropbox Pros & Cons In 2024: An In-Depth Analysis and Why A DAM Solution Stands Out Google Drive Vs OneDrive: The Better Storage Option For Digital Assets Manage your video assets better with video metadata Understanding DAM's Role in Strengthening Brand Identity Digital asset management strategy: What to know before creating one The Ultimate Guide To Marketing Agency Onboarding 6 Solutions To Simplify Large File Sharing Over The Web A Step-by-Step Breakdown of a Video Production Workflow 13 Digital Asset Management Use Cases You Should Know How to Conduct a Brand Audit and Manage Your Brand Assets Costly Consequences of Inconsistent Branding And How DAM Can Help Dynamic Asset Transformation: What It Is, Why You Need It, and How ImageKit Can Help Everything You Need to Know About HTML Video Autoplay How To Select Your DAM Vendor: A Complete Guide How to Boost User Experience with Smart Digital Asset Management React Image Optimization: A Guide for Web Developers Why Should DAM Be A Part Of Your MarTech Stack? Unleashing the Power of Content Repurposing with ImageKit MKV vs MP4: Which Video File Format Is Better for Your Needs? Digital Asset Management For Ecommerce: A Complete Guide How an Image Tagging Software can Transform Your Image Search How to Manage Your Content Lifecycle Effectively M4V vs MP4: Which Video Format Should You Use and Why? Why Every Business Needs An Image Management System All The Questions To Ask During A Dam Demo Which is the Best Image Format for Your Website? Uploading Multiple Files Using JavaScript: A Comprehensive Guide Headless DAM: Why API-Driven Digital Asset Management is the Way Forward
Adding video player in Next.js
Yashaswi Agrawal · 2024-03-26 · via ImageKit.io Blog

Introduction

This article will explore how to play different video formats like MP4, WebM, and Adaptive Bitrate Streaming(ABS) protocols like HLS and DASH across all the major browsers in Next.js. We will cover the features and limitations of HTML <video> tag and the need for external video players like video.js.

For this tutorial, a stable version of Node 18.17.0 or above is needed.

You can find the complete code on GitHub.

Creating a Next.js project

To create a new project, run the below command in the code terminal; it contains all the required flags to avoid user interactivity.

npx create-next-app@14.1.3 video-player --ts --eslint --app --no-src-dir --use-npm --no-tailwind --import-alias '@/*'

💡

Note that we are using a specific version of Next.js, i.e., 14.1.3, because later, we will integrate the video.js library and some of its plugins, which have reported compatibility issues with the latest version of Next.js at the time of this writing. Sticking to the versions mentioned in this tutorial will help you avoid compatibility issues.

Here's how the boilerplate code appears in the Visual Studio Code editor:

To run the project, use the below command:

npm run dev

After running this command, the web server can be accessed at http://localhost:3000/. Whenever we edit and save any page in the project, it will hot reload itself.

Using HTML video element

HTML5 provides us with a standard video tag that can be directly used in Next.js to play videos. It comes with various attributes like autoPlay, controls, playsInline, etc., which cover most of the use cases and give us appropriate control over video.

Let's begin by playing our first video. We will use this video, which is publicly hosted on ImageKit.

Replace the app/page.module.css  code with the below code:

.container {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  padding: 6rem;
  min-height: 100vh;
}

Replace the app/page.tsx code with the below code:

import styles from "./page.module.css";

export default function Home() {
  return (
    <main >
      <div className={styles.container}>
        <video height="452" width="768" >
          <source src="https://ik.imagekit.io/ikmedia/example_video.mp4" />
          Your browser does not support the video tag...
        </video>
      </div>
    </main>
  );
}

We should have something like this:

Video player without controls
Video player without controls

At this point, the video player didn't render user controls. To provide controls, we can add a controls attribute in the video element that will allow the user to control video playback, including volume, seeking, and pause/resume playback.

import styles from "./page.module.css";

export default function Home() {
  return (
    <main >
      <div className={styles.container}>
        <video height="452" width="768" controls >
          <source src="https://ik.imagekit.io/ikmedia/example_video.mp4" />
          Your browser does not support the video tag...
        </video>
      </div>
    </main>
  );
}
Video player with controls
Video player with controls

The video content downloaded by the browser, as seen in the network tab:

Resizing video

Resizing video can easily be achieved by editing height and width attributes. Let's resize the video to 200 x 200 px, as shown below.

<video height="200" width="200" controls>
  <source src="https://ik.imagekit.io/ikmedia/example_video.mp4" />
  Your browser does not support the video tag...
</video>

There are two issues with the above way of resizing:

  1. Despite reducing the dimensions of the video, the browser will still need to download the original large video. We can verify this in the network tab, as Content-Length in both cases remains the same:

2.  We don't have any control over the cropping mode. By default, it maintains the aspect ratio and leaves extra space blank, as shown below.

Blank spaces on top and bottom
Blank spaces on top and bottom

To overcome these challenges, we need to encode the video on the server side so that the browser downloads the resized video. It will result in faster downloads because of the smaller file size. Also, on the server side, you can control the cropping behavior.

For this tutorial, we will use ImageKit.io video API, which provides URL-based transformation parameters to control resizing, cropping and a lot more.

Let's add tr=w-200,h-200 query parameter in the video URL to resize the video using ImageKit.

<video height="200" width="200" controls>
  <source src="https://ik.imagekit.io/ikmedia/example_video.mp4?tr=w-200,h-200" />
  Your browser does not support the video tag...
</video>

There is a significant file size reduction. This will save valuable bandwidth and ensure that video plays smoothly, even on slow network connections.

Reduce content-length
Reduce content-length

Due to the default cropping mode of ImageKit.io, we also see that the video covers a complete 200 * 200 px  box above.

Multiple source tag

The <video> tag contains one or more <source> tags with different video sources. The browser will choose the first source it supports.

For example, the MOV format is not supported in Chrome, but Safari can play it. So, based on the browser, Chrome vs Safari picks and plays different sources.

<video height="200" width="200" controls >
  <source src="https://ik.imagekit.io/ikmedia/file_example_MOV_640_800kB.mov?tr=orig-true" type="video/quicktime" />
  <source src="https://ik.imagekit.io/ikmedia/sample-5s.webm?tr=f-mp4" type="video/webm" />
  Your browser does not support the video tag...
</video>
Chrome Browser
Chrome Browser
Safari Browser
Safari Browser

Video thumbnail

A video thumbnail is a still image that acts as the preview image for our video. A great video thumbnail can be the difference between getting a few views and a few thousand views. By default, the first frame of the video is shown as a thumbnail, but only after the browser loads the video.

💡

There is preload attribute in the video element that decides whether the video can be preloaded by the browser before playing it or not; if you set its value as preload=none then no thumbnail will be shown by default.

Hence, to ensure the thumbnail of our choice is visible across browsers, irrespective of whether the video is downloaded or not, we should use the poster attribute. It takes the image path as a value.

Let's add the image below to our repository in the public folder.

thumbnail.png
thumbnail.png

Now, we will provide its path as value to the poster attribute as shown below

<video height="200" width="200" controls
  poster="../thumbnail.png">
  <source src="https://ik.imagekit.io/ikmedia/example_video.mp4" />
  Your browser does not support the video tag...
</video>

💡

Notice that the path given is poster="../thumbnail.png" and not poster="../public/thumbnail.png" because assets hosted in the public folder is available on the root directory path.

Now, our video with a custom thumbnail looks like the below:

Video with thumbnail
Video with thumbnail

There are a few challenges, as mentioned below:

  1. If we want to use a particular frame from the video apart from the first frame, such as at a precise timestamp of 7.5 seconds, then we will need third-party tools to extract the requisite frame.
  2. After extracting the thumbnail, we need to store it somewhere like we did above, creating an overhead that leads to extra storage, too.

To solve the above problems, we can use ImageKit. For example, if we want an image at the 7.5-second mark with dimensions of 200x200 pixels from the video mentioned above, we can utilize ImageKit's video thumbnail feature. The URL would appear as follows:

https://ik.imagekit.io/ikmedia/example_video.mp4/ik-thumbnail.jpg?tr=so-7.5,w-200,h-200

The video will have a thumbnail as depicted below:

 <video height="200" width="200"
    poster="https://ik.imagekit.io/ikmedia/example_video.mp4/ik-thumbnail.jpg?tr=so-7.5,w-200,h-200"
    controls>
    <source src="https://ik.imagekit.io/ikmedia/example_video.mp4?tr=w-200,h-200,c-maintain_ratio" />
    Your browser does not support the video tag...
</video>
Video with custom thumbnail
Video with custom thumbnail

Playing inline video

When playing a video on an iOS mobile device, by default, it opens in full-screen mode, as shown in the video attached:

To prevent this, the video element provides the playsInline attribute that determines whether the video plays inline or in full-screen mode.

The code snippet with playsInline attribute looks like the following, and the behavior is demonstrated in the accompanying video:

<video height="200" width="200"
    playsInline
    controls
    poster="https://ik.imagekit.io/ikmedia/example_video.mp4/ik-thumbnail.jpg?tr=so-7.5,w-200,h-200" >
    <source src="https://ik.imagekit.io/ikmedia/example_video.mp4?tr=w-200,h-200,c-maintain_ratio" />
    Your browser does not support the video tag...
</video>

💡

It's important to note that the absence of the playsInline attribute doesn't imply that the video will always play in full-screen mode. The behavior may vary depending on the browser and device. However, to ensure that the video consistently plays inline across browsers and devices, using the playsInline attribute is recommended.

Automatically playing videos

You might want to auto-play the video on a typical marketing website to demonstrate a feature or product.

To do this, the video element provides the autoPlay attribute. To ensure that a video autoplays across most browsers, it's essential to pair the autoPlay attribute with the muted attribute. Additionally, incorporating the playsInline attribute is crucial for ensuring compatibility with iOS devices.

The final code snippet looks like the following:

<video height="200" width="200"
    autoPlay
    muted
    playsInline
    controls
    poster="https://ik.imagekit.io/ikmedia/example_video.mp4/ik-thumbnail.jpg?tr=so-7.5,w-200,h-200" >
    <source src="https://ik.imagekit.io/ikmedia/example_video.mp4?tr=w-200,h-200,c-maintain_ratio" />
    Your browser does not support the video tag...
</video>

Limitation of HTML video element

The video element excels at playing common video formats across major browsers, but what if we want Adaptive bitrate streaming (ABS)?

Unfortunately, the standard HTML video element does not support ABS out of the box. Custom video players like video.js come in handy here. video.js provides us with a unified cross-browser API.

Adaptive Bitrate Streaming

Before proceeding further, let's understand ABS a bit. ABS dynamically adjusts the quality of video content based on the viewer’s network conditions. The video is encoded at different bitrates, resulting in different qualities.

Subsequently, a manifest file, similar to a text file, is prepared and contains information about segments of the video at varying bit rates. During playback, the video player uses this manifest file to determine the optimal bitrate based on the viewer’s network conditions, thereby delivering the best possible viewing experience. This process is known as Adaptive Bitrate Streaming (ABS).

Currently, there are two major protocols for ABS, which lead to two different types of manifest files.

  1. HTTP Live Streaming (HLS) - The manifest file is denoted with m3u8 extension.
  2. Dynamic Adaptive Streaming over HTTP (MPEG-DASH) - The manifest file is denoted with mpd extension.

Creating these manifest files yourself can be tricky. To streamline this, you can utilize a video API platform like ImageKit. ImageKit offers a straightforward URL-based parameter for generating a manifest file in the protocol of your choice.

Why video.js?

As discussed above, we need video libraries to implement Adaptive Bitrate Streaming(ABS). There are several video libraries recommended by Next.js documentation, of which we will choose video.js. Below are the reasons for this choice:

  1. ABS support - The library has been supporting ABS protocols out of the box since version 7.0, making implementation straightforward and hassle-free.
  2. Accessibility Feature - The library offers advanced keyboard navigation and screen reader compatibility, democratizing usability and broadening accessibility for all users. More information is available here.
  3. Cross-Browser Compatibility - The library ensures that users experience consistent behavior for various video formats across different browsers, enhancing user convenience and providing a seamless viewing experience. For example, it can play mov video files in Chrome browser out of the box.
  4. Various plugins - The library supports various 3rd party plugins for easy customization and various support. In the upcoming video.js demo, we will use the httpSourceSelector plugin to offer a manual quality-level selection of videos.

How to use video.js

In this section, we will provide a step-by-step guide to implementing video.js in Next.js.

First, let's copy the code of app/page.tsx  into a new folder video-element at path app/video-element/page.tsx

Now, our existing page will also be available on the new route http://localhost:3000/video-element

Then, install the npm dependencies below with specific versions to avoid incompatibility issues.

npm install video.js@7.18.1 videojs-contrib-quality-levels@2.1.0 videojs-http-source-selector@1.1.6

💡

Using the specific version 7.18.1 of video.js instead of the latest release is essential. This choice ensures compatibility with the plugins we'll utilize later in the tutorial. Maintaining consistency with this version is crucial to preventing compatibility issues.

After this, install the dev dependency by running the following command.

 npm install --save-dev @types/video.js@7.3.57

Creating VideoJS component

Now, create a video player component in the new file VideoPlayer.tsx at app/components/VideoPlayer.tsx.

import { useEffect, useRef } from "react";
import videojs from "video.js";
import "video.js/dist/video-js.css";

//to provide quality control option in ABS Video
import "videojs-contrib-quality-levels";
import "videojs-http-source-selector";

export const VideoJS = (props: { options: any; onReady?: any; }) => {
    const placeholderRef = useRef<any>(null);
    const playerRef = useRef<any>(null)
    const { options, onReady } = props;

    useEffect(() => {
        // Make sure Video.js player is only initialized once
        if (!playerRef.current) {
         // The Video.js player needs to be inside the component element for React 18 Strict Mode. 
            const placeholderEl = placeholderRef.current;
            const videoElement = placeholderEl.appendChild(
                document.createElement("video-js")
            );

            const player: any = videojs(videoElement, options, () => {
                player.log("player is ready");
                onReady && onReady(player);
            });

            playerRef.current = player

            // Binding to the source selector plugin in Video.js
            player.httpSourceSelector();

            // You can update player in the `else` block here, for example:
        } else {
            const player = playerRef.current;
            player.autoplay(options.autoplay);
            player.src(options.sources);
        }

    }, [options, onReady]);

    // Dispose the Video.js player when the functional component unmounts
    useEffect(() => {

        const player = playerRef.current;

        return () => {
            if (player) {
                player.dispose();
                playerRef.current = null;
            }
        };
    }, [playerRef]);

    return <div ref={placeholderRef}></div>;
};

export default VideoJS;

Here, we have used two plugins videojs-http-source-selector and videojs-contrib-quality-levels to provide functionality for choosing different video quality.

ℹ️

Compatibility with React 18 StrictMode

Note that we are utilizing a placeholder element placeholderEl to append our Video.js element.

This approach is necessary because React 18 StrictMode introduces additional behaviors that aim to prepare for a reusable state in dev mode. Specifically, during a component's initial mounting, React simulates mounting, unmounting, and then mounting again.

When React simulates unmount, the video.js dispose removes the video element from the DOM, which invalidates the ref that React held, leading to an error. Hence, by wrapping it in the parent element, we can get rid of this error.

Using VideoJS component with HLS protocol

To configure video.js an options object is passed, the complete list can be found here. The options passed are similar to the props value in the HTML video element. In addition, it also accepts a plugin object, which contains a list of plugins.

The following URL will generate an HLS manifest and four variants at different resolutions i.e., 240p, 360p, 480p, and 720p using ImageKit ABS capabilities.

https://ik.imagekit.io/ikmedia/sample-video.mp4/ik-master.m3u8?tr=sr-240_360_480_720

Now replace the code at app/page.tsx with the code below. Notice that the we are using use client; on the top because we are using client-side hooks like useEffect and useRef.

"use strict";
"use client"; // to ensure client side execution as we are using client-side hooks like useRef
import styles from "./page.module.css";
import { useRef } from "react";
import videojs from "video.js";
import VideoJS from "./components/VideoPlayer";


export default function Home() {
  const playerRef = useRef(null);

  const videoJsOptionsM3u8 = {
    controls: true,
    autoplay: false,
    width: 400,
    sources: [
      {
        src: 'https://ik.imagekit.io/ikmedia/sample-video.mp4/ik-master.m3u8?tr=sr-240_360_480_720',
        type: 'application/x-mpegURL'
      },
    ],
    plugins: {
      httpSourceSelector:
      {
        default: 'auto'
      }
    }
  };
  
  const handlePlayerReady = (player: any) => {
    playerRef.current = player;

    console.log(player.qualityLevels())

    // You can handle player events here, for example:
    player.on('waiting', () => {
      videojs.log('player is waiting');
    });

    player.on('dispose', () => {
      videojs.log('player will dispose');
    });
  };
  return (

    <main >
      <div className={styles.container}>
        <VideoJS options={videoJsOptionsM3u8} onReady={handlePlayerReady} />
      </div>
    </main>
  );
}

Now you should be able to see and select the quality levels from the player. See the live demo hosted on CodeSandbox here:

Playing DASH protocol

Now, to run the DASH protocol video, we just need to replace the source with the correct URL and content type. Let's create a new object for the DASH protocol and pass it as  options in the video component.

....
   const videoJsOptionsMpd = {
    controls: true,
    autoplay: false,
    width: 400,
    sources: [
      {
        src: 'https://ik.imagekit.io/demo/sample-video.mp4/ik-master.mpd?tr=sr-240_360_480_720_1080',
        type: 'application/dash+xml'
      },
    ],
    plugins: {
      httpSourceSelector:
      {
        default: 'auto'
      }
    }
  };
....
  return (

    <main >
      <div className={styles.container}>
        <VideoJS options={videoJsOptionsMpd} onReady={handlePlayerReady} />
      </div>
    </main>
  );
}

Conclusion

The article begins by exploring the fundamentals of the HTML video element and its seamless integration with Next.js. It then delves into the intricacies of various attributes of the video element and offers best practices for their usage.

We also learned how ImageKit video API can simplify various use cases, such as video resizing or creating thumbnails for better engagement. We explore the necessity of a video library like Video.js and how it simplifies the playback of various Adaptive Bitrate Streaming Protocols like HLS and DASH.

You can find the complete code on GitHub and see the live demo of ABS hosted on CodeSandbox.