Implementing Flutter WebRTC client and server

Standard

Introduction

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 pub.dev 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 https://github.com/cloudwebrtc/flutter-webrtc-demo
   $ 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',
            'username':YOUR_COTURN_USERNAME,
            '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 https://github.com/cloudwebrtc/flutter-webrtc-server
   $ 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:

   [general]
   domain=demo.cloudwebrtc.com
   cert=configs/certs/cert.pem
   key=configs/certs/key.pem
   bind=0.0.0.0
   port=8086
   html_root=web

   [turn]
   public_ip=YOUR_TURN_SERVER_ADDRESS
   port=3478
   realm=YOUR_TURN_SERVER_REALM

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.

IMG_3696

References

5 thoughts on “Implementing Flutter WebRTC client and server

  1. omar taradeh

    I don’t know what the realm is. what should I put in the realm in ” realm=YOUR_TURN_SERVER_REALM
    “?
    another question: public IP means the IP of my network eg: “195.123.163.204”?. and internal IP means the IP of the host in that network eg: “192.168.1.5”?

  2. Daniel

    So the coturn server only allows access to one realm and through one IP? What’s the use of that? Also the co-turn install doesn’t specify which IPs to use

    • I am not sure if i understood your question. Link to co-turn installation can be found in my blog’s reference section. Usually a co-turn server sits in the cloud having a public IP address. Since it would have been your server, you specify the server’s IP address. A co-turn server can services many clients. The clients would have to know the co-turn server’s public IP address.

    • Daniel

      Hi Larry, thanks for the response. I misunderstood the coturn external IP setting. I thought it meant the external IP that can utilize the turn server instead of the external IP of the turn server since most server side apps can just grab that IP themselves. I ended up getting it to work. Thanks for the guide!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s