Skip to content

Commit

Permalink
@remotion/renderer: Handle ERR_TIMED_OUT when offthreadvideo images…
Browse files Browse the repository at this point in the history
… take too long
  • Loading branch information
JonnyBurger committed Apr 18, 2024
1 parent 4b252da commit 0172d36
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 8 deletions.
2 changes: 2 additions & 0 deletions packages/renderer/src/browser/BrowserPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,14 @@ export const enum PageEmittedEvents {
Console = 'console',
Error = 'error',
Disposed = 'disposed',
OffthreadVideoFailure = 'img-fail',
}

interface PageEventObject {
console: ConsoleMessage;
error: Error;
disposed: undefined;
['img-fail']: undefined;
}

export class Page extends EventEmitter {
Expand Down
12 changes: 10 additions & 2 deletions packages/renderer/src/browser/FrameManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import type {LogLevel} from '../log-level';
import {assert} from './assert';
import type {Page} from './BrowserPage';
import {PageEmittedEvents, type Page} from './BrowserPage';
import type {CDPSession} from './Connection';
import {Connection} from './Connection';
import type {
Expand Down Expand Up @@ -83,7 +83,15 @@ export class FrameManager extends EventEmitter {
super();
this.#client = client;
this.#page = page;
this.#networkManager = new NetworkManager(client, this, indent, logLevel);
this.#networkManager = new NetworkManager(
client,
this,
indent,
logLevel,
() => {
page.emit(PageEmittedEvents.OffthreadVideoFailure);
},
);
this.setupEventListeners(this.#client);
}

Expand Down
10 changes: 10 additions & 0 deletions packages/renderer/src/browser/NetworkManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ export class NetworkManager extends EventEmitter {
#networkEventManager = new NetworkEventManager();
#indent: boolean;
#logLevel: LogLevel;
#onOffthreadImageFail: () => void;
constructor(
client: CDPSession,
frameManager: FrameManager,
indent: boolean,
logLevel: LogLevel,
onOffthreadImageFail: () => void,
) {
super();
this.#client = client;
Expand Down Expand Up @@ -89,6 +91,7 @@ export class NetworkManager extends EventEmitter {
'Network.responseReceivedExtraInfo',
this.#onResponseReceivedExtraInfo.bind(this),
);
this.#onOffthreadImageFail = onOffthreadImageFail;
}

async initialize(): Promise<void> {
Expand Down Expand Up @@ -346,6 +349,13 @@ export class NetworkManager extends EventEmitter {
}

if (!event.canceled) {
if (
request._url?.includes('/proxy') &&
event.errorText === 'net::ERR_TIMED_OUT'
) {
this.#onOffthreadImageFail();
}

Log.warn(
{indent: this.#indent, logLevel: this.#logLevel},
`Browser failed to load ${request._url}: ${event.errorText}`,
Expand Down
13 changes: 9 additions & 4 deletions packages/renderer/src/render-frames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -575,9 +575,10 @@ const innerRenderFrames = async ({
]);
} catch (err) {
const isTargetClosedError = isTargetClosedErr(err as Error);
const shouldRetryError = (err as Error).stack?.includes(
NoReactInternals.DELAY_RENDER_RETRY_TOKEN,
);
const shouldRetryError =
(err as Error).stack?.includes(
NoReactInternals.DELAY_RENDER_RETRY_TOKEN,
) || (err as Error).message.includes('Offthread timed out');

if (isUserCancelledRender(err) && !shouldRetryError) {
throw err;
Expand Down Expand Up @@ -611,7 +612,11 @@ const innerRenderFrames = async ({
{indent, logLevel},
`delayRender() timed out while rendering frame ${frame}: ${(err as Error).message}`,
);
const actualRetriesLeft = getRetriesLeftFromError(err as Error);
const actualRetriesLeft = (err as Error).message.includes(
'Offthread timed out',
)
? 1
: getRetriesLeftFromError(err as Error);

return renderFrameAndRetryTargetClose({
frame,
Expand Down
24 changes: 22 additions & 2 deletions packages/renderer/src/seek-to-frame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,33 @@ export const waitForReady = ({

return Promise.race([
new Promise((_, reject) => {
page.on(PageEmittedEvents.Disposed, () => {
const onDispose = () => {
reject(new Error('Target closed (page disposed)'));
};

page.on(PageEmittedEvents.Disposed, onDispose);
cleanups.push(() => {
page.off(PageEmittedEvents.Disposed, onDispose);
});
}),
new Promise((_, reject) => {
const onImgFailure = () => {
reject(new Error('Offthread timed out'));
};

page.on(PageEmittedEvents.OffthreadVideoFailure, onImgFailure);
cleanups.push(() => {
page.off(PageEmittedEvents.OffthreadVideoFailure, onImgFailure);
});
}),
new Promise((_, reject) => {
page.browser.on(BrowserEmittedEvents.ClosedSilent, () => {
const onClosedSilent = () => {
reject(new Error('Target closed'));
};

page.browser.on(BrowserEmittedEvents.ClosedSilent, onClosedSilent);
cleanups.push(() => {
page.browser.off(BrowserEmittedEvents.ClosedSilent, onClosedSilent);
});
}),
waitForReadyProm,
Expand Down

0 comments on commit 0172d36

Please sign in to comment.