delayRender() 和 continueRender()
通过调用 delayRender(),您在表示一个帧不应立即渲染,而应等待异步任务完成。
如果您想在渲染之前调用 API 来获取数据,则此方法很有用。
delayRender() 返回一个句柄。一旦您获取了数据或完成了异步任务,应调用 continueRender(handle),以通知 Remotion 您现在已准备好进行渲染。
示例
tsximport {useCallback ,useEffect ,useState } from "react";import {continueRender ,delayRender } from "remotion";export constMyVideo = () => {const [data ,setData ] =useState (null);const [handle ] =useState (() =>delayRender ());constfetchData =useCallback (async () => {constresponse = awaitfetch ("http://example.com/api");constjson = awaitresponse .json ();setData (json );continueRender (handle );}, []);useEffect (() => {fetchData ();}, []);return (<div >{data ? (<div >This video has data from an API! {JSON .stringify (data )}</div >) : null}</div >);};
tsximport {useCallback ,useEffect ,useState } from "react";import {continueRender ,delayRender } from "remotion";export constMyVideo = () => {const [data ,setData ] =useState (null);const [handle ] =useState (() =>delayRender ());constfetchData =useCallback (async () => {constresponse = awaitfetch ("http://example.com/api");constjson = awaitresponse .json ();setData (json );continueRender (handle );}, []);useEffect (() => {fetchData ();}, []);return (<div >{data ? (<div >This video has data from an API! {JSON .stringify (data )}</div >) : null}</div >);};
超时
您需要在页面加载后的 30 秒内调用 continueRender()。这是 puppeteer 的默认超时时间,如果您忘记调用 continueRender(),它将抛出异常。您可以自定义超时时间。
如果在超时帧内未调用 continueRender(),渲染将失败,并显示类似于以下内容的异常:
A delayRender() was called but not cleared after 28000ms. See https://remotion.dev/docs/timeout for help. The delayRender was called
A delayRender() was called but not cleared after 28000ms. See https://remotion.dev/docs/timeout for help. The delayRender was called
请查看超时页面以解决超时问题。
添加标签v2.6.13
如果遇到超时问题并且不知道其来源,可以将标签作为参数添加:
tsxdelayRender ("Fetching data from API...");
tsxdelayRender ("Fetching data from API...");
如果调用超时,错误消息中将引用该标签:
Uncaught Error: A delayRender() "Fetching data from API..." was called but not cleared after 28000ms. See https://remotion.dev/docs/timeout for help. The delayRender was called
Uncaught Error: A delayRender() "Fetching data from API..." was called but not cleared after 28000ms. See https://remotion.dev/docs/timeout for help. The delayRender was called
并发
用于渲染的是多个页面,因此可以多次调用 delayRender() 进行渲染。如果正在进行 API 请求,可以通过缓存请求来加快渲染速度并避免速率限制,例如通过将数据存储在 localStorage 中。
多次调用
您可以多次调用 delayRender()。只要至少存在一个阻塞句柄且尚未通过 continueRender() 清除,渲染将被阻塞。
tsximport {useEffect ,useState } from "react";import {continueRender ,delayRender } from "remotion";constMyComp :React .FC = () => {const [handle1 ] =useState (() =>delayRender ());const [handle2 ] =useState (() =>delayRender ());useEffect (() => {// You need to clear all handles before the render continuescontinueRender (handle1 );continueRender (handle2 );}, []);return null;};
tsximport {useEffect ,useState } from "react";import {continueRender ,delayRender } from "remotion";constMyComp :React .FC = () => {const [handle1 ] =useState (() =>delayRender ());const [handle2 ] =useState (() =>delayRender ());useEffect (() => {// You need to clear all handles before the render continuescontinueRender (handle1 );continueRender (handle2 );}, []);return null;};
封装
您应该将 delayRender() 调用放在组件内部,而不是将其放在顶层语句中,以避免在渲染不同组合时阻塞渲染。此外,在下面的示例中,调用被包裹在 useState() 中,以避免在组件重新渲染时创建多个阻塞调用。
❌ 不要这样做tsximport {useEffect } from "react";import {continueRender ,delayRender } from "remotion";// Don't call a delayRender() call outside a component -// it will block the render if a different composition is rendered// as well as block the fetching of the list of compositions.consthandle =delayRender ();constMyComp :React .FC = () => {useEffect (() => {continueRender (handle );}, []);return null;};
❌ 不要这样做tsximport {useEffect } from "react";import {continueRender ,delayRender } from "remotion";// Don't call a delayRender() call outside a component -// it will block the render if a different composition is rendered// as well as block the fetching of the list of compositions.consthandle =delayRender ();constMyComp :React .FC = () => {useEffect (() => {continueRender (handle );}, []);return null;};
出现错误时v3.3.44
如果您的代码未能执行异步操作并且您希望取消渲染,您可以调用带有错误消息的 cancelRender()。这将自动取消所有 delayRender() 调用,以避免进一步延迟渲染。
MyComposition.tsxtsximportReact , {useEffect ,useState } from "react";import {cancelRender ,continueRender ,delayRender } from "remotion";export constMyComp :React .FC = () => {const [handle ] =useState (() =>delayRender ("Fetching data..."));useEffect (() => {fetch ("https://example.com").then (() => {continueRender (handle );}).catch ((err ) =>cancelRender (err ));}, []);return null;};
MyComposition.tsxtsximportReact , {useEffect ,useState } from "react";import {cancelRender ,continueRender ,delayRender } from "remotion";export constMyComp :React .FC = () => {const [handle ] =useState (() =>delayRender ("Fetching data..."));useEffect (() => {fetch ("https://example.com").then (() => {continueRender (handle );}).catch ((err ) =>cancelRender (err ));}, []);return null;};
重试v4.0.140
如果某个操作不稳定(例如,从 CDN 加载资源有时会出现 5xx 错误),您可以传递一个带有 retries 值的对象作为第二个参数。
如果 delayRender() 调用在超时内未清除,则整个浏览器选项卡将被关闭,并且将从头开始重试帧。
重试 delayRender()tsximport {delayRender } from "remotion";delayRender ("Loading asset...", {retries : 1, // default: 0});
重试 delayRender()tsximport {delayRender } from "remotion";delayRender ("Loading asset...", {retries : 1, // default: 0});
<Img>、<Audio>、<Video> 和 <IFrame> 标签支持一个 delayRenderRetries 属性,用于控制这些组件进行的 delayRender() 调用的 retries 值。
修改超时时间v4.0.140
除了可以设置的全局超时时间,超时时间可以在每个 delayRender() 级别上进行修改。
修改 delayRender() 的超时时间tsximport {delayRender } from "remotion";delayRender ("Loading asset...", {timeoutInMilliseconds : 7000,});
修改 delayRender() 的超时时间tsximport {delayRender } from "remotion";delayRender ("Loading asset...", {timeoutInMilliseconds : 7000,});
<Img>、<Audio>、<Video> 和 <IFrame> 标签支持一个 delayRenderTimeoutInMilliseconds 属性,用于控制这些组件进行的 delayRender() 调用的 timeoutInMilliseconds 值。```
与 useBufferState().delayPlayback() 的区别
useBufferState() 是一个不同的 API,允许在 Studio 和 Player 中暂停播放。
如果您正在加载数据,您可能希望在渲染过程中延迟组件的截图,并在预览期间启动缓冲状态,在这种情况下,您需要同时使用这两个 API。
同时使用 delayRender() 和 delayPlayback()tsximportReact 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()tsximportReact 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 <></>;};