How to use Twilio for video calling in swift.

Pradeep Chauhan
Jul 28, 2017 · 6 min read

What is Twilio?

Twilio is powering the future of business communications, enabling developers to embed voice, VoIP, and messaging into applications. They virtualize all infrastructure needed in a cloud-based, global environment, exposing it through the Twilio communications API platform. Applications are simple to build and scalable. Enjoy flexibility with pay-as-you go pricing, and benefit from cloud reliability.

Twilio Voice allows your applications to make and receive phone calls. Twilio SMS enables your applications to send and receive SMS messages.Twilio Client allows you to make VoIP calls from any phone, tablet, or browser and supports WebRTC.

Concepts

The Twilio API is a RESTful API that provides voice and SMS functionality for applications. Client libraries are available in multiple languages; for a list, see Twilio API Libraries.

Key aspects of the Twilio API are Twilio verbs and Twilio Markup Language (TwiML).

Twilio verbs

The API makes use of Twilio verbs; for example, the <Say> verb instructs Twilio to audibly deliver a message on a call.

The following is a list of Twilio verbs. Learn about the other verbs and capabilities via Twilio Markup Language documentation.

  • <Dial>: Connects the caller to another phone.
  • <Gather>: Collects numeric digits entered on the telephone keypad.
  • <Hangup>: Ends a call.
  • <Play>: Plays an audio file.
  • <Pause>: Waits silently for a specified number of seconds.
  • <Record>: Records the caller’s voice and returns a URL of a file that contains the recording.
  • <Redirect>: Transfers control of a call or SMS to the TwiML at a different URL.
  • <Reject>: Rejects an incoming call to your Twilio number without billing you
  • <Say>: Converts text to speech that is made on a call.
  • <Sms>: Sends an SMS message.

Create a Twilio Account

When you’re ready to get a Twilio account, sign up at Try Twilio. You can start with a free account, and upgrade your account later.

When you sign up for a Twilio account, you’ll receive an account ID and an authentication token. Both will be needed to make Twilio API calls. To prevent unauthorized access to your account, keep your authentication token secure. Your account ID and authentication token are viewable at the Twilio account page, in the fields labeled ACCOUNT SID and AUTH TOKEN, respectively.

Let’s Start…..

Create new project in xcode.

We are integrating Twilio with pod. So if you are not familiar with pod then please check this link CocoaPods.org and install cocoapod on your system else open terminal and go to your project directory and run this command $ pod init

this command will install pod file in your project directory. Now open your pod file and insert this in your pod file.

source 'https://github.com/twilio/cocoapod-specs'
use_frameworks!
target 'TwilioDemo' do
pod 'TwilioConversationsClient'
end

After save pod file go to terminal and run this command $pod install

this command will install Twilio library in your project.

Now create header file for your project and add this line

#import <TwilioConversationsClient/TwilioConversationsClient.h> in your header file.

Now Go to storyboard in drag view controller from object library to storyBoard.

We required 3 things in this view controller.

1. remote view — It will show romete view of user.

2. local view — It will show local preview.

3. Identity label — This label is indicating user conversation name.

After drawing this your view will look like this.

Create VideoCallViewController class and link with view.

Insert this on header on VideoCallViewController.swift file.

import TwilioCommon

Create variable for Video SDK components

// Video SDK components    var accessManager: TwilioAccessManager?    var client: TwilioConversationsClient?    var localMedia: TWCLocalMedia?    var camera: TWCCameraCapturer?    var conversation: TWCConversation?    var incomingInvite: TWCIncomingInvite?    var outgoingInvite: TWCOutgoingInvite?    var dimensions:CMVideoDimensions = CMVideoDimensions()    var username:String = String()

Create UI Element Outlets

// MARK: UI Element Outlets and handles
@IBOutlet weak var remoteMediaView: UIView!
@IBOutlet weak var localMediaView: UIView!
@IBOutlet weak var identityLabel: UILabel!

Add helper to determine to running on iphone or simulator.

// Helper to determine if we're running on simulator or device
struct Platform {
static let isSimulator: Bool = {
var isSim = false
#if arch(i386) || arch(x86_64)
isSim = true
#endif
return isSim
}()
}

Now we are required token to communicate with client.

Configure access token manually for testing, if desired! Create one manually in the console at https://www.twilio.com/user/account/video/dev-tools/testing-tools

Insert any client id like “Demo” and Choose your Configuration Profile and click on Generate Access Token button.

It will create access token like this.

Create access_token variable and assign this token value to access_token.

Add Twilio delegates and finally your code look like this:

import UIKit
import TwilioCommon
import SwiftyJSON
class VideoCallViewController: UIViewController {
// MARK: View Controller Members
// Configure access token manually for testing, if desired! Create one manually in the console
// at https://www.twilio.com/user/account/video/dev-tools/testing-tools
var accessToken = ""

// Configure remote URL to fetch token from
var tokenUrl = ""

// Video SDK components
var accessManager: TwilioAccessManager?
var client: TwilioConversationsClient?
var localMedia: TWCLocalMedia?
var camera: TWCCameraCapturer?
var conversation: TWCConversation?
var incomingInvite: TWCIncomingInvite?
var outgoingInvite: TWCOutgoingInvite?
var dimensions:CMVideoDimensions = CMVideoDimensions()
// MARK: UI Element Outlets and handles
var alertController: UIAlertController?
@IBOutlet weak var remoteMediaView: UIView!
@IBOutlet weak var localMediaView: UIView!
@IBOutlet weak var identityLabel: UILabel!
@IBOutlet var hangUpView: UIView!
// Helper to determine if we're running on simulator or device
struct Platform {
static let isSimulator: Bool = {
var isSim = false
#if arch(i386) || arch(x86_64)
isSim = true
#endif
return isSim
}()
}

override func viewDidLoad() {
super.viewDidLoad()
accessToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImN0eSI6InR3aWxpby1mcGE7dj0xIn0.eyJqdGkiOiJTSzJkMmUxODcyZjI1YTFkYzM3MDBjNGM5MWUyNmQ1OGFjLTE0NjU4OTk3MDAiLCJpc3MiOiJTSzJkMmUxODcyZjI1YTFkYzM3MDBjNGM5MWUyNmQ1OGFjIiwic3ViIjoiQUMyOGQ0ODA2MzI0NDQyNTEzNzhmZGYzNWYzODEwNDViMSIsImV4cCI6MTQ2NTkwMzMwMCwiZ3JhbnRzIjp7ImlkZW50aXR5IjoiYWJjIiwicnRjIjp7ImNvbmZpZ3VyYXRpb25fcHJvZmlsZV9zaWQiOiJWU2QwYWNhNTIyMjdkMThiNjFhNGMwODUxYzRmYzY5MDQwIn19fQ.WfFySUcxE_xXkVQ8f1pHqvu7IUAXNRKaFVe3uLoqoQw"
// Configure access token either from server or manually
// If the default wasn't changed, try fetching from server
if self.accessToken == "" {
// If the token wasn't configured manually, try to fetch it from server
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config, delegate: nil, delegateQueue: nil)
let url = NSURL(string: self.tokenUrl)
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "GET"

// Make HTTP request
session.dataTaskWithRequest(request, completionHandler: { data, response, error in
if (data != nil) {
// Parse result JSON
let json = JSON(data: data!)
self.accessToken = json["token"].stringValue
// Update UI and client on main thread
dispatch_async(dispatch_get_main_queue()) {
self.initializeClient()
}
} else {
print("Error fetching token :\(error)")
}
}).resume()
} else {
// If token was manually set, initialize right away
self.initializeClient()
}

// video dimension for remote view
dimensions.width = Int32(self.remoteMediaView.frame.size.height)
dimensions.height = Int32(self.remoteMediaView.frame.size.height)
}

// Once access token is set, initialize the Conversations SDK and display the identity of the
// current user
func initializeClient() {
// Set up Twilio Conversations client
self.accessManager = TwilioAccessManager(token:self.accessToken, delegate:self);
self.client = TwilioConversationsClient(accessManager: self.accessManager!, delegate: self);
self.client?.listen();

self.startPreview()

self.identityLabel.text = self.username
}

func startPreview() {
// Setup local media preview
self.localMedia = TWCLocalMedia(delegate: self)
self.camera = self.localMedia?.addCameraTrack()

if((self.camera) != nil && Platform.isSimulator != true) {
self.camera!.videoTrack?.attach(self.localMediaView)
self.camera!.videoTrack?.delegate = self;

// Start the preview.
self.camera!.startPreview();
self.localMediaView!.addSubview((self.camera!.previewView)!)
self.camera!.previewView?.frame = self.localMediaView!.bounds
self.camera!.previewView?.contentMode = .ScaleToFill
self.camera!.previewView?.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
}
}
}
// MARK: TWCLocalMediaDelegate
extension VideoCallViewController: TWCLocalMediaDelegate {
func localMedia(media: TWCLocalMedia, didAddVideoTrack videoTrack: TWCVideoTrack) {
//print("added media track")
}
}
// MARK: TWCVideoTrackDelegate
extension VideoCallViewController: TWCVideoTrackDelegate {
func videoTrack(track: TWCVideoTrack, dimensionsDidChange dimensions: CMVideoDimensions) {
print("video dimensions changed")
}
}
// MARK: TwilioAccessManagerDelegate
extension VideoCallViewController: TwilioAccessManagerDelegate {
func accessManagerTokenExpired(accessManager: TwilioAccessManager!) {

}

func accessManager(accessManager: TwilioAccessManager!, error: NSError!) {
print("Access manager error:")
print(error)
}
}
// MARK: TwilioConversationsClientDelegate
extension VideoCallViewController: TwilioConversationsClientDelegate {
func conversationsClient(conversationsClient: TwilioConversationsClient,
didFailToStartListeningWithError error: NSError) {
print("failed to start listening:")
print(error)

}

// Automatically accept any invitation
func conversationsClient(conversationsClient: TwilioConversationsClient,
didReceiveInvite invite: TWCIncomingInvite) {
//print(invite.from)
invite.acceptWithLocalMedia(self.localMedia!) { conversation, error in
self.conversation = conversation
self.conversation!.delegate = self
}
}
}
// MARK: TWCConversationDelegate
extension VideoCallViewController: TWCConversationDelegate {
func conversation(conversation: TWCConversation,
didConnectParticipant participant: TWCParticipant) {
self.navigationItem.title = participant.identity
participant.delegate = self
}

func conversation(conversation: TWCConversation,
didDisconnectParticipant participant: TWCParticipant) {
disconnectCall()

}

func conversationEnded(conversation: TWCConversation) {
self.navigationItem.title = "no call connected"
// Restart the preview.
self.startPreview()
}
}
// MARK: TWCParticipantDelegate
extension VideoCallViewController: TWCParticipantDelegate {
func participant(participant: TWCParticipant, addedVideoTrack videoTrack: TWCVideoTrack) {
videoTrack.attach(self.remoteMediaView)
}

}

Build your project and make call.

Thanks

Hope you learned something new today.

Enjoy!!

If you enjoyed reading this post, please share and recommend it so others can find it 💚💚💚💚💚💚 !!!!

You can follow me on Medium for fresh articles. Also, connect with me on LinkedIn.

If you have any comment, question, or recommendation, feel free to post them in the comment section below!

Pradeep Chauhan

Written by

Full Stack Developer

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade