WebRTC is a browser technology by default — but IoT and embedded devices rarely have a browser to run it in, and even when they do, the browser is the wrong place for real-time video on constrained hardware. To run WebRTC natively on a camera, a gateway, or an industrial controller, you compile libwebrtc — the same C++ engine that lives inside Chrome — directly for ARM. Do it right and you get real-time audio and video on a low-power ARM CPU with a fraction of the overhead. Do it wrong and you lose days to a toolchain that fails quietly. This guide walks the full build to compile libwebrtc for ARM (both ARM32 and ARM64), then covers the flags and gotchas that the official docs leave out.
Why compile libwebrtc natively instead of using the browser
On a desktop, WebRTC in the browser is fine. On embedded and IoT hardware, three things change. There is often no browser at all — a headless camera or gateway has no Chrome to host a WebRTC session. Resources are tight — a browser carries enormous overhead you can’t spare on a device measured in hundreds of megabytes of RAM. And efficiency is the product — lower CPU means lower power, lower heat, and longer life in the field.
Compiling libwebrtc natively gives you the real-time stack — capture, encode, transport, the peer connection — as a C++ library you link into your own application, with none of the browser wrapped around it. The result is lower latency, tighter control over resources, and a build you can tune for the exact SoC you’re shipping. (For the wider picture of how these media flows are routed once they leave the device, see our explainer on what an SFU is.)
Before the build itself, a few things will save you a wasted afternoon.
Before you start: prerequisites
The libwebrtc checkout is large — budget 25–30 GB of free disk and as much RAM as you can give the compile; linking is memory-hungry. Decide up front whether you’re building natively on the ARM device or cross-compiling from an x86 Linux machine. Cross-compiling on a fast x86 host is almost always the right call — compiling the full engine on the target board itself can take hours or fail on memory.
One decision matters more than any other: pin a version. The fetch webrtc command pulls the tip of tree, which breaks often. For anything you intend to ship, check out a stable milestone branch (branch-heads/XXXX) instead, so your build is reproducible and not at the mercy of whatever landed in the tree that morning. With that settled, here’s the build.
Steps to Compile LibWebRTC for ARM
1. Set Up the Build Environment
Start with an Ubuntu environment — either on the ARM device directly, or on an x86 machine if you’re cross-compiling. Install the core dependencies:
sudo apt-get update
sudo apt-get install build-essential python git
2. Fetch the LibWebRTC Source Code
Clone depot_tools, Google’s toolset for managing the source, and put it on your PATH:
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH="$PATH:/path_to_depot_tools"
Then fetch the source and sync its dependencies:
fetch --nohooks webrtc
cd src
gclient sync
This is the step to pin to a milestone branch rather than tip-of-tree if you’re building for production, as noted above.
3. Explore Available GN Build Options
Before generating the build, list every configurable option so you can tune the build for your target:
gn args out/Default --list
4. Set Up GN Configuration
Generate the build files for your target architecture. For ARM32:
For ARM32:
gn gen out/arm32 --args='target_os="linux" target_cpu="arm" is_debug=false is_clang=true use_custom_libcxx=false'
For ARM64:
gn gen out/arm64 --args='target_os="linux" target_cpu="arm64" is_debug=false is_clang=true use_custom_libcxx=false'
Selecting the correct target_cpu (either arm for ARM32 or arm64 for ARM64) is crucial for optimizing the build for your IoT or embedded device.
5. Compile the Code
Once the GN configuration is set, you can proceed to compile the code using Ninja.
For ARM32:
ninja -C out/arm32
For ARM64:
ninja -C out/arm64
The compilation process may take some time, depending on your system’s hardware capabilities.
6. Deploy and Test
Copy the compiled binaries to your target ARM device and test thoroughly. Don’t just check that it runs — verify the performance you compiled for actually materialized: CPU under load, that NEON acceleration is engaged, and that a real call survives a degrading network. A build that “works” on the bench can still fall over on the device.
The build gotchas nobody warns you about
The commands above get you a build. These are the things that decide whether it’s a build you can actually ship.
is_clang=true is mandatory on ARM. This flag makes the build use the Clang that libwebrtc ships with, which is required to compile the NEON flags in the ARM architecture that accelerate video rendering. The default GCC on Ubuntu can’t compile these flags — it complains about NEON and stops. Use the bundled Clang, not the system GCC.
use_custom_libcxx=false keeps your ABI sane. By default libwebrtc links its own bundled libc++. If your application is built against the system C++ standard library, that mismatch produces link errors and subtle runtime failures when you integrate the library. Setting this to false builds against the system libc++ so the library and your app agree on one ABI.
H.264 needs extra flags. Many embedded pipelines rely on hardware H.264, but libwebrtc ships without proprietary codecs enabled. To include H.264 you need to build with the proprietary-codec and FFmpeg flags turned on — broadly, rtc_use_h264=true, proprietary_codecs=true, and ffmpeg_branding="Chrome". If your device encodes or decodes H.264 in hardware, decide this before you build, not after.
Slim the binary down. A default build is large. For a device, a static library with the fat trimmed off is easier to ship — is_component_build=false for a single static lib, symbol_level=0 to drop debug symbols, and rtc_include_tests=false to skip building the test suite you’ll never run on-device. Each one cuts size and build time.
Mind the cross-compile sysroot. When you cross-compile from x86, the build needs a sysroot matching your target’s architecture and libc. A mismatched or missing sysroot is one of the most common reasons a cross-build fails late, after you’ve already waited through most of it.
None of these are in the quick-start. All of them are the difference between a demo binary and one that ships.
What we learned building this for real
We recently built a C++ video application for ARM devices — both 32-bit and 64-bit — to work with our existing cloud video infrastructure. The honest takeaway: it is not an easy task, and it needs real effort to compile and build a native C++ video application that behaves in production. The build is only the first hurdle. Integrating the library cleanly into your own application, getting the codecs your hardware actually uses, and keeping calls stable across the flaky networks embedded devices live on — that’s where the time goes. If you’re starting an embedded or IoT video project and this is new territory, expect the schedule to be dominated by the integration and tuning, not the initial compile.
The bottom line
Compiling libwebrtc for ARM is how you bring real-time WebRTC to devices that were never meant to run a browser — cameras, gateways, controllers, anything on a low-power ARM CPU. The build itself is a handful of commands. What separates a shippable result from a wasted week is the detail: pinning a milestone instead of tip-of-tree, using Clang for NEON, matching your libc++ ABI, enabling the codecs your hardware needs, and testing on the real device under real network conditions. Get those right and native WebRTC on ARM is genuinely a different class of efficiency than anything browser-based.
Building embedded or IoT video?
If you have an IoT or embedded video conferencing or streaming use case and aren’t sure where to start, we’ve done this — native C++ WebRTC on 32-bit and 64-bit ARM, wired into cloud video infrastructure. Reach out at hello@samvyo.com, or use the demo link on this page to talk through your use case with one of our engineers.
Frequently Asked Questions
Can you run WebRTC on ARM and embedded devices?
Yes. WebRTC isn’t limited to browsers — you can compile libwebrtc, the C++ engine inside Chrome, natively for ARM and link it into your own application. That lets a camera, gateway, or other embedded device run real-time audio and video without a browser and with far less overhead.
Do you need a browser to use WebRTC on IoT devices?
No. A browser is one way to run WebRTC, not the only way. On IoT and embedded hardware you compile libwebrtc natively and run it as part of a C++ application, which is both possible on headless devices and far more efficient than hosting a browser.
Why do you need is_clang=true to compile libwebrtc for ARM?
Because the ARM build relies on NEON flags for video acceleration, and the default GCC on Ubuntu can’t compile them — it errors on the NEON flags. Setting is_clang=true uses the Clang that libwebrtc bundles, which compiles them correctly.
How do you get H.264 support in a libwebrtc ARM build?
H.264 is a proprietary codec and is off by default. You enable it at build time with the proprietary-codec and FFmpeg flags — broadly rtc_use_h264=true, proprietary_codecs=true, and ffmpeg_branding="Chrome". This matters most when your device has hardware H.264 encode or decode.
How long does it take to compile libwebrtc for ARM?
It varies with your hardware, but a full build is heavy — potentially hours if you compile on the ARM device itself. Cross-compiling from a fast x86 machine is much quicker and is the recommended approach. Budget 25–30 GB of disk and plenty of RAM either way.
Can Samvyo help with embedded or IoT WebRTC?
Yes. Alongside its SFU-based cloud video platform and SDKs, Samvyo has built native C++ WebRTC clients for ARM devices that connect back to that infrastructure. For teams that need real-time video on embedded hardware without absorbing the full build-and-integrate effort themselves, that experience is available as part of the platform.