【Swift】 Apple WatchにiPhoneのカメラ映像を表示する

2022/04/20に公開約2,500字


watchOSにインストールされているカメラアプリはiPhoneのカメラ映像をリアルタイムで表示することができます。この機能は監視カメラアプリやドライブレコーダーアプリといったカメラを使用したiPhoneアプリに応用することができます。
iPhoneのカメラ映像をリアルタイムでWatchアプリに表示する機能を実現する方法について紹介します。

iPhoneアプリ側からビデオフレームを抽出する

以下のデリゲートメソッドを使用することでビデオフレームを抽出することができます。

  • func captureOutput(AVCaptureOutput, didOutput: CMSampleBuffer, from: AVCaptureConnection)

新しいビデオフレームが書き込まれる度に上記デリゲートメソッドがコールされます。このデリゲートメソッドを使用して、ビデオフレームをCMSampleBuffer として取得します。 CMSampleBuffer はビデオフレーム情報やタイムスタンプ情報などのさまざまな情報を含むオブジェクトです。このオブジェクトに含まれるビデオフレーム情報をWatchアプリに送信します。

CMSampleBufferをUIImageに変換する

CMSampleBuffer には多くの情報が含まれていますが、Watchアプリに送信するのはビデオフレーム情報だけです。 従ってCMSampleBuffer オブジェクトからビデオフレームデータを抽出し、UIImage オブジェクトに変換します。

画像データのリサイズと圧縮

iPhoneアプリからWatchアプリに送信できるデータのサイズには制限があるため、画像データをできるだけ小さくします。 画像データは以下のメソッドでサイズ変更・圧縮します。

  • func scaledBy(x: CGFloat, y: CGFloat) -> CGAffineTransform
  • func jpegData(compressionQuality: CGFloat) -> Data?

Watchアプリに画像データを送信する

現在、iPhoneアプリからWatchアプリにデータを送信する方法は3つあります。

  • func sendMessage(_:replyHandler:errorHandler:)またはfuncsendMessageData(_:replyHandler:errorHandler :)
  • func transferUserInfo(_ :)
  • func transferFile(_:metadata :)

上記の各方法には、送信データサイズと送信タイミングの上限が異なります。

メソッド 上限サイズ 通信タイプ
sendMessage または sendMessageData 65,536 bytes (65.5 KB) 即時
transferUserInfo 65,536 bytes (65.5 KB) 即時でない
transferFile 262,144 bytes (262.1 KB) 即時でない

sendMessage またはsendMessageData は、iPhoneアプリとWatchアプリの間で即時通信が行われますが、やりとりすることができるデータの上限サイズは非常に小さいです。transferUserInfo とtransferFile は、iPhoneアプリとWatchアプリの間ですぐに通信することはできません。 ただし、transferUserInfo の通信制限サイズは大きくなります。今回はカメラのライブビューをWatchアプリにリアルタイムで表示したいので、sendMessage またはsendMessageData を使用します。以下のサンプルコードはsendMessage を使用して画像データをWatchアプリに送信しています。

画像データを受信してWatchアプリに表示

Watchアプリ側にデータが到着すると、次のデリゲートメソッドがコールされます。

  • func session(WCSession, didReceiveMessage: [String : Any])

上記のメソッドで受信したデータをUIImageに変換し、WKInterfaceImageImageオブジェクトに設定すればiPhoneのカメラ映像をWatchアプリに表示することができます。

デモ

https://youtube.com/shorts/Jp1GroA1UCc?feature=share

Discussion

ログインするとコメントできます