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)
}
}
ポイント:
SharedCoordinateSpaceProviderはWorldTrackingProviderと同じ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 上で
SharedCoordinateSpaceProviderとWorldTrackingProviderを同時に起動し、Bonjour + UDP で LAN 内のCoordinateSpaceDataを双方向に交換します。さらに共有 WorldAnchor を組み合わせれば完成です。
関連 Session
- Share visionOS experiences with nearby people — SharePlay の高レベル API による近接デバイス間の空間体験共有。
- Discover Apple-Hosted Background Assets — Apple ホスティングのバックグラウンドアセット配信。エンタープライズ app のアセット配布の参考になります。
- Get started with HealthKit in visionOS — visionOS 上のもう 1 つのセンシティブデータアクセスのシナリオ。本セッションと併読して権限設計を検討できます。
- Explore spatial accessory input on visionOS — visionOS 26 の入力デバイス拡張。Window Follow Mode と組み合わせて、エンタープライズの現場シナリオに活用できます。
コメント
GitHub Issues · utterances