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:
import {CallbackListener , PlayerRef } from '@remotion/player';
import {useCallback , useSyncExternalStore } from 'react';
export const useCurrentPlayerFrame = (
ref : React .RefObject <PlayerRef | null>,
) => {
const subscribe = useCallback (
(onStoreChange : () => void) => {
const {current } = ref ;
if (!current ) {
return () => undefined ;
}
const updater : CallbackListener <'frameupdate'> = ({detail }) => {
onStoreChange ();
};
current .addEventListener ('frameupdate', updater );
return () => {
current .removeEventListener ('frameupdate', updater );
};
},
[ref ],
);
const data = useSyncExternalStore <number>(
subscribe ,
() => ref .current ?.getCurrentFrame () ?? 0,
() => 0,
);
return data ;
};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:
import React from 'react';
import {PlayerRef } from '@remotion/player';
import {useCurrentPlayerFrame } from './use-current-player-frame';
export const TimeDisplay : React .FC <{
playerRef : React .RefObject <PlayerRef | null>;
}> = ({playerRef }) => {
const frame = 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.