Autoplay a Video on a Next.js Landing page

Emma Alder

In modern web pages and platforms, human attention is earned, and even a slight reduction in the quality of user experience could lead to a significant drop in conversion. This can be said for media content, including videos and images.

How do you improve the user experience of video content on your application?

This post outlines how to autoplay video content when a user scrolls to the video on a Next.js page. We'll use the Cloudinary video player to render the video.

Cloudinary provides a robust media experience for any media type, covering image and video uploads, storage, and optimizations. With Cloudinary, you can store and render your video assets on a Next.js landing page.

Sandbox

You can find a complete version of the application on Codesandbox.

Prerequisites and Installation

To get the most out of this post, basic knowledge of JavaScript and React is required. An understanding of Next.js is also a necessity.

To get started, we install the Next.js CLI, and create a new Next application using NPX - a node package runner. You can also use yarn to install packages, and create a new project. Next.js ships with starters, and we'll use the Next.js defaulter starter in our application.

To get a Next.js project started, navigate to your desired directory, and run the command below:

1npx create-next-app

The command above will return an input, asking you for the project name. You can use your desired project name. Once done, it will create a Next.js project using the default starter.

We will use the Cloudinary video player shipped in the cloudinary-react package. The video player is efficient because we can use a public ID that is a unique identifier of the video on Cloudinary. We'll use this ID to fetch our uploaded video asset, and build dynamic delivery. Also, robust video transformations from Cloudinary are available when using the video player.

Proceed to install the following dependencies using the command below:

1npm install Cloudinary-react react-intersection-observer

cloudinary-react is a Software Development Kit (SDK) that allows us to seamlessly utilize Cloudinary’s image and video features in a React app.

react-intersection-observer tells us when an element enters or leaves a particular viewport. This is essential to know when our video player is in view.

Video player creation

First, we create a new directory called Videoplayer in our app’s src/components directory. Next, we create a file called VideoPlayer.jsx that will house the video player component. Then, we import the required dependencies using in the component with:

1// src/components/Videoplayer/VideoPlayer.jsx
2 import React, { useEffect, useref } from "react";
3 import { Video, CloudinaryContext } from "Cloudinary-react";
4 import { useInView } from "react-intersection-observer";

Intersection observer API provides a way to asynchronously observe changes in the intersection of a target element with a parent element, or viewport, in the browser.

react-intersection-observer is a declarative wrapper component for Intersection observer API.

We create a function component for the video player, which takes in a video ref. The component will return a Cloudinary Video component wrapped in a Cloudinary Context component. CloudinaryContext allows you to define shared parameters that apply to all child elements.

Let’s add the snippet below to our VideoPlayer component:

1const VidPlayer = React.memo(({ videoref }) => {
2 return (
3 <CloudinaryContext cloud_name="codedog">
4 <Video
5 publicId="videoplayer-demo"
6 width="100%"
7 controls
8 innerref={videoref}
9 />
10 </CloudinaryContext>
11 );
12 });

In the code above, our component is wrapped in React.memo.

[React.memo()](https://reactjs.org/docs/hooks-reference.html#usememo) is a higher-order component (HOC) that takes a component as a prop, and returns a component, preventing a component from re-rendering if the props have not changed. React.memo() implements memoization on React components, and prevents our Video player from rerendering even if its parent component rerenders.

The Cloudinary context specifies the cloud_name, with which we fetch media assets from Cloudinary. To obtain your cloud_name, you need to create an account on Cloudinary, and get the cloud name value from your Cloudinary dashboard.

We also specified options for our video player, including the publicId of our video on Cloudinary.

Handling video interaction with intersection-observer

In src/components/VideoPlayer.jsx, we create a function component named VideoPlayer. Inside it, we use the useInView hook, imported from react-intersection-observer to track a DOM element for when it gets in view.

1const VideoPlayer = () => {
2 const videoref = useref();
3 const { ref, inView } = useInView({
4 threshold: 0
5 });
6 useEffect(() => {
7 if (inView === true) {
8 videoref.current.play();
9 }
10 });
11 return (
12 <div ref={ref}>
13 <VidPlayer videoref={videoref} />
14 </div>
15 );
16 };
17 export default VideoPlayer;

We assigned the ref value, destructured from the useInView hook, to the DOM element we want to monitor. In this case, it’s the div enclosing the rendered VidPlayer component.

In the VideoPlayer component’s useEffect function, we play the video when in view. The videoRef reference is created using React’s useRef() hook, and is assigned to the ref prop of video player. This ref value will be used to access the video player methods in our VideoPlayer component. The HTML video element’s .play() method is then used to play the video when it is in view.

refs are references to objects. They can include DOM nodes, or values. useRef returns a mutable object with a .current property set to the initial value we passed to the hook. The code below should be added to our VideoPlayer.jsx file.

Rendering the video player

In the site’s homepage, located in the src/pages, we create a new file named index.jsx. This is the home page of the website. In this file, we render the VideoPlayer component in the parent Home component along with other page content. The code snippet below should be copied into our newly created index.jsx file in src/pages directory.

1import Head from "next/head";
2 import styles from "../styles/Home.module.css";
3 import VideoPlayer from "../components/VideoPlayer/VideoPlayer";
4
5 const Home = () => {
6 return (
7 <div className={styles.container}>
8 <Head>
9 <title>Video Player with Cloudinary</title>
10 <link rel="icon" href="/favicon.ico" />
11 </Head>
12 <header className={styles.header}>
13 <h1>Video Player</h1>
14 </header>
15 <main className={styles.main}>
16 <section className={styles.intro}>
17 <p>NOW EASILY</p>
18 <h1 className={styles.title}>
19 Render Your Videos with Cloudinary, <br /> And Observer Intersection
20 Library.
21 </h1>
22 </section>

In the code block above, we created a Home component, with the title and icons for our landing page. Next, we add content and render the VideoPlayer component. The code block below will be added to our index.jsx file above.

1<section className={styles.img_wrapper}>
2 <img src="/assets/video.svg" alt="illustration" />
3 </section>
4 </main>
5 <section className={styles.description}>
6 <p>
7 There is no one who loves pain itself, who seeks after it, and wants to have it, simply because it is pain.
8 There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain.
9 </p>
10 </section>
11 <section className={styles.video_player}>
12 <VideoPlayer />
13 </section>
14 </div>
15 );
16 };
17 export default Home;

With this, the homepage should look like this:

Summary

In this post, we created a Next.js landing page, and made a video player using the Cloudinary Video player. We also added autoplay when in view, using react observer intersection. You can improve the application by utilizing other video player events.

You may check out the following useful resources:

Emma Alder

Technical Writer at Hackmamba.io

Technical writer at Hackmamba.io