{"record":{"id":"39527050fff6c993","repo":"remotion-dev/remotion","slug":"getaudiodata-is-only-available-in-the-browser","errorCode":null,"errorMessage":"getAudioData() is only available in the browser.","messagePattern":"getAudioData\\(\\) is only available in the browser\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/media-utils/src/get-audio-data.ts","lineNumber":24,"sourceCode":"const metadataCache: {[key: string]: MediaUtilsAudioData} = {};\n\nconst limit = pLimit(3);\n\ntype Options = {\n\tsampleRate?: number;\n\trequestInit?: RequestInit;\n};\n\nconst fn = async (\n\tsrc: string,\n\toptions?: Options,\n): Promise<MediaUtilsAudioData> => {\n\tif (metadataCache[src]) {\n\t\treturn metadataCache[src];\n\t}\n\n\tif (typeof document === 'undefined') {\n\t\tthrow new Error('getAudioData() is only available in the browser.');\n\t}\n\n\tconst audioContext = new AudioContext({\n\t\tsampleRate: options?.sampleRate ?? 48000,\n\t});\n\n\tconst response = await fetchWithCorsCatch(src, options?.requestInit);\n\tif (!response.ok) {\n\t\tthrow new Error(\n\t\t\t`Failed to fetch audio data from ${src}: ${response.status} ${response.statusText}`,\n\t\t);\n\t}\n\n\tconst arrayBuffer = await response.arrayBuffer();\n\n\tconst wave = await audioContext.decodeAudioData(arrayBuffer);\n\n\tconst channelWaveforms = new Array(wave.numberOfChannels)","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-utils/src/get-audio-data.ts#L6-L42","documentation":"Thrown by getAudioData() when the global `document` is undefined (line 23). The function needs a real browser to create an AudioContext and run fetch().decodeAudioData(), so it refuses to run in Node, SSR, or any non-DOM environment. The guard fires before any audio work happens, so the error is purely about where the call executed.","triggerScenarios":"Calling getAudioData(src) from a Node script, a server-side React render (Next.js getStaticProps, Remix loader), Jest/Node tests without jsdom, or any module-eval that runs the function at import time on the server.","commonSituations":"Importing @remotion/media-utils into a Next.js app and calling getAudioData() in a server component; running unit tests under Node without a DOM polyfill; server-side pre-rendering that tries to compute audio waveforms; calling it inside getStaticProps/getServerSideProps.","solutions":["Only call getAudioData() inside Remotion components (which render in a Chromium browser) or client-only code guarded by typeof window !== 'undefined'.","If you need audio metadata server-side, switch to Mediabunny's metadata API (see docs/mediabunny/metadata) which is not DOM-bound.","In tests, configure jsdom/happy-dom or run the test in the Remotion testbed browser; do not run getAudioData under plain Node.","For Next.js/Remix, mark the calling component 'use client' or move the call into a useEffect so it only runs after hydration in the browser."],"exampleFix":"// before (runs on server, throws)\nimport {getAudioData} from '@remotion/media-utils';\nexport async function getStaticProps() {\n  const data = await getAudioData('/song.mp3');\n  return {props: {data}};\n}\n\n// after (client-only)\nimport {useAudioData} from '@remotion/media-utils';\nexport default function Player() {\n  const data = useAudioData(staticFile('song.mp3'));\n  return <Audio src={staticFile('song.mp3')} />;\n}","handlingStrategy":"validation","validationCode":"// Browser-environment guard before calling the DOM-dependent helper\nimport {getAudioData} from '@remotion/media-utils';\n\nasync function safeGetAudioData(src: string) {\n  if (typeof document === 'undefined' || typeof window === 'undefined') {\n    // skip server-side; only run in a real browser\n    return null;\n  }\n  return getAudioData(src);\n}","typeGuard":"const hasBrowserAudio = (): boolean =>\n  typeof document !== 'undefined' &&\n  typeof window !== 'undefined' &&\n  typeof window.AudioContext !== 'undefined';","tryCatchPattern":"try {\n  const data = await getAudioData(src);\n} catch (err) {\n  if ((err as Error).message.includes('only available in the browser')) {\n    // SSR path: skip or compute metadata server-side via Mediabunny\n  } else {\n    throw err;\n  }\n}","preventionTips":["Never import-and-call @remotion/media-utils DOM helpers at module top level; call inside React components or effects.","Keep audio-data fetching inside Remotion compositions (which always run in Chromium) rather than in server code.","If metadata is needed server-side, use Mediabunny's metadata API or ffprobe instead of these DOM helpers.","Add typeof document !== 'undefined' guards around any call invoked from isomorphic code."],"tags":["browser-only","ssr","dom","audio","environment"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}