Twilio SDKを使った音声通話アプリ開発

Twilio SDKを使った音声通話アプリ開発

はじめに

前回の記事で述べた通りに、今日はTwilio Video SDKを使用してiOS版音声通話アプリを開発する方法を説明させていただきます。

概して言えば、Twilio Videoは、リアルタイムビデオチャット機能や音声通話機能、画面共有機能などを作るための色々なサービスを提供するプラットフォームとして知られており、世界で高く評価されています。

https://www.g2.com/products/twilio/reviews

https://www.trustradius.com/products/twilio-video/reviews

この記事ではVideo APIを使用して音声通話アプリを開発してみましょう。

Twilioでのプロジェクト作成

Twilloでアカウントを登録します。

コンソールページを開きます。

こちらで「TwilioDemoChat」という名前または任意の名前のプロジェクトを作成します。

プロジェクト作成が終わったら、ウェルカムページが表示されます。

「Other」を選択し、ダッシュボードページに遷移して、プロジェクトの作成手順を完了しましょう。

後で使用できるように、アカウントSIDと認証トークンをファイルに保存しておきます。

APIキー作成

こちらで参照してください。

新しいAPIキーは、1回だけ表示されるので、慎重に保管しておいてください。

アクセストークン作成

こちらで2つの新しいアクセストークンを作成します。その理由としては、2人のユーザー(TwilioDemoChatRoomUser1およびTwilioDemoChatRoomUser2)がTwilioDemoChatRoomという同じルームに参加するケースを検証するためです。「Generate Access Token」ボタンをクリックしてアクセストークンを取得し、iOSアプリに使用するために保存しておきます。

注意事項:リリース環境では、これがサーバー側によって実施されます。サーバー側でルームに参加するユーザーにつきアクセストークンを生成します。そのアクセストークンは、Twilioサーバーに対してユーザーを認証するための短期認証です。

 

iOSでの音声通話アプリ開発

チュートリアルを参照してください。

TwilioDemoChatという新しいプロジェクトを作成します。

CocoaPods構成

プロジェクトのルートディレクトリにPodFileという空ファイルを作成し、以下のコードを入れます。

platform :ios,'11.0'
use_frameworks!

def install_pods
  pod 'TwilioVideo'
  pod 'MBProgressHUD'
end

target 'TwilioDemoChat' do
  install_pods
end

ターミナルアプリを開き、プロジェクトルートで次のコマンドを実行することでTwilioVideo SDKをインストールします。

pod install

アプリ側は音声通話のため端末のマイクロを使用するので、端末のマイクにアクセスする権限をinfo.plistファイルに追加する必要があります。

NSMicrophoneUsageDescription
このサンプルにて音声通話機能に端末のマイクロを使います。

Twilio導入

まず、ルームへの参加を処理するTwilioController.swiftコントローラーを作成します。

import UIKit
import TwilioVideo
import MBProgressHUD

let TWILIO_TEST_ROOM = "TwilioDemoChatRoom"

let TWILIO_ACCESS_TOKEN_1 = "「アクセストークン作成」で作成されたアクセストークン"
let TWILIO_ACCESS_TOKEN_2 = "「アクセストークン作成」で作成されたアクセストークン"

let kTwilioController = TwilioController.shared

public enum RoomStatus{
    case Connected
    case Disconnected
    case ParticipantConnected
    case ParticipantDisconnected
    case Error
}

public typealias RoomStatusUpdatedHandler = (RoomStatus) -> (Void)

class TwilioController: NSObject {
    static let shared = TwilioController()
    
    var room:Room? = nil
    var connected = false
    var roomStatusHandler:RoomStatusUpdatedHandler?
    
    private var localAudioTrack = LocalAudioTrack()

    //TWILIO_TEST_ROOM定数でルームへ接続を行ないます。
    func  connectToRoom(handler:RoomStatusUpdatedHandler?) {
        roomStatusHandler = handler 
        //各端末ごとにアクセストークンを変更します。
        let connectOptions = ConnectOptions(token: TWILIO_ACCESS_TOKEN_2) { (builder) in
            builder.roomName = TWILIO_TEST_ROOM
            
            //cấu hình âm thanh
            if let audioTrack = self.localAudioTrack {
                builder.audioTracks = [ audioTrack ]
            }
        }
        room = TwilioVideoSDK.connect(options: connectOptions, delegate: self)
    }
    
    func disconnectFromRoom()  {
        room?.disconnect()
    }
    
    // MARK: プライベートメソッド
    private func toastMessage(message:String){
        print("toastMessage \(message)")
        DispatchQueue.main.asyncAfter(deadline: .now() ) {
            let hud = MBProgressHUD.showAdded(to: UIApplication.shared.keyWindow!, animated: true)
            hud.mode = .text
            hud.label.text = message
            hud.removeFromSuperViewOnHide = true
            hud.hide(animated: true, afterDelay: 2)
        }
    }
}

extension TwilioController : RoomDelegate{
    
    //ユーザーがルームに接続した時のイベント
    func roomDidConnect(room: Room) {
        connected = true
        roomStatusHandler?(.Connected)
    }
    
    //ユーザーがルームを出た時のイベント
    func roomDidDisconnect(room: Room, error: Error?) {
        connected = false
        roomStatusHandler?(.Disconnected)
    }
    
    //ネットワーク接続エラーまたはタイムアウト等でルームに参加できない時のイベント
    func roomDidFailToConnect(room: Room, error: Error) {
        connected = false
        roomStatusHandler?(.Error)
    }
    
    //他者がルームに参加した時のイベント
    func participantDidConnect(room: Room, participant: RemoteParticipant) {
        let message = "participant \(participant.identity) connected"
        toastMessage(message: message)
        roomStatusHandler?(.ParticipantConnected)
    }
    
    //参加者がルームを出た時のイベント
    func participantDidDisconnect(room: Room, participant: RemoteParticipant) {
        let message = "participant \(participant.identity) disconnected"
        toastMessage(message: message)
        roomStatusHandler?(.ParticipantDisconnected)
    }
}

このコントローラーには、主な関数が二つあります。

connectToRoom()はTWILIO_TEST_ROOM定数とアクセストークン(TWILIO_ACCESS_TOKEN_1またはTWILIO_ACCESS_TOKEN_2)で指定された特定のルームに接続します。
端末で実行する場合は、端末ごとに異なるアクセストークンを設定してください。また、この関数は次のイベント処理をも行ないます。

  • Connected:ユーザーがルームに接続した時のイベント
  • Disconnected:ユーザーがルームを出たときのイベント
  • ParticipantConnected:他者がルームに参加した時のイベント
  • ParticipantDisconnected:参加者がルームを出た時のイベント
  • roomDidFailToConnect:ネットワーク接続エラーまたはタイムアウト等でルームに参加できない時のイベント

disconnectFromRoom()はルームを出ます

つぎに、以下のような簡単な画面のCallViewControllerビューコントローラーを作成します。

次のコードをCallViewController.swiftファイルに入れます。

import UIKit
import MBProgressHUD

class CallViewController: UIViewController {
    
    @IBOutlet weak var joinButton: UIButton!
    @IBOutlet weak var roomTxt: UITextField!
        
    //ルームの参加ステータスが変わったら、ボタンの名前が更新されます。
    private var joined = false{
        didSet{
            if joined {
                joinButton.setTitle("End call", for: .normal)
            }else{
                joinButton.setTitle("Join", for: .normal)
            }
        }
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        roomTxt.text = TWILIO_TEST_ROOM
                
    }
    
    @IBAction func joinRoom(_ sender: Any) {
        if !joined{
            MBProgressHUD.showAdded(to: self.view, animated: true)
            kTwilioController.connectToRoom { (status) -> (Void) in
                if status == .Connected {
                    self.joined = true
                }
                if status == .Disconnected{
                    self.joined = false
                }
                MBProgressHUD.hide(for: self.view, animated: true)
            }
            
        }else{
            kTwilioController.disconnectFromRoom()
        }

    }
        
}

ユーザーが参加したいルームの名前を入力するためのテキストフィールドと、ルームに参加または退出するためのボタンがあります。このテキストフィールドはTwilioDemoChatRoomと命名し、変更不可とします。このボタンは参加ステータスによって名前が変更され、connectToRoom()disconnectFromRoom()を呼び出します。

では、2台のiOS端末で実行して動作を確認しましょう。尚、このアプリはシミュレーターに対応していません。

実行にあたって端末ごとにアクセストークンを必ず変更しておいてください。

参照元:

Twilio Video iOS Tutorial

Twilio Console