Introduction
Videos enable us to establish authority and a more personal feel to your message. It enables us to connect with the emotional levels of our audience. React is a great JavaScript library for describing User Interfaces that change over time. To create video content programmatically with React.js
We are going to use an amazing tool called Remotion.
Let’s explore how we can achieve this.
Github
Check out this GitHub Repository for the complete source code.
Codesandbox
The final project can be viewed on Codesandbox.
You can find the complete source code on my Github repository.
Pre-requisites
Below are some requirements you are to meet to follow along with this article:
- Basic knowledge of JavaScript
- Basic knowledge of React.js
Setting Up the Sample Project
In your preferred directory, create a new remotion project using yarn create video
You might want to choose the recommended template but for the purposes of this choose a blank template. Run yarn start
This will start the local dev server running. You will see a window like this.
On the left we have a sidebar showing all the compositions for our project which allows you to isolate and inspect each scene in the video. Each composition is a renderable component. Composition is made up of sequences which tell the video which frames to display the content in. The entry point of a remotion project is the
index.tsx
here we call the function registerRoot(RemotionVideo);
which is in the Video.tsx
Introduction
Open the Video.tsx
file. This file contains the RemotionVideo
component. You can think of this component as your entire video.
1export const RemotionVideo: React.FC = () => {2 return (3 <>4 <Composition5 id="Empty"6 component={MyComposition}7 durationInFrames={450}8 fps={30}9 width={1280}10 height={720}11 />12 </>13 );14};
A video is basically made up of one or more compositions. within the composition, we define video properties as the durationInFrames
which is the number of frames which the video will take, fps
which is the number of frames per second, width
and height
of the video in pixels.
When we talk of frames you can think of it as a still image at a given point in the video.
The id
identifies the composition in the video player and references the component that contains the UI that you want to show. The width and height properties are used to change the resolution of the video e.g., to change the resolution to a portrait
1width={1080}2 height={1920}
The actual length of the video in seconds is based on the fps. durationInFrames / fps = length(s)
This implies that for this demo our video is 15 seconds long 450 / 30 = 15
.
Customizing the Video
We are going to create new Main
component just below the RemotionVideo
component.
1const Main = () => {2 return <h1>Welcome to Cloudinary!</h1>3}
To view this on your browser you will have to change the value of the id from id="Empty"
to id=" Main"
also the component value to component={Main}
When you change the id value you will also have to change the package.json
file
1"build": "remotion render src/index.tsx Empty out/video.mp4"
to have the value of the id
1"build": "remotion render src/index.tsx Main out/video.mp4"
Once you open the video player you will see the video with the text Welcome to Cloudinary
.
To modify the css styling of your video programmatically use inline CSS.
1const Main = () => {2 return (3 <div style={{backgroundColor: 'white', flexGrow: 1}}>4 <h15 style={{6 position: 'absolute',7 top: '50%',8 width: '100%',9 textAlign: 'center',10 fontSize: '5rem',11 }}12 >Welcome to Cloudinary!</h1>13 </div>14 );15};
We can have three components for this particular video the Title
, SubTitle
and the Image
then call them inside the Main
component.
1const Title = () => {2 return(3 <h14 style={{5 position: 'absolute',6 top: '50%',7 width: '100%',8 textAlign: 'center',9 fontSize: '5rem',10 }}11 >Welcome to Cloudinary!</h1>12 );13}14const SubTitle = () => {15 return(16 <h317 style={{18 position: 'absolute',19 top: '60%',20 width: '100%',21 textAlign: 'center',22 fontSize: '3rem',23 }}24 >Transform images and videos to load faster with no visual degradation, automatically generate image and video variants, and deliver high quality responsive experiences to increase conversions.</h3>25 );26}
To add images and render them we have to use Img
tag which shoud be imported from Remotion.
1import {Composition, Img} from 'remotion';2import cloudinary from './cloudinary.png';
We can then create the Image
Component
1const Image = () => {2 return(3 <Img4 src={cloudinary} alt='cloudinary'5 style={{6 display: 'block',7 marginLeft: 'auto',8 marginRight: 'auto',9 width: '30%',10 height: '50%',11 }}12 />13 );14}15const Main = () => {16 return (17 <div style={{backgroundColor: 'white', flexGrow: 1}}>18 <Title />19 <Image />20 <SubTitle />21 </div>22 );23};
For now, everything we need for this video is set, but we need to do some animation to make create our video cool and interesting.
Animation
To make up our entire video clip we are going to use Sequences
, these are small individual sections in finite time that make up our entire video. We then specify the time we from which we want a component to show using from={0}
This means it will start to show at the start(0 seconds). You can also specify the time you want the component to disappear using the durationInFrames={60}
attribute.
1<div style={{backgroundColor: 'white', flexGrow: 1}}>2 <Sequence from={0}>3 <Image />4 </Sequence>5 <Sequence from={60}>6 <Title />7 </Sequence>8 <Sequence from={120}>9 <SubTitle />10 </Sequence>11</div>
Adding Audio for our Video
We can simply add videos using the <Audio />
tag in Remotion. Let's add a Voice
component to render the voice.
1import {Composition, Img, Audio} from 'remotion';2import voice from './voice.mp3';3// rest of the code4const AudVoice = () => {5 return (6 <Audio src={voice} startFrom={0} endAt={30*15}/>7 );8};9// other code
Remotion provides a variety of different hooks which enable us to provide data about the video.
useVideoConfig() hook enables us grab data about the
fps
,duration in frames
,width
, andheight
. We can use this to calculate values for animating our frames.useCurrentFrame() hook gives us the current frame and the timeline. These frames will be re-rendered for each time in the video.
For now your video player is playing well but we now need to use the data about the video in place of the natural numbers 0, 60 and 90. Import useVideo
from remotion.
1const Main = () => {2 const {fps, durationInFrames} = useVideoConfig();3 return (4 <div style={{backgroundColor: 'white', flexGrow: 1}}>5 <Sequence from={fps*0.3} durationInFrames={durationInFrames}>6 <Image />7 </Sequence>8 <Sequence from={fps} durationInFrames={durationInFrames}>9 <AudVoice />10 </Sequence>11 <Sequence from={fps} durationInFrames={durationInFrames}>12 <Title />13 </Sequence>14 <Sequence from={fps*2} durationInFrames={durationInFrames}>15 <Subtitle />16 </Sequence>17 </div>18 );19}
Fade-In effect on the SubTitle
Let's make our animation more captivating with a fade in effect. Here we'll use the useCurrentFrame()
hook as shown.
1const SubTitle = () => {2 const frame = useCurrentFrame();3 const opacity = frame > 30 ? 1 : frame / 30;4 return(5 <h36 style={{7 position: 'absolute',8 top: '60%',9 width: '100%',10 textAlign: 'center',11 fontSize: '3rem',12 opacity13 }}14 >Transform images and videos to load faster with no visual degradation, automatically generate image and video variants, and deliver high quality responsive experiences to increase conversions.</h3>15 );16}
useCurrentFrame brings back the current frame which is SubTitle
in the context of the sequence.
1const frame = useCurrentFrame();
We want the opacity to be zero at the start then as time goes it becomes one. If the frame is greater than 30 then return the opacity as 1. Otherwise, have the opacity as frame/30
1const opacity = frame > 30 ? 1 : frame / 30;
Bounce effect on the Image
1const Image = () => {2 const frame = useCurrentFrame();3 const {fps} = useVideoConfig();4 const translate = spring({frame, fps, to: 100})5 return(6 <Img7 src={cloudinary} alt='cloudinary'8 style={{9 display: 'block',10 marginLeft: 'auto',11 marginRight: 'auto',12 width: '30%',13 height: '50%',14 transform: `translateY(${translate}px)`15 }}16 />17 );18}
The spring
function makes our component bounce from a point to a point. We'll get the fps
from the hook as shown. The function takes the frame
and fps
so that it knows how fast to go, from
and to
tell you how much range you want the outputs to be, and from
has a default value of zero.
Building our Project
To build our project run yarn build
or npm run build
on your terminal. This has a dependency on ffmpeg
, the terminal will give you instructions on how to configure it on your machine.
Once done you will find the video inside the out
folder of your project.
Click this link to see the end video.
Conclusion
Great! In this article, we managed to create a 15-second video without using any video editing tools just React. It's amazing how we can create videos using react, right?