Playing videos in sequence
If you would like to play multiple videos in sequence, you can:
Define a component that renders a<Series> of <OffthreadVideo> components.
calculateMetadata() function that fetches the duration of each video.
<Composition> that specifies a list of videos.
Basic example
Start off by creating a component that renders a list of videos using the <Series> and <OffthreadVideo> component:
import React from 'react';
import {OffthreadVideo , Series } from 'remotion';
type VideoToEmbed = {
src : string;
durationInFrames : number | null;
};
type Props = {
videos : VideoToEmbed [];
};
export const VideosInSequence : React .FC <Props > = ({videos }) => {
return (
<Series >
{videos .map ((vid ) => {
if (vid .durationInFrames === null) {
throw new Error ('Could not get video duration');
}
return (
<Series .Sequence key ={vid .src } durationInFrames ={vid .durationInFrames }>
<OffthreadVideo src ={vid .src } />
</Series .Sequence >
);
})}
</Series >
);
};In the same file, create a function that calculates the metadata for the composition:
CallsparseMedia() to get the duration of each video.
Create a calculateMetadata() function that fetches the duration of each video.
Sums up all durations to get the total duration of the composition.
export const calculateMetadata : CalculateMetadataFunction <Props > = async ({props }) => {
const fps = 30;
const videos = await Promise .all ([
...props .videos .map (async (video ): Promise <VideoToEmbed > => {
const {slowDurationInSeconds } = await parseMedia ({
src : video .src ,
fields : {
slowDurationInSeconds : true,
},
});
return {
durationInFrames : Math .floor (slowDurationInSeconds * fps ),
src : video .src ,
};
}),
]);
const totalDurationInFrames = videos .reduce ((acc , video ) => acc + (video .durationInFrames ?? 0), 0);
return {
props : {
...props ,
videos ,
},
fps ,
durationInFrames : totalDurationInFrames ,
};
};In your root file, create a <Composition> that uses the VideosInSequence component and the exported calculateMetadata function:
import React from 'react';
import {Composition , staticFile } from 'remotion';
import {VideosInSequence , calculateMetadata } from './VideosInSequence';
export const Root : React .FC = () => {
return (
<Composition
id ="VideosInSequence"
component ={VideosInSequence }
width ={1920}
height ={1080}
defaultProps ={{
videos : [
{
durationInFrames : null,
src : 'https://remotion.media/BigBuckBunny.mp4',
},
{
durationInFrames : null,
src : staticFile ('localvideo.mp4'),
},
],
}}
calculateMetadata ={calculateMetadata }
/>
);
};Adding premounting
If you only care about the video looking smooth when rendered, you may skip this step.
If you also want smooth preview playback in the Player, consider this:
A video will only load when it is about to be played.
To create a smoother preview playback, we should do two things to all videos:
premountFor prop to <Series.Sequence>. This will
invisibly mount the video tag before it is played, giving it some time to load.
Add the pauseWhenBuffering prop. This will transition the Player into a buffering state, should the video still need to load.
export const VideosInSequence : React .FC <Props > = ({videos }) => {
const {fps } = useVideoConfig ();
return (
<Series >
{videos .map ((vid ) => {
if (vid .durationInFrames === null) {
throw new Error ('Could not get video duration');
}
return (
<Series .Sequence key ={vid .src } premountFor ={4 * fps } durationInFrames ={vid .durationInFrames }>
<OffthreadVideo pauseWhenBuffering src ={vid .src } />
</Series .Sequence >
);
})}
</Series >
);
};Browser autoplay policies
Mobile browsers are more aggressive in blocking autoplaying videos that enter after the start of the composition.
If you want to ensure a smooth playback experience for all videos, also read the notes about browser autoplay behavior and customize the behavior if needed.