<OffthreadVideo>
Available from Remotion 3.0.11
This component imports and displays a video, similar to <Video/>, but during rendering, extracts the exact frame from the video and displays it in a <Img> tag. This extraction process happens outside the browser using FFMPEG.
This component was designed to combat limitations of the default <Video> element. See: <Video> vs <OffthreadVideo>.
Example
tsximport {AbsoluteFill ,OffthreadVideo ,staticFile } from "remotion";export constMyVideo = () => {return (<AbsoluteFill ><OffthreadVideo src ={staticFile ("video.webm")} /></AbsoluteFill >);};
tsximport {AbsoluteFill ,OffthreadVideo ,staticFile } from "remotion";export constMyVideo = () => {return (<AbsoluteFill ><OffthreadVideo src ={staticFile ("video.webm")} /></AbsoluteFill >);};
You can load a video from an URL as well:
tsxexport constMyComposition = () => {return (<AbsoluteFill ><OffthreadVideo src ="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" /></AbsoluteFill >);};
tsxexport constMyComposition = () => {return (<AbsoluteFill ><OffthreadVideo src ="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" /></AbsoluteFill >);};
Props
The props volume, playbackRate and muted are supported and work the same as in <Video>.
The props onError, className and style are supported and get passed to the underlying HTML element. Remember that during render, this is a <img> element, and during preview, this is a <video> element.
imageFormat
Available since v3.0.22
Either jpeg or png. Default jpeg.
With png, transparent videos (VP8, VP9, ProRes) can be displayed, however it is around 40% slower, with VP8 videos being much slower.
Performance tips
Avoid embedding a video beyond it's end (for example: Rendering a 5 second video inside 10 second composition). To create parity with the <Video> element, the video still displays its last frame in that case. However, to fetch the last frame specifically is a significantly more expensive operation than a frame from a known timestamp.
Looping a video
Unlike <Video>, OffthreadVideo does not currently implement the loop property. You can use the following snippet that uses @remotion/media-utils to loop a video.
LoopedOffthreadVideo.tsxtsximport {getVideoMetadata } from "@remotion/media-utils";importReact , {useEffect ,useState } from "react";import {continueRender ,delayRender ,Loop ,OffthreadVideo ,staticFile ,useVideoConfig ,} from "remotion";constsrc =staticFile ("myvideo.mp4");export constLoopedOffthreadVideo :React .FC = () => {const [duration ,setDuration ] =useState <null | number>(null);const [handle ] =useState (() =>delayRender ());const {fps } =useVideoConfig ();useEffect (() => {getVideoMetadata (src ).then (({durationInSeconds }) => {setDuration (durationInSeconds );continueRender (handle );}).catch ((err ) => {console .log (err );});}, [handle ]);if (duration === null) {return null;}return (<Loop durationInFrames ={Math .floor (fps *duration )}><OffthreadVideo src ={src } /></Loop >);};
LoopedOffthreadVideo.tsxtsximport {getVideoMetadata } from "@remotion/media-utils";importReact , {useEffect ,useState } from "react";import {continueRender ,delayRender ,Loop ,OffthreadVideo ,staticFile ,useVideoConfig ,} from "remotion";constsrc =staticFile ("myvideo.mp4");export constLoopedOffthreadVideo :React .FC = () => {const [duration ,setDuration ] =useState <null | number>(null);const [handle ] =useState (() =>delayRender ());const {fps } =useVideoConfig ();useEffect (() => {getVideoMetadata (src ).then (({durationInSeconds }) => {setDuration (durationInSeconds );continueRender (handle );}).catch ((err ) => {console .log (err );});}, [handle ]);if (duration === null) {return null;}return (<Loop durationInFrames ={Math .floor (fps *duration )}><OffthreadVideo src ={src } /></Loop >);};