Implementing Flutter WebRTC client and server



Video chat has become a common form of communication, made popular by likes of Face Time, WhatsApp and Google Duo.  What if you need to implement your own video chat app?  This is where WebRTC comes in.  In this blog post I will cover how I went about implementing Android and iOS client using flutter-webrtc-demo and WebRTC servers using flutter-webrtc-server and coturn.  I will explain each in more detail later; but first I will explain what Flutter and WebRTC are.

What is Flutter?

Flutter is a mobile app framework based on Dart, a language developed by Google.  Flutter is a framework not unlike React-Native, whose purpose is to simplify app development for iOS and Android even web. Just as with React-Native, Flutter apps, written in Dart, can be build for iOS, Android or for the web browser without having to rewrite the code.  The “old-fashion” way the developers would have to write in Java/Kotlin for Android apps, and Objective-C/Swift for iOS apps, not to mention having to use different layout tools for UI.  In React-Native, layout is done using XML separately from the program logic written in JavaScript. On the other hand, Flutter together with lets developers create both UI layout and program logic with Dart.

Flutter supports native implementation as plugins through a thriving developer community on where one can find contributed plugins for just about every kind of use, ranging from controlling devices on the phone, to integrating online payment. For WebRTC, the most popular plugin is flutter-webrtc-demo and its related server project, flutter-webrtc-server.

What is WebRTC?

WebRTC is an open source real-time video chat framework that uses two types of servers for signaling and media relay, ultimately enabling devices behind separate LAN to find and communicate with one another.  The problem is that two devices in different LAN can only see their local IP addresses, and cannot communicate with one another even if exchanging their local IP addresses.  What they must exchange is their Internet addresses, or public addresses.  In WebRTC, a STUN server on the Internet can exchange the public addresses of devices connecting to it, subsequently enabling devices behind LANs to communicate with each other. If a direct connection cannot be found due to firewalls between the two devices, then information is relayed through the TURN server.  For production WebRTC, signaling, STUN and TURN functions are needed.

Flutter WebRTC Client

One of the more “established” WebRTC project in the Flutter community is the flutter-webrtc-demo project.  It builds iOS and Android clients using the flutter-webrtc plugin.  To build this code requires familiarity with Flutter development, a topic deserving a blog post of its own, therefore will not be covered here.

To run flutter-webrtc-demo, simply plugin your iOS or Android phone and run the following:

   $ git clone
   $ cd flutter-webrtc-demo
   $ flutter run  

As-is flutter-webrtc-demo only works over devices on the same LAN.  To make it work with devices on different LAN one will need to point the app to a TURN server.  To do this one will have to modify this part of signaling.dart this way:

   _iceServers = {
      'iceServers': [
            'url': 'turn:YOUR_TURN_SERVER_ADDRESS:3478',
            'credential': YOUR_COTURN_PASSWORD


Flutter WebRTC Server

To implement the WebRTC STUN and TURN servers, I created two Ubuntu 18.04 EC2 instances: one for running flutter-webrtc-server for signaling, which I will refer to as signaling server; and one for running coturn, a server with both STUN and TURN capability.

On the signaling server, first install Go by following this blog post, then do the following:

   $ git clone
   $ cd flutter-webrtc-server
   $ make
   $ ./bin/server-linux-amd64 &

This will launch the signaling server daemon.  However, the default configuration connects to a flutter-webrtc-server implementation of TURN server, which does not work.  To make it work, you will have to edit the config.ini to look like this:



The flutter-webrtc-demo project performs signaling between the devices using port 8060 of the signaling server, but connects to ‘coturn’ for ICE server ( STUN+TURN ).

To install ‘coturn’, on the EC2 instance for TURN server, follow this blog post configuring for long-term credential.  If all goes well, you will get this — Android phone running on LAN, iOS phone running on 4G/LTE.