Troubleshoot Node.js Media SDK issues
Public Beta
The Video Media SDK for Node.js is currently available as a Public Beta product and the information contained in this document is subject to change. This means that some features are not yet implemented and others may be changed before the product is declared as Generally Available. Public Beta products are not covered by the Twilio Support Terms or Twilio Service Level Agreement.
The Video Media SDK for Node.js is not a US Health Insurance Portability and Accountability Act (HIPAA) Eligible Service or Payment Card Industry Data Security Standard (PCI DSS) compliant and should not be enabled in workflows that are subject to HIPAA or PCI.
On an Apple Silicon Mac with an arm64 version of Node installed, the npm install of this SDK npm install @twilio/video-node-sdk fails, returning npm error code EBADPLATFORM. To correct this error, switch to an x64 build of Node.js.
The SDK requires an x64 build of Node.js. Rosetta lets an x64 build run on Apple Silicon, but installing Rosetta doesn't change which build of Node.js you have. If your Node.js is an arm64 build, the SDK doesn't install.
To install an x64 build of Node.js on an Apple Silicon (M-series) Mac, follow these steps:
- In Terminal, install Rosetta:
/usr/sbin/softwareupdate --install-rosetta --agree-to-license
- Install an x64 build of Node.js version 24.0.0 or later. Open a shell that runs under Rosetta, and then install Node.js with nvm:
1arch -x86_64 zsh2nvm install 24
- Confirm that your Node.js install uses the
x64architecture:A successful install returnsnode -e "console.log(process.arch)"x64. If this commands returnsarm64, you're running an arm64 build:- If you have an arm64 build of Node.js 24, remove it, and then repeat steps 2 and 3:
1nvm deactivate2nvm uninstall 24
- If you have an arm64 build of Node.js 24, remove it, and then repeat steps 2 and 3:
If npm install fails with npm error code EBADPLATFORM and reports "cpu":"arm64", you're running an arm64 build of Node.js. Follow the preceding steps to switch to an x64 build.
If the SDK throws an UnsupportedPlatformError, there's no prebuilt binary for your platform or architecture. Run the SDK on Linux x86-64, or on macOS x86_64 for local development, with an x64 build of Node.js version 24.0.0 or later. If you use an Apple Silicon Mac, see SDK installation fails on Apple Silicon.
If loading the SDK throws a NativeBindingLoadError that says the prebuilt binary failed to load, check your prerequisites:
- Confirm that you're running Node.js version 24.0.0 or later:
On earlier versions, npm installs the SDK with only a warning.node --version
- On macOS, confirm that you're running macOS 26 or later:
The prebuilt binary targets macOS 26. npm can't check the operating system version, so on macOS 25 or earlier the install succeeds and the binary fails to load.sw_vers -productVersion
- On Linux, confirm that the
libX11library is installed:If the command prints nothing, the library is missing. Minimal container images, such asldconfig -p | grep libX11node:24-slim, don't include it. On Debian or Ubuntu, install it:apt-get update && apt-get install -y libx11-6 - On Linux, confirm that glibc is version 2.34 or later:
The first line of the output shows the glibc version. The SDK doesn't support Alpine or other musl-based distributions.ldd --version
If the Access Token is malformed, expired, or missing a Video grant, connect() rejects with one of the AccessToken*Error classes, such as AccessTokenInvalidError (20101) or AccessTokenExpiredError (20104). To handle it, wrap await connect() in a try...catch block, then check the following:
- Set environment variables for
TWILIO_ACCOUNT_SID,TWILIO_API_KEY, andTWILIO_API_SECRET. - Add a
VideoGrantto the token. - If the token expired, generate a new one.
If connect() rejects with TypeError: Unknown video codec: <name> or TypeError: Unknown audio codec: <name>, the SDK doesn't support a codec in your connect options. This error can appear when you reuse connect options from the JavaScript SDK, such as preferredVideoCodecs: ['H264'].
The SDK accepts the following values:
preferredVideoCodecs:'VP8'preferredAudioCodecs:'opus'and'PCMU'
Codec names are case-sensitive, so 'vp8' and 'Opus' also fail. In TypeScript, the VideoCodec and AudioCodec types catch unsupported values at compile time. To fix the error, use only the supported values or leave out the option:
1const room = await connect(token, {2name: 'my-room',3preferredVideoCodecs: ['VP8'],4preferredAudioCodecs: ['opus'],5});
To learn more, see Known issues and limitations.
If a remote participant publishes an H.264 video track, the SDK can't subscribe to it. The Room emits trackSubscriptionFailed with a MediaNoSupportedCodecError, which has error code 53404. The SDK supports VP8 video only.
To detect the failure, listen for the event:
1const { MediaNoSupportedCodecError } = require('@twilio/video-node-sdk');23room.on('trackSubscriptionFailed', (error, publication, participant) => {4if (error instanceof MediaNoSupportedCodecError) {5console.warn(`Can't subscribe to ${publication.trackName} from ${participant.identity}: unsupported codec`);6}7});
To fix the failure, set preferredVideoCodecs: ['VP8'] in the client apps that join the Room. To learn how client SDKs set codec preferences, see Managing codecs.
If your app keeps running after it leaves a Room, the Room still holds its native resources. Call room.dispose() when you finish with a Room. The disconnect() method leaves the Room but doesn't release those resources. The disconnected event is a good place to call dispose():
1room.on('disconnected', () => {2room.dispose();3});
Verify the following in your code:
- Wait for
connect()to resolve, and then push video frames. The SDK drops any video frames that you write before then. - Review the parameters you pass to the Room:
- Pass video frames in the I420 format, which uses the Y'UV color model. Each of
y,u, andvis a plane object with its owndata,stride,width, andheight. Framewidthandheightmust be even.Y: Full-resolution luminance at the full frame width and heightU: Blue-difference chrominance (Cb) at half the frame width and heightV: Red-difference chrominance (Cr) at half the frame width and height
- Set Audio frame input to 48 kHz mono
S16LEPCM.S: Use Signed positive or negative integer values.16: Store 16 bits (or two bytes) of data per audio sample.LE: Use the little-endian method to store data placing the least significant byte in the smallest memory address.PCM: Convert data using Pulse-code modulation: the raw, uncompressed audio wave data.
- Pass video frames in the I420 format, which uses the Y'UV color model. Each of
- Check the return value of
write(). It returnsfalsewhen the SDK drops a frame, andgetWriteStats().framesDroppedcounts the drops.
To inspect a Room's media and connection health beyond your own logs, use Video Insights.
If you can't resolve an issue, contact Twilio Support.