Skip to content
Building an iOS Video Chat App with In-Call Statistics featured

Building an iOS Video Chat App with In-Call Statistics

By Author: Max Cobb In Developer

When you’re building a real-time engagement application, a ton of metrics need to be monitored to deliver a smooth experience to the end user. There can be many challenges when debugging a suboptimal user experience: high CPU usage, low internet bandwidth, dropped frames, and so on. The in-call statistics can be used to monitor, maintain, and improve the user experience.

In this tutorial, we’ll add in-call stats to an iOS app, using the Agora UIKit CocoaPod to simplify the process. If you’re new to the Agora SDK, you can learn how to build a project from scratch by using the quickstart blog or the short UIKit guide. We’ll look at how to access and display statistics for local and remote videos, and how to access other important call aspects, like bandwidth and CPU usage.

Prerequisites

  • An Agora developer account (see How to Get Started with Agora)
  • Xcode 12.0 or later
  • An iOS device running iOS 11.0 or later
  • A basic understanding of iOS development
  • CocoaPods

Setup

Create an iOS project in Xcode, and then install the AgoraUIKit_iOS CocoaPod. Your Podfile should look like this:

target 'Agora-Call-Stats' do
 pod 'AgoraUIKit_iOS', '~> 1.5'
end

The latest AgoraUIKit release at the time of writing is v1.5.1

Run pod init, and open the .xcworkspace file to get started.

Add authorisation for the app to use the camera and microphone. To do this, open the Info.plist file at the root of your Xcode project and add NSCameraUsageDescription and NSMicrophoneUsageDescription.

For more information on requesting authorisation for media capture, check out this article from Apple.

Setting up Agora Video Calling

As is explained in the Agora Quickstart Guide, we must initialise the Agora engine, enable video, and join a channel:

There’s a little more we need to do to display videos. With AgoraUIKit_iOS, we can utilise the AgoraSingleVideoView class, which takes care of most of the video functionality for us.

All the video feeds will be stored in videoFeeds, which is a map of [UInt: AgoraSingleVideoView], where UInt is the RTC ID associated with the user (0 for local user). Add this property to your ViewController declaration.

This method will create an instance of AgoreSingleVideoView given a user ID, set up local or remote video for that user, and store it in videoFeeds

Now we need to add the local user’s feed once we have joined the channel. And we need to catch incoming streams using the delegate method remoteVideoStateChangedOfUid:

We’ll add self.addUserVideo(with: 0) to the joinSuccess callback from the call to joinChannel.

The final step in setting up the initial video calling is organising the video feeds so we can see ourselves and the remote users. For simplicity, we will only display videos in a 2×2 grid:

Building an iOS Video Chat App with In-Call Statistics screenshot 1

Accessing In-Call Stats

We will use two delegate methods to get stats for the local and remote videos: localVideoStats and remoteVideoStats.

Your delegate extension may look like this now:

We will define updateStats soon. But first I’ll add the stats.statsViewText custom property in my sample. This property returns a few status properties as a String:

extension AgoraRtcRemoteVideoStats {
  var statsViewText: String {
    """
    Received Bitrate: \(self.receivedBitrate)
    Packet Loss Rate: \(self.packetLossRate)
    Active Time: \(self.totalActiveTime)
    Output Frame Rate: \(self.decoderOutputFrameRate)
    Frame Dimensions: \(self.width)x\(self.height)
    """
  }
}
extension AgoraRtcLocalVideoStats {
  var statsViewText: String {
    """
    Encoded Bitrate: \(self.encodedBitrate)
    Sent Target Bitrate: \(self.sentTargetBitrate)
    Packet Loss Rate: \(self.txPacketLossRate)
    Capture Frame Rate: \(self.captureFrameRate)
    Frame Dimensions: \(self.encodedFrameWidth)x\(self.encodedFrameHeight)
    """
  }
}

These are just some of the properties I have chosen to present, but there are many more. See the class references AgoraRtcLocalVideoStats and AgoraRtcRemoteVideoStats for a list of all properties.

Now for the updateStats method:

Building an iOS Video Chat App with In-Call Statistics screenshot 2

The camera feeds in the screenshot have been blurred to make the text more legible in this example.

If you want to add similar stats to your own app, you might want to display the text in different ways. For example, you may want to monitor the received bitrate value and show a small icon on a user when the value goes below a certain threshold. This would let everyone else know that there may be some issue with that remote user’s internet connection.

More Stats

A few more options for stats are offered as part of the Agora Video Streaming SDK, including local/remote audio stats and channel stats.

Channel stats can be found in the reportRtcStats delegate method, which returns a stats class AgoraChannelStats. Using this stats object, you can check for the CPU usage of your app, the total system CPU usage, the last-mile delay, the memory usage of your app, and many more properties.

Testing

You can try out the code in a prebuilt sample on GitHub:

Conclusion

That is how we can listen, monitor, and display the in-call statistics for our video experience. You can even build functions to log or react to change in these values to deliver an exceptional user experience.

Other Resources

For more information about building applications using Agora Video and Audio Streaming SDKs, take a look at the Agora Video Call Quickstart Guide and Agora API Reference.

I also invite you to join the Agora.io Developer Slack community.