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

componentlazyComponent

直接传递一个 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

可选

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

doubleClickToFullscreen

可选

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

note

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

spaceKeyToPlayOrPause

可选

一个布尔属性,定义您是否可以使用空格键播放或暂停视频。如果启用,播放视频然后按空格键暂停和恢复视频。仅在controlstrue时有效。默认为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)的数字,用于指定播放器运行媒体的速度。

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

默认为 1

errorFallback

可选

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

renderLoading

可选

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

回调函数的第一个参数包含播放器呈现时的 heightwidth

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,覆盖在播放器上方。

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

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

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 键进行键盘导航 (onBlurinputRef)。

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.