Skip to main content

Playing videos in sequence

To play multiple videos one after another:

Render each <Video> in a <Series.Sequence>.
2
Use Mediabunny to determine the duration of each video.
3
Return the durations and their sum from calculateMetadata().

Create the video series

Render each <Video> in a <Series.Sequence> and set its durationInFrames:

VideosInSequence.tsx
import {Video} from '@remotion/media'; import React from 'react'; import {Series, useVideoConfig} from 'remotion'; export type VideoToEmbed = { src: string; durationInFrames: number | null; }; export type VideosInSequenceProps = { videos: VideoToEmbed[]; }; export const VideosInSequence: React.FC<VideosInSequenceProps> = ({videos}) => { const {fps} = useVideoConfig(); return ( <Series> {videos.map((video) => { if (video.durationInFrames === null) { throw new Error('Could not get video duration'); } return ( <Series.Sequence key={video.src} durationInFrames={video.durationInFrames} premountFor={fps} > <Video src={video.src} /> </Series.Sequence> ); })} </Series> ); };

premountFor mounts each video one second before it enters the timeline, giving it time to load in the Player.

Calculate the durations

Create a calculateMetadata() function that gets the duration of each video using Mediabunny's computeDuration(), converts the durations to frames, and returns their sum as the composition duration:

calculate-metadata.ts
import {ALL_FORMATS, Input, UrlSource} from 'mediabunny'; import type {CalculateMetadataFunction} from 'remotion'; import type {VideosInSequenceProps} from './VideosInSequence'; const getVideoDuration = async (src: string) => { const input = new Input({ formats: ALL_FORMATS, source: new UrlSource(src, { getRetryDelay: () => null, }), }); return input.computeDuration(); }; export const calculateMetadata: CalculateMetadataFunction< VideosInSequenceProps > = async ({props}) => { const fps = 30; const videos = await Promise.all( props.videos.map(async (video) => { const durationInSeconds = await getVideoDuration(video.src); return { ...video, durationInFrames: Math.floor(durationInSeconds * fps), }; }), ); const durationInFrames = videos.reduce( (sum, video) => sum + video.durationInFrames, 0, ); return { durationInFrames, fps, props: { ...props, videos, }, }; };

Mediabunny loads the assets using fetch(). Remote URLs must be CORS-enabled; files referenced with staticFile() are served from the same origin.

Register the composition

In the root file, register the component and pass the videos through defaultProps:

Root.tsx
import React from 'react'; import {Composition, staticFile} from 'remotion'; import {calculateMetadata} from './calculate-metadata'; import {VideosInSequence} from './VideosInSequence'; export const RemotionRoot: 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} /> ); };

Browser autoplay policies

Mobile browsers may block videos that start after the beginning of the composition. See the notes about browser autoplay behavior for the available options.

See also