https://d226lax1qjow5r.cloudfront.net/blog/blogposts/how-to-make-video-calls-with-swiftui/video-call_swiftui_1200x600.png

SwiftUIでビデオ通話をする方法

最終更新日 May 13, 2021

所要時間:1 分

この記事は2025年3月に更新されました。

このチュートリアルでは、Vonage Video Client SDK を使用します。を使用して SwiftUI で一対一のビデオチャットを構築します。

前提条件

Video API プロジェクトの作成

あなたの Vonage APIダッシュボードを開き、新しいVonageアプリケーションを作成します。アプリケーションの名前は何でもかまいませんが、機能のところでVideoを有効にしてから、generate a new applicationをクリックしてください。アプリケーションが作成されたら、アプリケーションIDをコピーします。次に にアクセスしてください。 Video Playgroundにアクセスします。にアクセスし、新しいセッションを作成します:

  1. 一番上の "Create a new session "タブが選択されていることを確認してください。

  2. 特定のアプリケーションIDをお持ちですか」で「はい」を選択する。

  3. 表示された "Application ID "ボックスに、先ほど作成したApplication IDをペーストする。

  4. 他はそのままにして、"Create Session "をクリックします。

  5. 次に表示されるページで、「SESSION ID」を控えておいてください。

  6. 上部にある「接続」ボタンをクリックします。

  7. 一番上の「セッションとトークン情報」セクションを展開します。

  8. 生成された "TOKEN "をメモしておく。

iOSアプリケーションの作成

次のステップは、iOSアプリケーションのセットアップです。アプリケーションを作成したら、Video Client SDKをインストールし、マイクとカメラの許可を求める必要があります。

Xcodeプロジェクトの作成

始めるには、Xcodeを開き、File > New > Projectで新しいプロジェクトを作成する。プラットフォームとしてiOS、テンプレートとしてAppを選択し、名前を付ける。

Xcode platform screen

インターフェイスはSwiftUI、ライフサイクルはSwiftUI App、言語はSwiftを選択する。最後に、プロジェクトを保存する場所を指定します。

Xcode project creation screen

Client SDKのインストール

これでプロジェクトが作成できたので、Video Client SDKを依存関係として追加することができます。Xcodeプロジェクトを閉じ、ターミナルでプロジェクトを保存した場所に移動し、以下のコマンドを実行します:

  1. pod initコマンドを実行して、プロジェクト用の新しいPodfileを作成します。

  2. Xcodeでopen -a Xcode Podfileを使ってPodfileを開く。

  3. Podfileを更新して OTXCFrameworkを依存関係として持つようにPodfileを更新する。

# Uncomment the next line to define a global platform for your project
# platform :ios, '12.0'

target 'VideoChat' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for VideoChat
  pod 'OTXCFramework'

end
  1. SDKをインストールするには pod install.

  2. 新しい xcworkspaceファイルを開く。 open VideoChat.xcworkspace.

アクセス許可

アプリケーションはビデオチャットにマイクとカメラを使用するため、パーミッションが必要な理由の説明を追加する必要があります。

ファイルを編集する Info.plistファイルを編集する。ファイルを編集する。 Info.plistはアプリケーションに必要なすべてのメタデータを含むファイルです。リストの最後のエントリにマウスカーソルを合わせ、表示される小さな +ボタンをクリックします。ドロップダウンリストから Privacy - Microphone Usage Descriptionを選び、その値に Microphone access required to video chatを追加します。の手順を繰り返します。 Privacy - Camera Usage Description.

ビデオクライアントSDK

Video Client SDKは、Video APIダッシュボードで作成した認証情報を使用してVonageサーバに接続します。

Client SDKの接続

という新しいファイルを作成する。 OpenTokManager.swiftという新しいファイルを作成する。 ファイル>新規ファイル(CMD + N)を追加し、空の文字列を認証情報に置き換える:

import OpenTok

final class OpenTokManager: NSObject, ObservableObject {
    // Replace with your Vonage Application ID
    private let kAppId = ""
    // Replace with your generated session ID
    private let kSessionId = ""
    // Replace with your generated token
    private let kToken = ""

    private lazy var session: OTSession = {
        return OTSession(apiKey: kAppId, sessionId: kSessionId, delegate: self)!
    }()

    private lazy var publisher: OTPublisher = {
        let settings = OTPublisherSettings()
        settings.name = UIDevice.current.name
        return OTPublisher(delegate: self, settings: settings)!
    }()
    
    private var subscriber: OTSubscriber?
    
    @Published var pubView: UIView?
    @Published var subView: UIView?
    @Published var error: OTErrorWrapper?
}

クレデンシャルに加えて、以下の変数がある。 セッション, パブリッシャーそして 購読者.前述したように、セッションはクライアントが接続する部屋と考えることができます。 OTSessionクラスがあります。パブリッシャー、 OTPublisherは、セッションに接続されたときに、クライアントがオーディオとビデオをパブリッシュできるようにします。サブスクライバー、 OTSubscriberは、クライアントがセッション内の他のクライアントのオーディオやビデオをサブスクライブできるようにします。また @Publishedプロパティラッパーもあります。 OpenTokManagerクラスが後でビューコードと通信する方法です。

プロパティが揃ったので、次の関数を OpenTokManagerクラスに追加します:

import OpenTok

final class OpenTokManager: NSObject, ObservableObject {
    ...

    public func setup() {
        doConnect()
    }
    
    private func doConnect() {
        var error: OTError?
        defer {
            processError(error)
        }
        session.connect(withToken: kToken, error: &error)
    }
    
    private func doPublish() {
        var error: OTError?
        defer {
            processError(error)
        }
        
        session.publish(publisher, error: &error)
        
        if let view = publisher.view {
            DispatchQueue.main.async {
                self.pubView = view
            }
        }
    }
    
    private func doSubscribe(_ stream: OTStream) {
        var error: OTError?
        defer {
            processError(error)
        }
        subscriber = OTSubscriber(stream: stream, delegate: self)
        session.subscribe(subscriber!, error: &error)
    }
    
    private func cleanupSubscriber() {
        DispatchQueue.main.async {
            self.subView = nil
        }
    }
    
    private func cleanupPublisher() {
        DispatchQueue.main.async {
            self.pubView = nil
        }
    }
    
    private func processError(_ error: OTError?) {
        if let err = error {
            DispatchQueue.main.async {
                self.error = OTErrorWrapper(error: err.localizedDescription)
            }
        }
    }
}

この doConnect関数はクライアントをセッションに接続する、 doPublishパブリッシュを開始します、 doSubscribeサブスクライブを開始します。そして、サブスクライバ(cleanupSubscriber)とパブリッシャー(cleanupPublisher)をクリーンアップする関数があります。processError).

についてOTSessionDelegate

これは OTSessionDelegateは、Video Client SDK がセッションの変更をあなたに通知する方法です。同じファイルに拡張子を追加します:

extension OpenTokManager: OTSessionDelegate {
    func sessionDidConnect(_ session: OTSession) {
        print("Session connected")
        doPublish()
    }
    
    func sessionDidDisconnect(_ session: OTSession) {
        print("Session disconnected")
    }
    
    func session(_ session: OTSession, didFailWithError error: OTError) {
        print("session Failed to connect: \(error.localizedDescription)")
    }
    
    func session(_ session: OTSession, streamCreated stream: OTStream) {
        print("Session streamCreated: \(stream.streamId)")
        doSubscribe(stream)
    }
    
    func session(_ session: OTSession, streamDestroyed stream: OTStream) {
        print("Session streamDestroyed: \(stream.streamId)")
        if let subStream = subscriber?.stream, subStream.streamId == stream.streamId {
            cleanupSubscriber()
        }
    }
}

セッションが接続すると doPublishが呼び出され、ストリームが作成されると doSubscribeが呼び出され、ストリームが破棄されると cleanupSubscriberが呼ばれる。

についてOTPublisherDelegate

これは OTPublisherDelegateは、Video Client SDK がセッションの公開に伴う変更をお客様に通知する方法です。同じファイルに拡張子を追加します:

extension OpenTokManager: OTPublisherDelegate {
    func publisher(_ publisher: OTPublisherKit, streamCreated stream: OTStream) {
        print("Publishing")
    }
    
    func publisher(_ publisher: OTPublisherKit, streamDestroyed stream: OTStream) {
        cleanupPublisher()
        if let subStream = subscriber?.stream, subStream.streamId == stream.streamId {
            cleanupSubscriber()
        }
    }
    
    func publisher(_ publisher: OTPublisherKit, didFailWithError error: OTError) {
        print("Publisher failed: \(error.localizedDescription)")
    }
}

と同様に OTSessionDelegateストリームが破壊されたとき cleanupPublisherが呼び出され cleanupSubscriberが呼び出されます。

についてOTSubscriberDelegate

を使用します。 OTSubscriberDelegateは、Video Client SDK がセッションをサブスクライブして、変更をあなたに通知する方法です。同じファイルに拡張子を追加します:

extension OpenTokManager: OTSubscriberDelegate {
    
    func subscriberDidConnect(toStream subscriberKit: OTSubscriberKit) {
        if let view = subscriber?.view {
            DispatchQueue.main.async {
                self.subView = view
            }
        }
    }
    
    func subscriber(_ subscriber: OTSubscriberKit, didFailWithError error: OTError) {
        print("Subscriber failed: \(error.localizedDescription)")
    }
}

セッションに発行するときと同様に、購読が成功すると UIViewオブジェクトが返されます。オブジェクトが返されます。 subscriberDidConnectの場合、返されるビューオブジェクトはサブスクライバ用のものです。

ビデオチャット UI の構築

これで OpenTokManagerクラスが完成したら、次はUIを構築します。Video Client SDK は SwiftUI では直接使用できない UIViewオブジェクトを提供します。プロトコルは UIViewRepresentableプロトコルは UIViewオブジェクトから Viewオブジェクトへのブリッジングを可能にします。ファイル内に ContentView.swiftファイルに次の構造体を追加します:

struct OTErrorWrapper: Identifiable {
    var id = UUID()
    let error: String
}

struct OTView: UIViewRepresentable {
    @State var view: UIView
    
    func makeUIView(context: Context) -> UIView {
        return view
    }
    
    func updateUIView(_ uiView: UIView, context: Context) {
        DispatchQueue.main.async {
            self.view = uiView
        }
    }
}

この OTView構造体は UIViewRepresentableには UIViewオブジェクトをプロパティとして持ちます。このビューは、システムが makeUIView.SwiftUI におけるビューのライフサイクルはシステムによって制御されるので、それを処理するためにupdateUIViewを実装する必要があります。構造体OTErrorWrapper構造体はエラーがIdentifiableこれはSwiftUIのアラートを使うために必要です。

次に ContentView構造体を次のように置き換える:

struct ContentView: View {
    @ObservedObject var otManager = OpenTokManager()
    
    var body: some View {
        VStack {
            otManager.pubView.flatMap { view in
                OTView(view: view)
                    .frame(width: 200, height: 200, alignment: .center)
            }.cornerRadius(5.0)
            otManager.subView.flatMap { view in
                OTView(view: view)
                    .frame(width: 200, height: 200, alignment: .center)
            }.cornerRadius(5.0)
        }
        .alert(item: $otManager.error, content: { error -> Alert in
            Alert(title: Text("OpenTok Error"), message: Text(error.error), dismissButton: .default(Text("Ok")))
        })
        .animation(.default)
        .onAppear(perform: {
            otManager.setup()
        })
    }
}

このコードでは、先ほどの OpenTokManagerクラスのインスタンスのプロパティを追加しています。公開する OpenTokManagerはオプションです、 .flatmapが使われます。そのため、ビューがnilの場合は無視され、値がある場合はアンラップされます。もし OpenTokManagerがエラーを発行した場合、アラートは自動的に表示されます。 .error値の変更を監視しているので、アラートは自動的に表示されます。

プロジェクトをビルドして実行すれば、Videoチャットを開始できるはずです!他のデバイスまたは Video API プレイグラウンドを使ってラップトップからセッションに接続できます。

video chat ios screenshot

次はどうする?

完成したプロジェクトは GitHubで公開されています。また、Vonage Video API については私たちの ドキュメンテーション.

シェア:

https://a.storyblok.com/f/270183/400x400/19c02db2d3/abdul-ajetunmobi.png
Abdul AjetunmobiVonage 元チームメンバー

アブドゥルはVonageのデベロッパー・アドボケイト。iOSエンジニアとして消費者向け製品に携わった経歴を持つ。余暇には、サイクリング、音楽鑑賞、技術者としての道を歩み始めたばかりの人々の指導を楽しんでいる。