remotion-dev/remotion · error · Error
getAudioDuration() is only available in the browser.
Error message
getAudioDuration() is only available in the browser.
What it means
Thrown by getAudioDurationInSeconds() (and its deprecated alias getAudioDuration) when `document` is undefined (line 14). The implementation creates a real <audio> element via document.createElement to read loadedmetadata, so it cannot run outside a DOM. Note: this API is deprecated in favor of Mediabunny's metadata API.
Source
Thrown at packages/media-utils/src/get-audio-duration-in-seconds.ts:15
/* eslint-disable @typescript-eslint/no-use-before-define */
import {onMediaError} from './media-tag-error-handling';
import {pLimit} from './p-limit';
const limit = pLimit(3);
const metadataCache: {[key: string]: number} = {};
const fn = (src: string): Promise<number> => {
if (metadataCache[src]) {
return Promise.resolve(metadataCache[src]);
}
if (typeof document === 'undefined') {
throw new Error('getAudioDuration() is only available in the browser.');
}
const audio = document.createElement('audio');
audio.src = src;
return new Promise<number>((resolve, reject) => {
const onError = () => {
onMediaError({
error: audio.error!,
src,
cleanup,
reject,
api: 'getAudioDurationInSeconds()',
});
};
const onLoadedMetadata = () => {
metadataCache[src] = audio.duration;
resolve(audio.duration);View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Call getAudioDurationInSeconds() only from inside Remotion client components or other browser code.
- For server-side or test-time duration, migrate to Mediabunny's metadata API which is not DOM-bound (this also removes the deprecation warning).
- If you must use this API in tests, set test environment to jsdom or happy-dom and ensure the <audio> element can reach the URL.
- Gate the call with typeof document !== 'undefined' to avoid invoking it during SSR.
Example fix
// before (server-side call, throws)
import {getAudioDurationInSeconds} from '@remotion/media-utils';
export async function loader() {
return {duration: await getAudioDurationInSeconds('/a.mp3')};
}
// after (browser-only via hook)
import {useAudioData} from '@remotion/media-utils';
const audio = useAudioData(staticFile('a.mp3'));
const duration = audio?.durationInSeconds; Defensive patterns
Strategy: validation
Validate before calling
import {getAudioDurationInSeconds} from '@remotion/media-utils';
async function safeGetAudioDurationInSeconds(src: string): Promise<number | null> {
if (typeof document === 'undefined') {
return null; // not in a browser; caller can fall back to ffprobe/Mediabunny
}
return getAudioDurationInSeconds(src);
} Type guard
const canUseDomAudio = (): boolean => typeof document !== 'undefined';
Try / catch
try {
const duration = await getAudioDurationInSeconds(src);
} catch (err) {
if ((err as Error).message.includes('only available in the browser')) {
// fall back to a non-DOM path (Mediabunny metadata or ffprobe)
} else {
throw err;
}
} Prevention
- Migrate new code to Mediabunny's metadata API, which works outside the DOM and removes this deprecation.
- Only call this helper inside Remotion client components.
- Guard isomorphic call sites with typeof document !== 'undefined'.
- In Node tests, configure jsdom/happy-dom or skip the test rather than calling into a missing DOM.
When it happens
Trigger: Calling getAudioDurationInSeconds() during SSR, in a Node script, in Node-based unit tests, or in a Cloudflare/Vercel edge function. Importing the module eagerly and invoking at top-level on the server.
Common situations: Server-side pre-render of a Remotion composition; Next.js server component trying to compute clip length; Jest test under Node env without jsdom; build-time data fetching that needs the duration.
Related errors
- getAudioData() is only available in the browser.
- getImageDimensions() is only available in the browser.
- getVideoMetadata() is only available in the browser.
- Tried to call an API that only works in the browser from out
- measureText() can only be called in a browser.
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/ea31265b973ba6d8.
Report an issue: GitHub.