Displaying the current time
When rendering a <Player> in your app, special considerations must be taken to prevent constant re-renders of the app or <Player> if the time changes.
This is why the useCurrentFrame() hook does not work outside a composition.
Do not put this hook into the same component in which the <Player> is rendered, otherwise you'll see constant re-renders. Instead, put it inside a component that is rendered adjacent to the component in which the Player is rendered.
Synchronizing a component with the Player time
If you want to display a component that synchronizes with the time of the player, for example the cursor of a timeline component or a custom time display, you can use the following hook:
use-current-player-frame.tsimport {CallbackListener ,PlayerRef } from '@remotion/player'; import {useCallback ,useSyncExternalStore } from 'react'; export constuseCurrentPlayerFrame = (ref :React .RefObject <PlayerRef | null>, ) => { constsubscribe =useCallback ( (onStoreChange : () => void) => { const {current } =ref ; if (!current ) { return () =>undefined ; } constupdater :CallbackListener <'frameupdate'> = ({detail }) => {onStoreChange (); };current .addEventListener ('frameupdate',updater ); return () => {current .removeEventListener ('frameupdate',updater ); }; }, [ref ], ); constdata =useSyncExternalStore <number>(subscribe , () =>ref .current ?.getCurrentFrame () ?? 0, () => 0, ); returndata ; };
Usage example
Add a ref to a React Player and pass it to another component:
import {Player , PlayerRef } from '@remotion/player';
import {useRef } from 'react';
import {MyVideo } from './remotion/MyVideo';
import {TimeDisplay } from './remotion/TimeDisplay';
export const App : React .FC = () => {
const playerRef = useRef <PlayerRef >(null);
return (
<>
<Player
ref ={playerRef }
component ={MyVideo }
durationInFrames ={120}
compositionWidth ={1920}
compositionHeight ={1080}
fps ={30}
/>
<TimeDisplay playerRef ={playerRef } />
</>
);
};This is how a component could access the current time:
TimeDisplay.tsximportReact from 'react'; import {PlayerRef } from '@remotion/player'; import {useCurrentPlayerFrame } from './use-current-player-frame'; export constTimeDisplay :React .FC <{playerRef :React .RefObject <PlayerRef | null>; }> = ({playerRef }) => { constframe =useCurrentPlayerFrame (playerRef ); return <div >current frame: {frame }</div >; };
This approach is efficient, because only the video itself and the component relying on the time are re-rendering, but the <App> component is not.