WWDC Quick Look 💓 By SwiftGGTeam
Explore enhancements to your spatial business app

Explore enhancements to your spatial business app

元の動画を見る

Highlight

visionOS 26 では UVC ビデオと Neural Engine へのアクセスがすべての開発者に開放され、さらに Window Follow Mode、共有座標空間、コンテンツのキャプチャ保護、Camera Region という 4 種類のエンタープライズ API が追加されました。

核心となる内容

昨年、visionOS は初めてエンタープライズ向けに低レベルの機能を開放しましたが、その代償は決して小さくありませんでした。UVC カメラのビデオを取得するには managed entitlement の申請とライセンスファイルの設定が必要で、Neural Engine ですらエンタープライズ向けのプロセスを通す必要がありました。USB カメラを使ってリモート診断を行いたい小さなチームにとっては、審査だけでもエンタープライズ開発者向けのコンプライアンスフローを丸ごと通さなければなりませんでした。

visionOS 26 ではこの縛りが緩和されています。Apple のエンジニア Alex Powers がセッション内で発表した通り、UVC ビデオアクセスと Neural Engine アクセスは今年からすべての開発者が利用可能となり、エンタープライズライセンスや entitlement を必要としません。Object Tracking も CreateML app の GUI 上でしか操作できなかったところから、コマンドラインでのトレーニングへと拡張され、CI パイプラインに直接組み込めるようになりました。ライセンス管理についても Apple Developer アカウントへ移管され、更新は OTA でデバイスへ配信されます。

残りのエンタープライズ向け機能は 2 つの軸に分かれています。ユーザー体験側では、Window Follow Mode(ウィンドウがユーザーに追従する)、SharedCoordinateSpaceProvider(同じ部屋にある複数の Vision Pro で座標系を揃える)、contentCaptureProtected(センシティブなコンテンツを録画や共有から自動的にマスクする)が追加されました。環境ビジュアライゼーション側では、Camera Frame Provider が左右のカメラを個別に、あるいはステレオで取得できるようになり、新しい Camera Region API では現実世界の特定の領域だけを切り出して拡大したり、コントラストを強化したりできるようになりました。遠隔での計器読み取りといったシナリオに向いています。

詳細

コマンドラインで Object Tracking モデルを学習する(03:00

xcrun createml objecttracker -s my.usdz -o my.referenceobject

ポイント:

  • xcrun createml objecttracker: CreateML の Object Tracking サブコマンドを呼び出します。GUI 版の CreateML app と同じトレーニングパラメータを共有します。
  • -s my.usdz: 入力する USDZ モデルファイルで、対象オブジェクトの reference object を生成するために使用します。
  • -o my.referenceobject: 出力アセットのパス。自動化されたパイプラインに直接組み込み、ファイル単位でバッチ処理できます。

VisionEntitlementServices でライセンス状態をチェックする(04:28

import VisionEntitlementServices

func checkLicenseStatus() {
    let license = EnterpriseLicenseDetails.shared

    guard license.licenseStatus == .valid else {
        print("Enterprise license is not valid: \(license.licenseStatus)")
        return
    }

    if license.isApproved(for: .mainCameraAccess) {
        print("Main Camera Access approved. Enabling feature...")
    } else {
        print("Main Camera Access not approved.")
    }
}

ポイント:

  • EnterpriseLicenseDetails.shared: 現在の app のライセンス情報(状態、有効期限など)をカプセル化したシングルトンです。
  • licenseStatus == .valid: まずライセンス全体が有効かを確認し、期限切れのライセンスでエンタープライズ機能のロジックを継続実行しないようにします。
  • isApproved(for: .mainCameraAccess): entitlement 単位で、特定のエンタープライズ API の利用を許可されているかを判定します。実行時に動的に機能をオン/オフできます。
  • このフレームワークは Increased Performance Headroom の entitlement 検証もサポートしており、高負荷タスクを実行する前に権限を確認できます。

SharedCoordinateSpaceProvider でカスタムの共有空間を構築する(10:04

import ARKit

class SharedCoordinateSpaceModel {
    let arkitSession = ARKitSession()
    let sharedCoordinateSpace = SharedCoordinateSpaceProvider()
    let worldTracking = WorldTrackingProvider()

    func runARKitSession() async {
        do {
            try await arkitSession.run([sharedCoordinateSpace, worldTracking])
        } catch {
            reportError("Error: running session: \(error)")
        }
    }

    func pushCoordinateSpaceData(_ data: Data) {
        if let coordinateSpaceData = SharedCoordinateSpaceProvider.CoordinateSpaceData(data: data) {
            sharedCoordinateSpace.push(data: coordinateSpaceData)
        }
    }

    func pollCoordinateSpaceData() async {
        if let coordinateSpaceData = sharedCoordinateSpace.nextCoordinateSpaceData {
            // Send my coordinate space data
        }
    }

    func addWorldAnchor(at transform: simd_float4x4) async throws {
        let anchor = WorldAnchor(originFromAnchorTransform: transform, sharedWithNearbyParticipants: true)
        try await worldTracking.addAnchor(anchor)
    }
}

ポイント:

  • SharedCoordinateSpaceProviderWorldTrackingProvider と同じ ARKitSession 上で動作し、見慣れた ARKit data provider モデルをそのまま利用できます。
  • nextCoordinateSpaceData: 自端末から他の参加者へブロードキャストする位置合わせ用データを取り出します。TCP/UDP/独自プロトコルのいずれを使うかは開発者の判断に委ねられます。
  • push(data:): 他のデバイスからネットワーク経由で受け取った CoordinateSpaceData を ARKit に戻し、共通の座標系を構築します。
  • WorldAnchor(... sharedWithNearbyParticipants: true): アンカーに共有フラグを付けることで、同じ部屋にある他の Vision Pro でも同じアンカー位置を一致して認識できます。
  • eventUpdates 非同期シーケンスは、参加者の入退出や共有スイッチの切り替え時に app へ通知します(10:04)。

contentCaptureProtected で機密コンテンツの流出を防ぐ(12:50

struct SecretDocumentView: View {
    var body: some View {
        VStack {
            Text("Secrets")
                .font(.largeTitle)
                .padding()

            SensitiveDataView()
                .contentCaptureProtected()
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
    }
}

ポイント:

  • contentCaptureProtected() は SwiftUI の view modifier で、protected content entitlement が必要です。
  • 適用したレイヤがそのまま、システムのスクリーンショット、画面録画、Screen Mirroring、SharePlay で自動的にマスクされます。
  • Vision Pro を装着している本人は元のコンテンツを引き続き見られますが、外部の視聴者にはぼかしや遮蔽ブロックとして表示されます。
  • 2D ビューだけでなく、RealityKit のシーン全体をラップすることもできます。

Camera Region で現実世界の一部を切り出す(16:48 / 21:15

import SwiftUI
import VisionKit

struct InspectorView: View {
    @Environment(CameraFeedDelivery.self) private var cameraFeedDelivery: CameraFeedDelivery

    var body: some View {
        CameraRegionView(isContrastAndVibrancyEnhancementEnabled: true) { result in
            var pixelBuffer: CVReadOnlyPixelBuffer?
            switch result {
            case .success(let value):
                pixelBuffer = value.pixelBuffer
            case .failure(let error):
                reportError("Failure: \(error.localizedDescription)")
                cameraFeedDelivery.stopFeed()
                return nil
            }

            cameraFeedDelivery.frameUpdate(pixelBuffer: pixelBuffer!)
            return nil
        }
    }
}

ポイント:

  • CameraRegionView は VisionKit が提供する高レベル API で、ウィンドウを「現実世界の特定領域に向けたファインダー」として扱います。
  • isContrastAndVibrancyEnhancementEnabled: true: コントラストと色彩の強化を有効にします。遠方の計器盤や針の読み取りなどに適しています。
  • クロージャ内で受け取った pixelBuffer は、自前のビデオパイプライン(リモートサポート、OCR、ストリーミング配信など)に渡して後続処理を行えます。
  • 低レベルの ARKit における等価物は CameraRegionAnchor(originFromAnchorTransform:width:height:cameraEnhancement:) で、.stabilization などの強化モードを指定でき、cameraRegionProvider.anchorUpdates(forID:) 経由でフレーム単位のピクセル更新を取得できます。
  • Apple は、単一の CameraRegionAnchor が可視領域に占める割合を 1/6 以下に抑えることを推奨しています。それを超えるとリソース消費が著しく増加します。

核心となる気付き

  • USB カメラを使い倒す: UVC ビデオアクセスは今年からすべての開発者に開放され、エンタープライズライセンスは不要になりました。

    • なぜ取り組む価値があるか: これまでライセンスの壁で諦めていたチームでも、産業用カメラ、サーモグラフィ、顕微鏡などの専門機器を直接接続できるようになります。
    • 始め方: Vision Pro Developer Strap を入手し、Building spatial experiences for business apps のドキュメントに従って UVC API を組み込みます。まずは最もシンプルな webcam のビデオストリームを通してから、ビジネスロジックを追加していきましょう。
  • コマンドラインで Object Tracking モデルをバッチ学習する: xcrun createml objecttracker によりモデル学習をスクリプト化できます。

    • なぜ取り組む価値があるか: 従来は 1 製品 SKU につき 1 つの USDZ を手動でクリックしていたものが、shell スクリプトで数十個のオブジェクトを一気に処理し、CI 上で referenceobject を自動生成できるようになります。
    • 始め方: Implementing object tracking in your app を参考に、CI コンテナへ Xcode command line tools をインストールし、USDZ の入力と referenceobject の出力を artifact フローへ組み込みます。
  • 機密ビューに contentCaptureProtected() を一括適用する: 1 行の modifier でスクリーンショット/画面録画/共有時の挙動を制御します。

    • なぜ取り組む価値があるか: 金融、医療、デザインデータなどのコンプライアンス対応で最大の悩みは「従業員が無意識に SharePlay や画面録画を起動してしまうこと」です。この API なら制御を SwiftUI のビュー層に集約できます。
    • 始め方: まず機密データを表示しているサブビューを洗い出し、SensitiveContent といった wrapper にまとめ、その内部で .contentCaptureProtected() を適用します。あわせてエンタープライズ開発者ポータルで protected content entitlement を申請しておきましょう。
  • ローカルネットワーク上で複数 Vision Pro が協調動作する: SharedCoordinateSpaceProvider を使い、自前のネットワーク上で共有座標空間を動かせます。

    • なぜ取り組む価値があるか: SharePlay は iCloud を経由するため負荷が高く、工場や病院のような閉じた社内ネットワークの環境では完全にローカルで動作するコラボレーションチャネルが求められます。新しい ARKit API はネットワーク層を完全に開発者に委ねます。
    • 始め方: ARKitSession 上で SharedCoordinateSpaceProviderWorldTrackingProvider を同時に起動し、Bonjour + UDP で LAN 内の CoordinateSpaceData を双方向に交換します。さらに共有 WorldAnchor を組み合わせれば完成です。

関連 Session

コメント

GitHub Issues · utterances