How to use Twilio for video calling in swift.
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 UIKitimport TwilioCommonimport SwiftyJSONclass 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: TWCLocalMediaDelegateextension VideoCallViewController: TWCLocalMediaDelegate { func localMedia(media: TWCLocalMedia, didAddVideoTrack videoTrack: TWCVideoTrack) { //print("added media track") }}// MARK: TWCVideoTrackDelegateextension VideoCallViewController: TWCVideoTrackDelegate { func videoTrack(track: TWCVideoTrack, dimensionsDidChange dimensions: CMVideoDimensions) { print("video dimensions changed") }}// MARK: TwilioAccessManagerDelegateextension VideoCallViewController: TwilioAccessManagerDelegate { func accessManagerTokenExpired(accessManager: TwilioAccessManager!) { } func accessManager(accessManager: TwilioAccessManager!, error: NSError!) { print("Access manager error:") print(error) }}// MARK: TwilioConversationsClientDelegateextension 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: TWCConversationDelegateextension 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: TWCParticipantDelegateextension VideoCallViewController: TWCParticipantDelegate { func participant(participant: TWCParticipant, addedVideoTrack videoTrack: TWCVideoTrack) { videoTrack.attach(self.remoteMediaView) } }
Build your project and make call.