播放器缓冲状态
从4.0.111版本开始可用
就像常规视频播放器一样,播放器中显示的内容可能尚未完全加载。
在这种情况下,最佳实践是暂停视频,让内容加载完毕,然后恢复播放。
Remotion具有本机缓冲状态,可以在缓冲区为空时暂停视频。
简而言之
您可以为<Video>
、<OffthreadVideo>
、<Audio>
标签添加pauseWhenBuffering
属性。
对于<Img>
标签,该属性称为pauseWhenLoading
。
通过这样做,播放器将在媒体加载完毕前暂停一小段时间。
机制
激活缓冲状态
组件可以通过首先使用useBufferState()
钩子,然后调用buffer.delayPlayback()
来告诉播放器切换到缓冲状态:
MyComp.tsxtsx
importReact from 'react';import {useBufferState } from 'remotion';constMyComp :React .FC = () => {constbuffer =useBufferState ();React .useEffect (() => {constdelayHandle =buffer .delayPlayback ();setTimeout (() => {delayHandle .unblock ();}, 5000);return () => {delayHandle .unblock ();};}, []);return null;};
MyComp.tsxtsx
importReact from 'react';import {useBufferState } from 'remotion';constMyComp :React .FC = () => {constbuffer =useBufferState ();React .useEffect (() => {constdelayHandle =buffer .delayPlayback ();setTimeout (() => {delayHandle .unblock ();}, 5000);return () => {delayHandle .unblock ();};}, []);return null;};
要清除句柄,请在delayPlayback()
的返回值上调用.unblock()
。
在激活缓冲状态时,请注意以下事项:
组件卸载时清除句柄
用户可能会寻找视频的不同部分,这些部分可能会立即可用。
使用useEffect()
的清理函数在组件卸载时清除句柄。
❌ 与React严格模式冲突tsx
importReact , {useState } from 'react';import {useBufferState } from 'remotion';constMyComp :React .FC = () => {constbuffer =useBufferState ();const [delayHandle ] =useState (() =>buffer .delayPlayback ()); // 💥React .useEffect (() => {setTimeout (() => {delayHandle .unblock ();}, 5000);}, []);return <></>;};
❌ 与React严格模式冲突tsx
importReact , {useState } from 'react';import {useBufferState } from 'remotion';constMyComp :React .FC = () => {constbuffer =useBufferState ();const [delayHandle ] =useState (() =>buffer .delayPlayback ()); // 💥React .useEffect (() => {setTimeout (() => {delayHandle .unblock ();}, 5000);}, []);return <></>;};
不要在useState()
内部使用delayPlayback()
虽然以下实现在生产环境中有效,但在React严格模式下会失败,因为useState()
钩子被调用两次,导致第一次调用的缓冲永远不会被清除。
❌ 当寻找视频的不同部分时不清除缓冲句柄tsx
importReact , {useState } from 'react';import {useBufferState } from 'remotion';constMyComp :React .FC = () => {constbuffer =useBufferState ();const [delayHandle ] =useState (() =>buffer .delayPlayback ()); // 💥React .useEffect (() => {setTimeout (() => {delayHandle .unblock ();}, 5000);return () => {delayHandle .unblock ();};}, []);return <></>;};
❌ 当寻找视频的不同部分时不清除缓冲句柄tsx
importReact , {useState } from 'react';import {useBufferState } from 'remotion';constMyComp :React .FC = () => {constbuffer =useBufferState ();const [delayHandle ] =useState (() =>buffer .delayPlayback ()); // 💥React .useEffect (() => {setTimeout (() => {delayHandle .unblock ();}, 5000);return () => {delayHandle .unblock ();};}, []);return <></>;};
Details
它不会替换delayRender()
delayRender()是一个不同的API,它控制了在渲染过程中何时拍摄屏幕截图。如果您正在加载数据,您可能希望在渲染过程中延迟组件的截图,并延迟预览视频的播放,在这种情况下,您需要同时使用这两个API。
同时使用delayRender()和delayPlayback()tsx
importReact from 'react';import {useBufferState ,delayRender ,continueRender } from 'remotion';constMyComp :React .FC = () => {constbuffer =useBufferState ();const [handle ] =React .useState (() =>delayRender ());React .useEffect (() => {constdelayHandle =buffer .delayPlayback ();setTimeout (() => {delayHandle .unblock ();continueRender (handle );}, 5000);return () => {delayHandle .unblock ();};}, []);return <></>;};
同时使用delayRender()和delayPlayback()tsx
importReact from 'react';import {useBufferState ,delayRender ,continueRender } from 'remotion';constMyComp :React .FC = () => {constbuffer =useBufferState ();const [handle ] =React .useState (() =>delayRender ());React .useEffect (() => {constdelayHandle =buffer .delayPlayback ();setTimeout (() => {delayHandle .unblock ();continueRender (handle );}, 5000);return () => {delayHandle .unblock ();};}, []);return <></>;};
可能的状态
播放器是否正在缓冲不会在内部更改playing
/ paused
状态。
因此,播放器可以处于四种播放状态:
playing && !buffering
playing && buffering
paused && !buffering
paused && buffering
只有在状态
默认情况下,Remotion将根据播放器的状态显示以下UI:
当处于状态
当处于状态
否则,将显示播放按钮。
您可以向此添加其他UI,例如在播放器缓冲时在播放器上叠加一个旋转器。
监听缓冲事件
如果<Player />
进入缓冲状态,它将发出waiting
事件。
一旦恢复,它会发出resume
事件。
监听waiting和resume事件tsx
import {Player ,PlayerRef } from '@remotion/player';import {useEffect ,useRef ,useState } from 'react';import {MyVideo } from './remotion/MyVideo';export constApp :React .FC = () => {constplayerRef =useRef <PlayerRef >(null);const [buffering ,setBuffering ] =useState (false);useEffect (() => {const {current } =playerRef ;if (!current ) {return;}constonBuffering = () => {setBuffering (true);};constonResume = () => {setBuffering (false);};current .addEventListener ('waiting',onBuffering );current .addEventListener ('resume',onResume );return () => {current .removeEventListener ('waiting',onBuffering );current .removeEventListener ('resume',onResume );};}, [setBuffering ]);return (<Player ref ={playerRef }component ={MyVideo }durationInFrames ={120}compositionWidth ={1920}compositionHeight ={1080}fps ={30}/>);};
监听waiting和resume事件tsx
import {Player ,PlayerRef } from '@remotion/player';import {useEffect ,useRef ,useState } from 'react';import {MyVideo } from './remotion/MyVideo';export constApp :React .FC = () => {constplayerRef =useRef <PlayerRef >(null);const [buffering ,setBuffering ] =useState (false);useEffect (() => {const {current } =playerRef ;if (!current ) {return;}constonBuffering = () => {setBuffering (true);};constonResume = () => {setBuffering (false);};current .addEventListener ('waiting',onBuffering );current .addEventListener ('resume',onResume );return () => {current .removeEventListener ('waiting',onBuffering );current .removeEventListener ('resume',onResume );};}, [setBuffering ]);return (<Player ref ={playerRef }component ={MyVideo }durationInFrames ={120}compositionWidth ={1920}compositionHeight ={1080}fps ={30}/>);};
具有内置缓冲的组件
您可以在以下组件上启用缓冲:
<Audio>
- 添加pauseWhenBuffering
属性<Video>
- 添加pauseWhenBuffering
属性<OffthreadVideo>
- 添加pauseWhenBuffering
属性<Img>
- 添加pauseWhenLoading
属性
在 UI 中指示缓冲
当播放器正在缓冲时,默认情况下,播放按钮将被一个旋转器替换。
为了防止 UI 闪烁,此旋转器只会在播放器处于缓冲状态超过 300 毫秒后显示。
您可以通过将 bufferStateDelayInMilliseconds
属性传递给 <Player />
组件来自定义 300
毫秒的超时时间。
设置显示旋转器的延迟时间tsx
import {Player ,PlayerRef } from '@remotion/player';import {useEffect ,useRef ,useState } from 'react';import {MyVideo } from './remotion/MyVideo';export constApp :React .FC = () => {return (<Player component ={MyVideo }durationInFrames ={120}compositionWidth ={1920}compositionHeight ={1080}fps ={30}bufferStateDelayInMilliseconds ={1000} // Or set to `0` to immediately show the spinner/>);};
设置显示旋转器的延迟时间tsx
import {Player ,PlayerRef } from '@remotion/player';import {useEffect ,useRef ,useState } from 'react';import {MyVideo } from './remotion/MyVideo';export constApp :React .FC = () => {return (<Player component ={MyVideo }durationInFrames ={120}compositionWidth ={1920}compositionHeight ={1080}fps ={30}bufferStateDelayInMilliseconds ={1000} // Or set to `0` to immediately show the spinner/>);};
在 Studio 中,您可以在 配置文件 中更改延迟:
remotion.config.tsts
import {Config } from '@remotion/cli/config';Config .setBufferStateDelayInMilliseconds (0);
remotion.config.tsts
import {Config } from '@remotion/cli/config';Config .setBufferStateDelayInMilliseconds (0);
要自定义显示在播放按钮位置的旋转器,您可以传递一个 renderPlayPauseButton()
属性:
在播放按钮内部渲染自定义旋转器tsx
import {Player ,RenderPlayPauseButton } from '@remotion/player';import {useCallback } from 'react';export constApp :React .FC = () => {constrenderPlayPauseButton :RenderPlayPauseButton =useCallback (({playing ,isBuffering }) => {if (playing &&isBuffering ) {return <MySpinner />;}return null;},[],);return (<Player component ={MyVideo }durationInFrames ={120}compositionWidth ={1920}compositionHeight ={1080}fps ={30}renderPlayPauseButton ={renderPlayPauseButton }/>);};
在播放按钮内部渲染自定义旋转器tsx
import {Player ,RenderPlayPauseButton } from '@remotion/player';import {useCallback } from 'react';export constApp :React .FC = () => {constrenderPlayPauseButton :RenderPlayPauseButton =useCallback (({playing ,isBuffering }) => {if (playing &&isBuffering ) {return <MySpinner />;}return null;},[],);return (<Player component ={MyVideo }durationInFrames ={120}compositionWidth ={1920}compositionHeight ={1080}fps ={30}renderPlayPauseButton ={renderPlayPauseButton }/>);};
要在播放器上方显示一个叠加的加载 UI(例如旋转器),您可以将 showPosterWhenBuffering
设置为 true
并传递一个 renderPoster()
属性:
在播放器上方渲染自定义旋转器tsx
import type {RenderPoster } from '@remotion/player';import {Player } from '@remotion/player';constMyApp :React .FC = () => {constrenderPoster :RenderPoster =useCallback (({isBuffering }) => {if (isBuffering ) {return (<AbsoluteFill style ={{justifyContent : 'center',alignItems : 'center'}}><Spinner /></AbsoluteFill >);}return null;}, []);return (<Player fps ={30}component ={Component }durationInFrames ={100}compositionWidth ={1080}compositionHeight ={1080}renderPoster ={renderPoster }showPosterWhenBuffering />);};
在播放器上方渲染自定义旋转器tsx
import type {RenderPoster } from '@remotion/player';import {Player } from '@remotion/player';constMyApp :React .FC = () => {constrenderPoster :RenderPoster =useCallback (({isBuffering }) => {if (isBuffering ) {return (<AbsoluteFill style ={{justifyContent : 'center',alignItems : 'center'}}><Spinner /></AbsoluteFill >);}return null;}, []);return (<Player fps ={30}component ={Component }durationInFrames ={100}compositionWidth ={1080}compositionHeight ={1080}renderPoster ={renderPoster }showPosterWhenBuffering />);};
Remotion 5.0 中即将发生的更改
在 Remotion 4.0 中,媒体标签如 <Audio>
、<OffthreadVideo>
标签需要选择使用缓冲状态。
在 Remotion 5.0 中,计划让 <Audio>
、<Video>
和 <OffthreadVideo>
自动使用缓冲状态,但它们可以选择退出。