Image of phone with a video preview opened while the user is on a different app.

Vonageビデオ通話にiOSのピクチャー・イン・ピクチャーを採用する方法

最終更新日 August 27, 2024

所要時間:1 分

iOS 15のリリースに伴い、アップルはiPhoneやiPadでのマルチタスクを大幅に改善するPicture in Picture機能を導入しました。Picture in Pictureでは、他のアプリケーションを使用しながらビデオ通話を続けることができ、優れた柔軟性と利便性を提供します。これにより、生産性と応答性が向上し、この機能が現代のコミュニケーションにとっていかに重要であるかがわかります。

この記事では、開発者がiOS Picture in Pictureを使ってVonageビデオ通話を効果的にアプリに統合する方法を探ります。

Vonage API Account

To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.

前提条件

Vonageカスタムビデオレンダリング

iOSのPicture in PictureにVonageビデオ通話を統合する前に、開発者はVonageのビデオレンダラから生のビデオデータを取得し、処理する必要があります。このデータは、アプリ内で直接 Video ストリームにアクセスするために不可欠です。アプリケーションの基礎を構築することから始めましょう!

チュートリアルに従って 基本的なビデオチャットアプリを作成する。(チュートリアルに沿って、基本的なビデオチャットアプリを作成してください(完成予想時間:25分)。ゼロから始めるのを避けたい場合は、私たちの Swift サンプルアプリのレポを GitHub.

レポをクローンした場合は、自分のApp ID、セッションID、トークンの値を自分のものに置き換えてください:

  • App IDは、アプリケーション作成時にダッシュボードに表示されるVonage APIキーです。

  • セッションIDは、ダッシュボードで「ビデオセッションを作成」を選択したときに作成されます。

  • トークンは Vonage Server SDKsを使用して、独自の値でトークンを生成することができます。

CocoaPods がインストールされていると仮定して、ターミナルを開き、プロジェクトディレクトリに cd して、次のように入力します。 ポッドインストール..xcworkspaceファイルを使用して、Xcodeでプロジェクトを再度開きます。

ViewController.swiftファイルの以下の空文字列を、対応するAPIキー、セッションID、トークンの値に置き換えます:

// *** Fill the following variables using your own Project info  ***

//  ***            https://tokbox.com/account/#/                  ***

// Replace with your OpenTok API key

let kApiKey = ""

// Replace with your generated session ID

let kSessionId = ""

// Replace with your generated token

let kToken = ""

アプリケーションをビルドして実行する。

サンプルアプリケーションの ViewController.swift ファイルでは、すでに OTSubscriber:

  subscriber = OTSubscriber(stream: stream, delegate: self)

サブスクライバには videoRenderというプロパティがあり、サブスクライブするストリームにカスタムレンダラを割り当てることができます。ここで プロパティに割り当てる必要があります。プロパティを クラスに割り当てる必要があります。クラスを実装するカスタム・クラスである OTVideoRenderプロトコルを実装するカスタムクラスである iOS SDK).このプロトコルにより、Vonage Video のパブリッシャまたはサブスクライバが使用するカスタムビデオレンダラを定義できます。

   let videoRender = ExampleVideoRender()
   subscriber?.videoRender = videoRender

継続的なビデオストリーミングを行うには、以下のように を削除する必要があります。をサブスクライバから削除する必要があります。これにより、アプリがバックグラウンドにある場合でも、Video ストリームの操作を維持できるようになります。

NotificationCenter.default.removeObserver(subscriber, name: UIApplication.willResignActiveNotification, object: nil)

ExampleVideoRenderクラスは、受信する Video ストリーム・データを処理し、サブスクライバの Video フレームがアプリ内でアクセスおよび調整できるようにします。このクラスは renderVideoFrameメソッドは、加入者が Video レンダラに Video フレームをレンダリングするときに呼び出されます。フレームは OTVideoFrameオブジェクト(iOS SDK で定義)であり、メタデータやプレーンデータなどの Video フレーム情報を持ちます。

以来 OTVideoFrameはYUVプレーンデータしか提供しないので、それを CMSampleBufferに変換する必要がある。この変換プロセスは後ほど説明する。

この CMSampleBufferを取得し、指定されたUIViewに表示することができます。

let bufferDisplayLayer = videoRender.bufferDisplayLayer

bufferDisplayLayer.frame = frame

videoContainerView.layer.addSublayer(bufferDisplayLayer)

YUVデータをサンプルバッファに変換する

YUV(YCbCr)はビデオ用の一般的な色空間で、ルミナンス(Y)とクロミナンス(UV)を別々に表現する。YUVプレーンデータを抽出することで、開発者はこれらのコンポーネントを操作し、iOSのサンプルバッファと互換性のある形式に変換することができます。これは、iOSのPicture in PictureモードでVideoフレームを表示するために必要です。

上述したように OTVideoFramerenderVideoFrameこのメソッドは、サブスクライバが Video フレームをレンダリングするときに呼び出されます。このフレームには YUV プレーンのデータが含まれます。 CVPixelBuffer.このステップでは、YUV コンポーネントを整理し、ピクセル バッファに正しくマッピングします。

let pixelAttributes: NSDictionary = [kCVPixelBufferIOSurfacePropertiesKey as String: [:]]

var pixelBuffer: CVPixelBuffer?

let result = CVPixelBufferCreate(kCFAllocatorDefault, width, height, kCVPixelFormatType_32BGRA, pixelAttributes as CFDictionary, &pixelBuffer)
         _ = accel.convertFrameVImageYUV(frame, to: pixelBuffer)

次に CMSampleBufferから から CVPixelBufferから CMSampleBuffer を作成し、タイムスタンプやフォーマットの説明などの必要なメタデータを含めます。これらの手順は、iOS の Picture in Picture モードで表示する Video フレームを準備し、スムーズな再生と iOS 標準への準拠を保証するために重要です。

func createSampleBufferFrom(pixelBuffer: CVPixelBuffer) -> CMSampleBuffer? {
        CVPixelBufferLockBaseAddress(pixelBuffer, .readOnly)
        
        var sampleBuffer: CMSampleBuffer?
        
        
        let now = CMTimeMakeWithSeconds(CACurrentMediaTime(), preferredTimescale: 1000)
        var timingInfo = CMSampleTimingInfo(duration: CMTimeMakeWithSeconds(1, preferredTimescale: 1000), presentationTimeStamp: now, decodeTimeStamp: now)
        var formatDescription: CMFormatDescription? = nil
        CMVideoFormatDescriptionCreateForImageBuffer(allocator: kCFAllocatorDefault, imageBuffer: pixelBuffer, formatDescriptionOut: &formatDescription)
        
        let osStatus = CMSampleBufferCreateReadyWithImageBuffer(
            allocator: kCFAllocatorDefault,
            imageBuffer: pixelBuffer,
            formatDescription: formatDescription!,
            sampleTiming: &timingInfo,
            sampleBufferOut: &sampleBuffer
        )
        
        if osStatus != noErr {
            let errorMessage = osStatusToString(status: osStatus)
            print("osStatus error: \(errorMessage)")
        }
        
        guard let buffer = sampleBuffer else {
            print("Cannot create sample buffer")
            return nil
        }
        
        CVPixelBufferUnlockBaseAddress(pixelBuffer, [])
        
        return buffer
    }

ピクチャー・イン・ピクチャー・コンポーネントの実装

CMSampleBufferの準備ができたので、以下の手順に従ってください。 ビデオ通話用にピクチャー・イン・ピクチャーを追加する:

1.Video-Callビューコントローラ内に表示するソースビューを作成する。

class SampleBufferVideoCallView: UIView {

    override class var layerClass: AnyClass {

        AVSampleBufferDisplayLayer.self

    }

    var sampleBufferDisplayLayer: AVSampleBufferDisplayLayer {

        layer as! AVSampleBufferDisplayLayer

    }

}

2.2. AVPictureInPictureVideoCallViewControllerを作成します。を作成し、ソースビューを表示するサブビューとしてソースを追加します。

let pipVideoCallViewController = AVPictureInPictureVideoCallViewController()

pipVideoCallViewController.preferredContentSize = CGSize(width: 640, height: 480)  

pipVideoCallViewController.view.addSubview(sampleBufferVideoCallView)

3.3. AVPictureInPictureController.ContentSourceを作成します。を作成します。これは、ViewController.swift ファイルでシステムが表示するコンテンツのソースを表します。

let contentSource = AVPictureInPictureController.ContentSource(

            activeVideoCallSourceView: videoContainerView,

            contentViewController: pipVideoCallViewController)

4.初期化 AVPictureInPictureControllerを初期化し を設定します。を true に設定します。

pipController = AVPictureInPictureController(contentSource: contentSource)   

pipController.canStartPictureInPictureAutomaticallyFromInline = true

以上のセットアップで、アプリケーションはPicture in Pictureモードの準備が整いました。ユーザーがバックグラウンドに移動すると、ビデオ通話が開始されるのが確認できます。表示されない場合は、iPhone/iPadの設定でPicture in Pictureモードが有効になっているかどうかを確認してください。

Screen recording of opening the video app, minimizing it and still being able to see a window while opening other applications.iOS Demo

統合プロセスの概要

Vonageのビデオ通話をiOSのPicture in Pictureと統合することで、マルチタスクが強化され、ユーザは他のアプリケーションを使用しながらビデオ通話を中断することなく続けることができます。この機能により、特に専門的な会議や共同作業の生産性が向上します。

ピクチャー・イン・ピクチャー・サンプル・アプリの詳細と完全なコードは、私たちの GitHubリポジトリ.

ご質問がある場合は コミュニティ・スラックに参加するか X以前はTwitterとして知られていました。

その他のリソース

シェア:

https://a.storyblok.com/f/270183/400x351/0c294bb1fc/iu-jie-lim.png
Iu Jie Lim

Iu Jie is a Software Engineer who is constantly seeking innovative ways to solve a problem. She is passionate about new technology, especially relating to cloud and AI. Out of work, she likes to spend her time hunting for tasty food with family.