Skip to main content

<Player>

一个组件,可以在常规的 React 应用程序中呈现(例如:Next.JS, Vite.js, Create React App),用于显示 Remotion 视频。

MyApp.tsx
tsx
import {Player} from '@remotion/player';
import {MyVideo} from './remotion/MyVideo';
 
export const App: React.FC = () => {
return (
<Player
component={MyVideo}
durationInFrames={120}
compositionWidth={1920}
compositionHeight={1080}
fps={30}
/>
);
};
MyApp.tsx
tsx
import {Player} from '@remotion/player';
import {MyVideo} from './remotion/MyVideo';
 
export const App: React.FC = () => {
return (
<Player
component={MyVideo}
durationInFrames={120}
compositionWidth={1920}
compositionHeight={1080}
fps={30}
/>
);
};

查看更多用法示例

API​

component 或 lazyComponent​

直接传递一个 React 组件 或 传递一个返回动态导入的函数。传递这两个属性中的任何一个或两个都会导致错误。

如果使用 lazyComponent,请将其包装在 useCallback() 中,以避免不断重新渲染。查看这里的示例。

note

Player 不使用 <Composition>。直接传递您的组件,不要将其包装在 <Composition> 组件中。

durationInFrames​

视频的帧数。必须是整数且大于 0。

fps​

视频的帧率。必须是数字。

compositionWidth​

在渲染为 MP4 时希望视频具有的宽度。使用 style={{width: <width>}} 来定义浏览器中假定的宽度。

note

示例: 如果要渲染全高清视频,请将 compositionWidth 设置为 1920,将 compositionHeight 设置为 1080。默认情况下,Player 还会假定这些尺寸。 要使其变小,请传递一个 style 属性,为播放器指定不同的宽度:{"style={{width: 400}}"}。查看 Player 缩放 以了解更多信息。

compositionHeight​

在渲染为 MP4 时希望视频具有的高度。使用 style={{height: <height>}} 来定义浏览器中假定的高度。

loop​

可选

视频结束时是否应重新开始。默认为 false。

autoPlay​

可选

视频加载后是否应立即开始播放。默认为 false。

controls​

可选

视频是否应显示一个进度条和播放/暂停按钮。默认为 false。

showVolumeControls​

可选

视频是否应显示音量滑块和静音按钮。仅在controls也设置为true时有效。默认为true。

allowFullscreen​

可选

视频是否可以全屏播放。默认为true。

clickToPlay​

可选

一个布尔属性,定义您是否可以通过单击播放器来播放、暂停或恢复视频。如果controls为true,默认为true,否则为false。

doubleClickToFullscreen​

可选

一个布尔属性,定义您是否可以通过双击播放器全屏和退出全屏。如果启用,单击视频一次将延迟暂停视频200毫秒,以等待可能的第二次单击。默认为false。

note

此选项不支持移动设备。您不需要在移动设备上双击以进入全屏模式。

spaceKeyToPlayOrPause​

可选

一个布尔属性,定义您是否可以使用空格键播放或暂停视频。如果启用,播放视频然后按空格键暂停和恢复视频。仅在controls为true时有效。默认为true。

moveToBeginningWhenEndedv3.1.3​

可选

一个布尔属性,定义视频在结束后是否应将位置返回到零。仅在loop被禁用时有效。默认为true。

inputProps​

可选

将props传递给您使用component prop指定的组件。Typescript定义采用您为component指定的props的形状。默认为undefined。

style​

可选

用于HTMLDivElement的常规style prop。如果您希望播放器具有不同的尺寸,则可以传递不同的高度和宽度。

classNamev3.1.3​

可选

要应用于容器的HTML类名。

initialFramev3.1.14​

可选

从特定帧开始播放。默认为0。一旦播放器被挂载,此属性将无法更改。

numberOfSharedAudioTagsv2.3.1​

可选

如果您使用 <Audio /> 标签,在某些浏览器(特别是 iOS Safari)中可能无法播放,这是由于浏览器的自动播放策略。这就是为什么 Remotion Player 预先挂载了一组带有静音音频的音频标签,这些音频标签在用户交互时会被播放。然后可以使用这些音频标签来稍后播放真实音频,并且不会受到浏览器的自动播放策略的影响。

此选项控制正在呈现的音频标签数量,默认为 5。如果挂载的音频标签多于可用的共享音频标签,则会引发错误。

如果您想退出此行为,可以传递 0,以便同时挂载原生音频标签和 Remotion 的 <Audio /> 标签。

设置了此属性后,将无法再更改它,否则将引发错误。

playbackRate​

可选

介于 -4 和 4 之间(不包括 0)的数字,用于指定播放器运行媒体的速度。

playbackRate 为 2 表示视频播放速度加快两倍。playbackRate 为 0.5 表示视频播放速度减慢两倍。playbackRate 为 -1 表示视频倒放。请注意,<Audio/> 和 <Video/> 标签无法倒放,这是浏览器的限制。

默认为 1。

errorFallback​

可选

用于渲染自定义错误消息的回调函数。请参阅 处理错误 部分以查看示例。

renderLoading​

可选

一个回调函数,允许您返回一个自定义 UI,在播放器加载时显示。

回调函数的第一个参数包含播放器呈现时的 height 和 width。

tsx
const MyApp: React.FC = () => {
// `RenderLoading` type can be imported from "@remotion/player"
const renderLoading: RenderLoading = useCallback(({height, width}) => {
return (
<AbsoluteFill style={{backgroundColor: 'gray'}}>
Loading player ({height}x{width})
</AbsoluteFill>
);
}, []);
 
return (
<Player
fps={30}
component={Component}
durationInFrames={100}
compositionWidth={1080}
compositionHeight={1080}
renderLoading={renderLoading}
/>
);
};
tsx
const MyApp: React.FC = () => {
// `RenderLoading` type can be imported from "@remotion/player"
const renderLoading: RenderLoading = useCallback(({height, width}) => {
return (
<AbsoluteFill style={{backgroundColor: 'gray'}}>
Loading player ({height}x{width})
</AbsoluteFill>
);
}, []);
 
return (
<Player
fps={30}
component={Component}
durationInFrames={100}
compositionWidth={1080}
compositionHeight={1080}
renderLoading={renderLoading}
/>
);
};
info

如果播放器包含使用 React Suspense 的元素,或者正在使用 lazyComponent 属性,则需要加载播放器。

renderPosterv3.2.14​

可选

一个回调函数,允许您返回一个自定义 UI,覆盖在播放器上方。

您可以使用showPosterWhenUnplayed、showPosterWhenPaused、showPosterWhenEnded和showPosterWhenBuffering属性来控制何时渲染海报。默认情况下,它们都被禁用。

第一个参数包含播放器渲染时的高度和宽度。

tsx
import type {RenderPoster} from '@remotion/player';
import {Player} from '@remotion/player';
 
const MyApp: React.FC = () => {
const renderPoster: RenderPoster = useCallback(
({height, width, isBuffering}) => {
if (isBuffering) {
return (
<AbsoluteFill
style={{justifyContent: 'center', alignItems: 'center'}}
>
<Spinner />
</AbsoluteFill>
);
}
 
return (
<AbsoluteFill style={{backgroundColor: 'gray'}}>
Click to play! ({height}x{width})
</AbsoluteFill>
);
},
[],
);
 
return (
<Player
fps={30}
component={Component}
durationInFrames={100}
compositionWidth={1080}
compositionHeight={1080}
renderPoster={renderPoster}
showPosterWhenUnplayed
/>
);
};
tsx
import type {RenderPoster} from '@remotion/player';
import {Player} from '@remotion/player';
 
const MyApp: React.FC = () => {
const renderPoster: RenderPoster = useCallback(
({height, width, isBuffering}) => {
if (isBuffering) {
return (
<AbsoluteFill
style={{justifyContent: 'center', alignItems: 'center'}}
>
<Spinner />
</AbsoluteFill>
);
}
 
return (
<AbsoluteFill style={{backgroundColor: 'gray'}}>
Click to play! ({height}x{width})
</AbsoluteFill>
);
},
[],
);
 
return (
<Player
fps={30}
component={Component}
durationInFrames={100}
compositionWidth={1080}
compositionHeight={1080}
renderPoster={renderPoster}
showPosterWhenUnplayed
/>
);
};

showPosterWhenUnplayedv3.2.14​

可选

当视频处于初始状态且尚未播放时渲染海报。需要设置renderPoster()。默认值:false。

showPosterWhenPausedv3.2.14​

可选

当视频暂停时渲染海报。尽管被视为暂停状态,但在用户浏览视频时不会渲染海报。需要设置renderPoster()。默认值:false。

showPosterWhenEndedv3.2.14​

可选

当视频结束时渲染海报。需要将moveToBeginning设置为false。需要设置renderPoster()。默认值:false。

showPosterWhenBufferingv4.0.111​

可选

在<Player>处于缓冲状态时渲染海报。例如,您可以在视频中心显示一个旋转的加载图标。

inFramev3.2.15​

可选

限制仅在特定帧之后播放。视频将从此帧开始,并在结束时移动到此位置。必须是一个整数,不小于0,不大于outFrame,也不大于durationInFrames - 1。默认值为null,表示视频的开头。

outFramev3.2.15​

可选

限制仅在特定帧之前播放。视频将在此帧结束,并在结束时移动到开头。必须是一个整数,不小于1,不小于inFrame,也不大于durationInFrames - 1。默认值为null,表示视频的结尾。

initiallyShowControlsv3.2.24​

可选

如果为true,则当播放器进入场景时,控件会闪烁。 2秒后没有悬停,控件会淡出。 这类似于YouTube的做法,并向用户发出信号,表明播放器实际上是可控的。 您还可以传递一个number,用于自定义以毫秒为单位的持续时间。 默认为true,自v3.2.24起支持,之前不支持。

initiallyMutedv3.3.81​

可选

如果为true,则播放器在初始状态下会被静音。 如果视频必须自动播放,而不管浏览器的autoplay策略如何,这将很有用。

renderPlayPauseButtonv3.2.32​

可选

允许您自定义控件的播放/暂停按钮。
必须是一个返回有效的React元素的回调函数。

App.tsx
tsx
import {Player, RenderPlayPauseButton} from '@remotion/player';
import {useCallback} from 'react';
 
export const App: React.FC = () => {
const renderPlayPauseButton: RenderPlayPauseButton = useCallback(
({playing, isBuffering}) => {
// Since v4.0.111, isBuffering is available
if (playing && isBuffering) {
return <MySpinner />;
}
 
if (playing) {
return <MyPlayButton />;
}
 
return <MyPauseButton />;
},
[],
);
 
return (
<Player
component={MyVideo}
durationInFrames={120}
compositionWidth={1920}
compositionHeight={1080}
fps={30}
renderPlayPauseButton={renderPlayPauseButton}
/>
);
};
App.tsx
tsx
import {Player, RenderPlayPauseButton} from '@remotion/player';
import {useCallback} from 'react';
 
export const App: React.FC = () => {
const renderPlayPauseButton: RenderPlayPauseButton = useCallback(
({playing, isBuffering}) => {
// Since v4.0.111, isBuffering is available
if (playing && isBuffering) {
return <MySpinner />;
}
 
if (playing) {
return <MyPlayButton />;
}
 
return <MyPauseButton />;
},
[],
);
 
return (
<Player
component={MyVideo}
durationInFrames={120}
compositionWidth={1920}
compositionHeight={1080}
fps={30}
renderPlayPauseButton={renderPlayPauseButton}
/>
);
};

自v4.0.111起,在回调中传递了一个isBuffering参数,如果播放器处于缓冲状态,则为true。 了解更多有关播放器可能处于的播放状态。

自v4.0.111起,您可以在回调中返回null以回退到默认UI。

renderFullscreenButtonv3.2.32​

可选

允许您自定义播放器控件的全屏按钮,必须返回有效的React元素。 如果浏览器禁用全屏或不支持全屏,则不会呈现。

tsx
import {Player, RenderFullscreenButton} from '@remotion/player';
import {useCallback} from 'react';
 
export const App: React.FC = () => {
const renderFullscreenButton: RenderFullscreenButton = useCallback(
({isFullscreen}) => {
if (isFullscreen) {
return <MinimiseButton />;
}
 
return <FullScreenButton />;
},
[],
);
 
return (
<Player
component={MyVideo}
durationInFrames={120}
compositionWidth={1920}
compositionHeight={1080}
fps={30}
renderFullscreenButton={renderFullscreenButton}
/>
);
};
tsx
import {Player, RenderFullscreenButton} from '@remotion/player';
import {useCallback} from 'react';
 
export const App: React.FC = () => {
const renderFullscreenButton: RenderFullscreenButton = useCallback(
({isFullscreen}) => {
if (isFullscreen) {
return <MinimiseButton />;
}
 
return <FullScreenButton />;
},
[],
);
 
return (
<Player
component={MyVideo}
durationInFrames={120}
compositionWidth={1920}
compositionHeight={1080}
fps={30}
renderFullscreenButton={renderFullscreenButton}
/>
);
};

renderMuteButtonv4.0.188​

可选

允许您自定义控件的静音按钮,必须返回有效的React元素。
操作已禁用,您必须自行使用PlayerRef附加点击处理程序。
如果取消静音视频,我们建议同时设置.setVolume(1)和.setMuted(false)。

tsx
import {Player, RenderMuteButton} from '@remotion/player';
import {useCallback} from 'react';
 
export const App: React.FC = () => {
const renderMuteButton: RenderMuteButton = useCallback(({muted, volume}) => {
const isMutedOrVolumeZero = muted || volume === 0;
if (isMutedOrVolumeZero) {
return <VolumeOffIcon />;
}
 
return <VolumeOnIcon />;
}, []);
 
return (
<Player
fps={30}
component={MyVideo}
durationInFrames={120}
compositionWidth={1920}
compositionHeight={1080}
renderMuteButton={renderMuteButton}
/>
);
};
tsx
import {Player, RenderMuteButton} from '@remotion/player';
import {useCallback} from 'react';
 
export const App: React.FC = () => {
const renderMuteButton: RenderMuteButton = useCallback(({muted, volume}) => {
const isMutedOrVolumeZero = muted || volume === 0;
if (isMutedOrVolumeZero) {
return <VolumeOffIcon />;
}
 
return <VolumeOnIcon />;
}, []);
 
return (
<Player
fps={30}
component={MyVideo}
durationInFrames={120}
compositionWidth={1920}
compositionHeight={1080}
renderMuteButton={renderMuteButton}
/>
);
};

renderVolumeSliderv4.0.188​

允许自定义音量滑块的实现,必须返回有效的 React 元素。
查看默认实现此处。
默认实现使音量滑块垂直 (isVertical),并且可以使用 Tab 键进行键盘导航 (onBlur,inputRef)。

App.tsx
tsx
import {useCallback} from 'react';
import {Player, type RenderVolumeSlider} from '@remotion/player';
 
export const App: React.FC = () => {
const renderVolumeSlider: RenderVolumeSlider = useCallback(
({isVertical, volume, onBlur, inputRef, setVolume}) => {
return null; // Your volume slider implementation
},
[],
);
 
return (
<Player
fps={30}
component={MyVideo}
durationInFrames={120}
compositionWidth={1920}
compositionHeight={1080}
renderVolumeSlider={renderVolumeSlider}
/>
);
};
App.tsx
tsx
import {useCallback} from 'react';
import {Player, type RenderVolumeSlider} from '@remotion/player';
 
export const App: React.FC = () => {
const renderVolumeSlider: RenderVolumeSlider = useCallback(
({isVertical, volume, onBlur, inputRef, setVolume}) => {
return null; // Your volume slider implementation
},
[],
);
 
return (
<Player
fps={30}
component={MyVideo}
durationInFrames={120}
compositionWidth={1920}
compositionHeight={1080}
renderVolumeSlider={renderVolumeSlider}
/>
);
};

alwaysShowControlsv3.3.55​

可选

如果为 true,则始终显示播放器控件,即使鼠标在播放器区域之外。此设置会覆盖默认行为,即在鼠标在播放器区域内不活动一段时间后自动隐藏控件。默认为 false。

hideControlsWhenPointerDoesntMovev4.0.124​

可选

当鼠标在播放器上不活动 3 秒后隐藏播放器控件。默认情况下,此行为已启用 (true)。将尊重 alwaysShowControls 属性,即如果设置为 true,则控件将永远不会隐藏。

您还可以传入一个数字来自定义以毫秒为单位的隐藏延迟,默认为 3000。

showPlaybackRateControlv3.3.98​

可选

如果为 true,则显示一个齿轮图标,允许用户更改播放速率。

您可以传入一个包含可供选择的播放速率的数组,但不支持动态更新列表。true 是 [0.5, 0.8, 1, 1.2, 1.5, 1.8, 2, 2.5, 3] 的别名。

默认为 false。

posterFillModev4.0.78​

可以是 player-size(默认)或 composition-size:

  • player-size:海报将以播放器的大小呈现。如果您想要以恒定大小呈现例如播放按钮,则这很有用。
  • composition-size:海报将以合成的大小呈现,并缩放到播放器的大小。如果您想要以视频的冻结帧作为海报呈现,则这很有用。

bufferStateDelayInMillisecondsv4.0.111​

在玩家进入缓冲状态后,它将等待一段时间,然后显示缓冲UI。
这可以防止在玩家仅处于缓冲状态的短时间内出现卡顿。默认值为 300。

Note:

这使您可以灵活地为缓冲状态实现自定义UI。

overflowVisiblev4.0.173​

使玩家在画布之外呈现内容。如果视频中有可拖动元素等交互元素,则此功能非常有用。

PlayerRef​

您可以将引用附加到播放器并以命令方式控制它。

tsx
import {Player, PlayerRef} from '@remotion/player';
import {useEffect, useRef} from 'react';
import {MyComposition} from './MyComposition';
 
const MyComp: React.FC = () => {
const playerRef = useRef<PlayerRef>(null);
 
useEffect(() => {
if (playerRef.current) {
console.log(playerRef.current.getCurrentFrame());
}
}, []);
 
return (
<Player
ref={playerRef}
durationInFrames={30}
compositionWidth={1080}
compositionHeight={1080}
fps={30}
component={MyComposition}
// Many other optional props are available.
/>
);
};
tsx
import {Player, PlayerRef} from '@remotion/player';
import {useEffect, useRef} from 'react';
import {MyComposition} from './MyComposition';
 
const MyComp: React.FC = () => {
const playerRef = useRef<PlayerRef>(null);
 
useEffect(() => {
if (playerRef.current) {
console.log(playerRef.current.getCurrentFrame());
}
}, []);
 
return (
<Player
ref={playerRef}
durationInFrames={30}
compositionWidth={1080}
compositionHeight={1080}
fps={30}
component={MyComposition}
// Many other optional props are available.
/>
);
};

以下方法可在播放器引用上使用:

pause()​

暂停视频。如果视频已经暂停,则不会发生任何事情。

pauseAndReturnToPlayStart()v4.0.67​

如果视频正在播放,则暂停并返回到视频上次播放的位置。

play()​

播放视频。如果视频已经在播放,则不会发生任何事情。

如果您从用户手势中播放视频,请将 SyntheticEvent 作为参数传递,以便浏览器自动播放限制不适用。

toggle()​

如果视频正在播放,则暂停视频。如果视频已暂停,则播放视频。

如果您从用户手势中播放视频,请将 SyntheticEvent 作为参数传递,以便浏览器自动播放限制不适用。

getCurrentFrame()​

获取当前位置表示为当前帧。除以您传递的 fps 以获取以秒为单位的时间。

如果要显示与播放器时间同步的组件,则必须考虑特殊情况。

isPlaying()v2.5.7​

返回一个布尔值,指示视频是否正在播放。

getContainerNode()v2.4.2​

获取播放器的容器 HTMLDivElement。如果您想要手动附加监听器到播放器元素,这将非常有用。

tsx
const playerRef = useRef<PlayerRef>(null);
 
useEffect(() => {
if (!playerRef.current) {
return;
}
const container = playerRef.current.getContainerNode();
if (!container) {
return;
}
 
const onClick = () => {
console.log('player got clicked');
};
 
container.addEventListener('click', onClick);
return () => {
container.removeEventListener('click', onClick);
};
}, []);
tsx
const playerRef = useRef<PlayerRef>(null);
 
useEffect(() => {
if (!playerRef.current) {
return;
}
const container = playerRef.current.getContainerNode();
if (!container) {
return;
}
 
const onClick = () => {
console.log('player got clicked');
};
 
container.addEventListener('click', onClick);
return () => {
container.removeEventListener('click', onClick);
};
}, []);

mute()​

静音视频。

unmute()​

取消静音视频。

getVolume()​

获取视频的音量。音量的值介于 0 和 1 之间,初始值为 1。

setVolume()​

参数​

  • volume: number

设置视频的音量。必须是介于 0 和 1 之间的值,否则将抛出异常。

isMuted()​

返回一个布尔值,指定视频是否已静音。

seekTo()​

参数​

  • frame: number

将视频中的位置移动到特定帧。如果视频正在播放,它将暂停一小段时间,然后在完成搜索后重新开始播放。

isFullscreen()​

返回一个布尔值,指示视频当前是否在全屏播放。

要观察全屏状态并对更改做出反应,请监听全局文档上的 fullscreenchange 事件。

requestFullscreen()​

请求视频进入全屏模式。如果 allowFullscreen 属性为 false 或浏览器不支持使播放器进入全屏模式,则此方法将抛出异常。

在 Mobile Safari 中,全屏模式从 iOS 17 开始支持。

exitFullscreen()​

退出全屏模式。

getScale()v3.2.24​

返回一个数字,表示内容相对于自然组合大小缩小了多少。例如,如果组合是 1920x1080,但播放器宽度为 960px,则此方法将返回 0.5。

addEventListener()​

开始监听事件。请查看 Events 部分以查看函数签名和可用事件。

removeEventListener()​

停止监听事件。请查看 Events 部分以查看函数签名和可用事件。

事件​

使用 player ref,您可以绑定事件侦听器以获取有关播放器的特定事件的通知。

tsx
import {CallbackListener} from '@remotion/player';
const playerRef = useRef<PlayerRef>(null);
 
useEffect(() => {
if (!playerRef.current) {
return;
}
const onPlay: CallbackListener<'play'> = () => {
console.log('play');
};
const onRateChange: CallbackListener<'ratechange'> = (e) => {
console.log('ratechange', e.detail.playbackRate);
};
const onVolumeChange: CallbackListener<'volumechange'> = (e) => {
console.log('new volume', e.detail.volume);
};
 
const onPause: CallbackListener<'pause'> = () => {
console.log('pausing');
};
 
const onSeeked: CallbackListener<'seeked'> = (e) => {
console.log('seeked to ' + e.detail.frame);
};
 
const onTimeupdate: CallbackListener<'timeupdate'> = (e) => {
console.log('time has updated to ' + e.detail.frame);
};
 
const onEnded: CallbackListener<'ended'> = () => {
console.log('ended');
};
 
const onError: CallbackListener<'error'> = (e) => {
console.log('error', e.detail.error);
};
 
const onFullscreenChange: CallbackListener<'fullscreenchange'> = (e) => {
console.log('fullscreenchange', e.detail.isFullscreen);
};
 
const onScaleChange: CallbackListener<'scalechange'> = (e) => {
console.log('scalechange', e.detail.scale);
};
 
const onMuteChange: CallbackListener<'mutechange'> = (e) => {
console.log('mutechange', e.detail.isMuted);
};
 
playerRef.current.addEventListener('play', onPlay);
playerRef.current.addEventListener('ratechange', onRateChange);
playerRef.current.addEventListener('volumechange', onVolumeChange);
playerRef.current.addEventListener('pause', onPause);
playerRef.current.addEventListener('ended', onEnded);
playerRef.current.addEventListener('error', onError);
playerRef.current.addEventListener('fullscreenchange', onFullscreenChange);
playerRef.current.addEventListener('scalechange', onScaleChange);
playerRef.current.addEventListener('mutechange', onMuteChange);
 
// See below for difference between `seeked` and `timeupdate`
playerRef.current.addEventListener('seeked', onSeeked);
playerRef.current.addEventListener('timeupdate', onTimeupdate);
 
return () => {
// Make sure to clean up event listeners
if (playerRef.current) {
playerRef.current.removeEventListener('play', onPlay);
playerRef.current.removeEventListener('ratechange', onRateChange);
playerRef.current.removeEventListener('volumechange', onVolumeChange);
playerRef.current.removeEventListener('pause', onPause);
playerRef.current.removeEventListener('ended', onEnded);
playerRef.current.removeEventListener('error', onError);
playerRef.current.removeEventListener(
'fullscreenchange',
onFullscreenChange,
);
playerRef.current.removeEventListener('scalechange', onScaleChange);
playerRef.current.removeEventListener('mutechange', onMuteChange);
playerRef.current.removeEventListener('seeked', onSeeked);
playerRef.current.removeEventListener('timeupdate', onTimeupdate);
}
};
}, []);
tsx
import {CallbackListener} from '@remotion/player';
const playerRef = useRef<PlayerRef>(null);
 
useEffect(() => {
if (!playerRef.current) {
return;
}
const onPlay: CallbackListener<'play'> = () => {
console.log('play');
};
const onRateChange: CallbackListener<'ratechange'> = (e) => {
console.log('ratechange', e.detail.playbackRate);
};
const onVolumeChange: CallbackListener<'volumechange'> = (e) => {
console.log('new volume', e.detail.volume);
};
 
const onPause: CallbackListener<'pause'> = () => {
console.log('pausing');
};
 
const onSeeked: CallbackListener<'seeked'> = (e) => {
console.log('seeked to ' + e.detail.frame);
};
 
const onTimeupdate: CallbackListener<'timeupdate'> = (e) => {
console.log('time has updated to ' + e.detail.frame);
};
 
const onEnded: CallbackListener<'ended'> = () => {
console.log('ended');
};
 
const onError: CallbackListener<'error'> = (e) => {
console.log('error', e.detail.error);
};
 
const onFullscreenChange: CallbackListener<'fullscreenchange'> = (e) => {
console.log('fullscreenchange', e.detail.isFullscreen);
};
 
const onScaleChange: CallbackListener<'scalechange'> = (e) => {
console.log('scalechange', e.detail.scale);
};
 
const onMuteChange: CallbackListener<'mutechange'> = (e) => {
console.log('mutechange', e.detail.isMuted);
};
 
playerRef.current.addEventListener('play', onPlay);
playerRef.current.addEventListener('ratechange', onRateChange);
playerRef.current.addEventListener('volumechange', onVolumeChange);
playerRef.current.addEventListener('pause', onPause);
playerRef.current.addEventListener('ended', onEnded);
playerRef.current.addEventListener('error', onError);
playerRef.current.addEventListener('fullscreenchange', onFullscreenChange);
playerRef.current.addEventListener('scalechange', onScaleChange);
playerRef.current.addEventListener('mutechange', onMuteChange);
 
// See below for difference between `seeked` and `timeupdate`
playerRef.current.addEventListener('seeked', onSeeked);
playerRef.current.addEventListener('timeupdate', onTimeupdate);
 
return () => {
// Make sure to clean up event listeners
if (playerRef.current) {
playerRef.current.removeEventListener('play', onPlay);
playerRef.current.removeEventListener('ratechange', onRateChange);
playerRef.current.removeEventListener('volumechange', onVolumeChange);
playerRef.current.removeEventListener('pause', onPause);
playerRef.current.removeEventListener('ended', onEnded);
playerRef.current.removeEventListener('error', onError);
playerRef.current.removeEventListener(
'fullscreenchange',
onFullscreenChange,
);
playerRef.current.removeEventListener('scalechange', onScaleChange);
playerRef.current.removeEventListener('mutechange', onMuteChange);
playerRef.current.removeEventListener('seeked', onSeeked);
playerRef.current.removeEventListener('timeupdate', onTimeupdate);
}
};
}, []);

seeked​

当用户使用播放进度条更改时间位置或使用 seek() 时触发。您可以通过从 e.detail.frame 中读取来获取当前帧。

tsx
playerRef.current.addEventListener('seeked', (e) => {
console.log('seeked to ' + e.detail.frame); // seeked to 120
});
tsx
playerRef.current.addEventListener('seeked', (e) => {
console.log('seeked to ' + e.detail.frame); // seeked to 120
});

此事件在每个单独的帧更新时触发。如果过多的重新渲染导致减速,请改用 timeupdate 事件。

此事件仅在搜索期间触发。如果您还想在播放期间获取时间更新,请改用 frameupdate。

ended​

当视频结束并且循环已禁用时触发。

play​

当视频开始播放或从暂停中恢复时触发。

ratechange​

当 playbackRate 发生更改时触发。

scalechangev3.3.86​

当 scale 发生更改时触发。也可以通过 getScale() 返回。

volumechangev3.3.86​

当音量发生更改时触发。也可以通过 getVolume() 返回。

pause​

当视频暂停或结束时触发。

timeupdate​

当视频播放时定期更新时间。与 seeked 事件不同,帧会被跳过,并且事件被节流,最多每 250 毫秒触发几次。

tsx
playerRef.current.addEventListener('timeupdate', (e) => {
console.log('current frame is ' + e.detail.frame); // current frame is 120
});
tsx
playerRef.current.addEventListener('timeupdate', (e) => {
console.log('current frame is ' + e.detail.frame); // current frame is 120
});

如果您只想在搜索期间获取时间更新,请改用 seeked 事件。

如果您需要每个单独帧的更新,请改用 frameupdate 事件。

frameupdatev3.2.27​

在当前时间更改时触发,无论是播放还是搜索。

tsx
playerRef.current.addEventListener('frameupdate', (e) => {
console.log('current frame is ' + e.detail.frame); // current frame is 120
});
tsx
playerRef.current.addEventListener('frameupdate', (e) => {
console.log('current frame is ' + e.detail.frame); // current frame is 120
});

如果您只想在搜索期间获取时间更新,请改用 seeked 事件。

如果您只需要定期更新(最多每 250 毫秒),请改用 timeupdate 事件。

fullscreenchangev3.2.0​

当播放器进入或退出全屏模式时触发。通过读取 e.detail.isFullscreen 或调用 playerRef.isFullscreen(),您可以确定播放器当前是否处于全屏模式。

tsx
playerRef.current.addEventListener('fullscreenchange', (e) => {
console.log('is fullscreen' + e.detail.isFullscreen); // is fullscreen true
});
tsx
playerRef.current.addEventListener('fullscreenchange', (e) => {
console.log('is fullscreen' + e.detail.isFullscreen); // is fullscreen true
});

mutechangev3.3.98​

当播放器的音频静音或取消静音时触发。也可以通过 isMuted() 返回。

tsx
playerRef.current.addEventListener('mutechange', (e) => {
console.log('is mute' + e.detail.isMuted); // is mute true
});
tsx
playerRef.current.addEventListener('mutechange', (e) => {
console.log('is mute' + e.detail.isMuted); // is mute true
});

error​

当视频发生错误或未捕获的异常时触发。

您可以通过读取 e.detail.error 值获取错误:

tsx
ref.current?.addEventListener('error', (e) => {
console.log('error ', e.detail.error); // error [Error: undefined is not a function]
});
tsx
ref.current?.addEventListener('error', (e) => {
console.log('error ', e.detail.error); // error [Error: undefined is not a function]
});

waitingv4.0.111​

当播放器进入本机缓冲状态时触发。

在这里阅读如何最佳实现状态管理。

resumev4.0.111​

当播放器退出本机缓冲状态时触发。

在这里阅读如何最佳实现状态管理。

处理错误​

由于视频是用 React 编写的,它们容易崩溃。 当视频抛出异常时,您可以使用 error 事件 处理错误。 视频将卸载并显示错误 UI,但宿主应用程序(嵌入播放器的 React 应用程序)不会崩溃。 您需要处理错误并重新挂载视频(例如通过在 React 中更改 key 属性)。

此功能使用错误边界实现,因此只会捕获渲染函数中的错误。事件处理程序和异步代码中的错误不会被报告,也不会导致视频卸载。

您可以自定义视频崩溃时显示的错误消息:

tsx
const MyApp: React.FC = () => {
// `ErrorFallback` type can be imported from "@remotion/player"
const errorFallback: ErrorFallback = useCallback(({error}) => {
return (
<AbsoluteFill
style={{
backgroundColor: 'yellow',
justifyContent: 'center',
alignItems: 'center',
}}
>
Sorry about this! An error occurred: {error.message}
</AbsoluteFill>
);
}, []);
 
return (
<Player
fps={30}
component={Component}
durationInFrames={100}
compositionWidth={1080}
compositionHeight={1080}
errorFallback={errorFallback}
/>
);
};
tsx
const MyApp: React.FC = () => {
// `ErrorFallback` type can be imported from "@remotion/player"
const errorFallback: ErrorFallback = useCallback(({error}) => {
return (
<AbsoluteFill
style={{
backgroundColor: 'yellow',
justifyContent: 'center',
alignItems: 'center',
}}
>
Sorry about this! An error occurred: {error.message}
</AbsoluteFill>
);
}, []);
 
return (
<Player
fps={30}
component={Component}
durationInFrames={100}
compositionWidth={1080}
compositionHeight={1080}
errorFallback={errorFallback}
/>
);
};

另请参阅​

I'm ready to translate the Markdown content into Chinese. Please go ahead and paste the content for translation.