ハイライト
macOS 14 の ScreenCaptureKit には、Presenter Overlay スピーカー オーバーレイ エフェクト、SCContentSharingPicker システム レベル コンテンツ セレクター、および SCScreenshotManager 高解像度スクリーンショット API が追加されており、これにより、画面共有アプリケーションは、独自に構築した UI を構築することなく、システムで一貫したエクスペリエンスを得ることができます。
主な内容
画面共有 UI のジレンマ
ビデオ会議ツールや画面録画ツールを作成する場合、コンテンツ選択インターフェイスが面倒になることがあります。すべてのウィンドウとアプリケーションを列挙するには、さまざまなエッジ ケースを処理する選択パネルを描画します。アプリケーションごとに選択インターフェイスの外観が異なるため、ユーザーは毎回それを学び直す必要があります。
SCContentSharingPicker がこの負担を引き継ぎます。これは、macOS ネイティブと一致するウィンドウ/アプリケーション/ディスプレイの選択エクスペリエンスを提供するシステム レベルのシングルトンであり、ユーザーがビデオ メニュー バー、アプリ内ボタン、またはウィンドウを直接クリックすることによってトリガーできます。
プレゼンター オーバーレイ: 自動スピーカー効果
リモート会議で画面を共有する場合、発言者のポートレートとコンテンツは分離されます。プレゼンター オーバーレイは、高度なセグメンテーション アルゴリズムを通じて共有コンテンツにスピーカーを埋め込みます。
スモール オーバーレイ モードでは、移動可能な円形ウィンドウ内にスピーカーが配置されます。ラージ オーバーレイ モードは、スピーカーを背景から分離し、スピーカーと背景の間に画面コンテンツを配置して、天気予報に似た没入型効果を作り出します。
重要なのは、この効果は ScreenCaptureKit を使用するアプリケーションに対して自動的に有効になるということです。アプリがカメラとスクリーン キャプチャ ストリームの両方を使用している限り、コントロールはビデオ メニュー バーに表示され、ScreenCaptureKit は合成されたフレームをストリームに直接プッシュします。
ビデオ ストリームからネイティブ スクリーンショットにフレームをキャプチャします
以前は、画面のコンテンツをキャプチャするには、SCStream からフレームを取得するか、CGWindowListCreateImage を使用する必要がありました。前者はストリームを維持する必要がありますが、後者は機能が制限されています。
SCScreenshotManager は、非同期スクリーンショット API を提供し、CGImage と CMSampleBuffer の 2 つの出力形式をサポートし、ScreenCaptureKit のフィルタリングおよび構成機能を再利用します。
##詳細
プレゼンターオーバーレイステータス検出
(03:32)
アプリは、UI を調整できるように、プレゼンター オーバーレイがいつ有効になっているかを知る必要があります。
let stream = SCStream(filter: filter, configuration: config, delegate: self)
// SCStreamDelegate コールバックを実装
func stream(_ stream: SCStream, outputEffectDidStart didStart: Bool) {
if didStart {
presentBanner()
turnOffCamera() // ローカルカメラのタイルを非表示にする
} else {
turnOnCamera()
}
}
キーポイント:
outputEffectDidStartプレゼンターのオーバーレイが有効/無効になったときにトリガーされます- 有効にすると、カメラがオーバーレイによって直接使用されるため、AVCaptureSession は通常のカメラ ストリームを出力しなくなります
- ビデオ通話アプリケーションはオーディオとビデオの同期を調整し、発言者のローカル カメラ タイルを非表示にする必要があります。
- オーバーレイにはリアルタイムの分割レンダリングが含まれるため、より高いフレーム レートに最適化することをお勧めします。
システムレベルのコンテンツセレクター
(06:48)
SCContentSharingPicker は、独自に構築されたコンテンツ選択インターフェイスを置き換えます。
let picker = SCContentSharingPicker.shared()
picker.addObserver(self)
picker.isActive = true
// アプリ内ボタンでシステムピッカーを表示
func showSystemPicker(sender: UIButton) {
picker.present(for: nil, using: .window)
}
// 選択完了時のコールバック
func contentSharingPicker(_ picker: SCContentSharingPicker,
didUpdateWith filter: SCContentFilter,
for stream: SCStream?) {
if let stream = stream {
stream.updateContentFilter(filter)
} else {
let newStream = SCStream(filter: filter, configuration: config, delegate: self)
// 新しいストリームを開始
}
}
// 失敗とキャンセルのコールバック
func contentSharingPicker(_ picker: SCContentSharingPicker,
didCancelFor stream: SCStream?) {
if let stream = stream {
resetStateForStream(stream: stream)
}
}
func contentSharingPickerStartDidFailWithError(_ error: Error) {
presentNotification(error: error)
}
キーポイント:
isActive = trueこのアプリをビデオ メニュー バーに含めるには必須ですpresent(for:using:)のcontentStyleオプション.window、.application、.display- コールバックによって返される
SCContentFilterストリームの作成または更新に直接使用できます - セレクターの動作はストリームごとに個別に設定可能
ストリームごとにセレクターを構成する
(08:41)
let pickerConfig = SCContentSharingPickerConfiguration()
pickerConfig.allowedPickingModes = [.window, .application]
pickerConfig.excludedBundleIDs = ["com.foo.myApp", "com.foo.myApp2"]
pickerConfig.allowsRepicking = false
picker.setConfiguration(pickerConfig, for: stream)
キーポイント:
allowedPickingModesユーザーが選択できるコンテンツの種類を制限するexcludedBundleIDsそしてexcludedWindowIDs機密性の高いアプリやウィンドウを非表示にするallowsRepicking = falseユーザーが選択したコンテンツを変更できないようにする- 各ストリームは異なる構成を持つことができます
HD スクリーンショット API
(12:26)
// 方法 1: CGImage 出力
if let screenshot = try? await SCScreenshotManager.captureImage(
contentFilter: myContentFilter,
configuration: myConfiguration
) {
// screenshot は CGImage で、NSImage/UIImage に直接使用できます
}
// 方法 2: CMSampleBuffer 出力
if let sampleBuffer = try? await SCScreenshotManager.captureSampleBuffer(
contentFilter: myContentFilter,
configuration: myConfiguration
) {
// より多くのピクセル形式に対応し、動画処理フローに適しています
}
完全な使用プロセス:
// 1. 共有可能なコンテンツを取得
let content = try await SCShareableContent.current
// 2. コンテンツフィルターを作成(ピッカーまたは手動で指定可能)
let filter = SCContentFilter(display: content.displays.first!,
excludingApplications: [],
exceptingWindows: [])
// 3. スクリーンショットのパラメータを設定
let configuration = SCStreamConfiguration()
configuration.width = 1920
configuration.height = 1080
configuration.showsCursor = true
// 4. スクリーンショット API を呼び出す
if let screenshot = try? await SCScreenshotManager.captureImage(
contentFilter: filter,
configuration: configuration
) {
print("スクリーンショットに成功、サイズ: \(screenshot.width) x \(screenshot.height)")
}
キーポイント:
captureImage直接表示または保存に適した CGImage を返します。captureSampleBufferCMSampleBuffer を返し、より多くのピクセル形式をサポートします- カーソル表示、解像度、色空間などの設定オプションは基本的に SCStream と同じです。
- CGWindowListCreateImageから移行する場合、ウィンドウ階層オプションはSCShareableContentで取得されます。
重要ポイント
- ワンクリック画面録画ツール
- やるべきこと: メニュー バー ウィジェットを作成し、クリックしてシステム セレクターをポップアップし、ウィンドウを選択して GIF/ビデオの録画を開始します。
- 実行する価値がある理由: SCContentSharingPicker は完全な選択 UI を提供します。自分で構築する必要はなく、わずか数行のコードでプロ レベルの画面記録を実現できます。
- 開始方法: を使用します
SCContentSharingPicker.shared()コールバックで作成されたセレクターを取得しますSCStream出力先AVAssetWriter
- スマートなスクリーンショットメモアプリケーション
- 対処方法: スクリーンショットを撮った後、OCR でテキストを自動的に認識し、アプリケーション分類ごとにアーカイブします。
- 実行する価値がある理由:
SCScreenshotManager特定のウィンドウを正確にキャプチャし、連携することができます。excludedBundleIDsプライベートコンテンツをフィルタリングする - 開始方法: を使用します
SCShareableContentウィンドウリストを取得して作成するSCContentFilter対象ウィンドウを指定して呼び出しますcaptureImage
- リモート コラボレーション ホワイトボード
- 内容: 画面共有時にスピーカーのジェスチャーとレーザー ポインター マークを自動的にオーバーレイします。
- 実行する価値がある理由: プレゼンター オーバーレイはすでに話者のセグメンテーションを処理しているため、アプリケーションは受信側でカスタム アノテーション レイヤーをオーバーレイするだけで済みます。
- 開始方法: 検出
outputEffectDidStartコールバック、UIレイアウトの調整、共有画面へのCAShapeLayer描画マークの重畳
- アプリケーション使用状況分析ツール
- 何をすべきか: ユーザーのアクティブなウィンドウを定期的に傍受し、毎日のアプリケーション使用時間の視覚的なレポートを生成します。
- 実行する価値がある理由: スクリーンショット API はアプリケーションごとに正確にフィルタリングできます。
SCShareableContentウィンドウレベルの情報 - 開始方法: を使用します
SCShareableContent.currentアプリケーションリストを取得し、アプリケーションごとにフィルターを作成し、定期的に呼び出します。captureSampleBufferピクセルの変化を分析してアクティビティを判断する
関連セッション
- ScreenCaptureKit の紹介 — 2022 年の ScreenCaptureKit の基本概要
- ScreenCaptureKit を次のレベルに引き上げる — 2022 年の高度なヒント
- アプリに SharePlay を追加 — 画面共有と SharePlay を組み合わせて共同作業を実現します
- Discover Continuity Camera for tvOS — クロスデバイスのカメラ共有テクノロジー
コメント
GitHub Issues · utterances