ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
ScreenCaptureKitの新機能
ScreenCaptureKitの最新機能を使って、画面共有の体験をレベルアップしましょう。ビルトインのシステムピッカー、プレゼンターオーバーレイ、スクリーンショット機能を探求し、これらの機能を既存のScreenCaptureKitアプリやゲームに組み込む方法を学びましょう。
関連する章
- 0:08 - Intro
- 1:36 - Presenter Overlay
- 4:36 - Screen sharing picker
- 9:46 - Screenshot API
- 13:01 - Wrap-Up
リソース
関連ビデオ
WWDC23
WWDC22
-
ダウンロード
♪ ♪
Christopher: こんにちは ようこそ! ScreenCaptureKitチームの ソフトウェアエンジニアの Christopherです 同僚のNatalie Lindsayと アプリのスクリーンキャプチャ機能を 強化する新機能を紹介します
ScreenCaptureKitは macOS 12.3で導入され アプリの画面共有体験を 作成する際に役立ちます ScreenCaptureKitは アプリのニーズに合ったコントロールで 共有したいコンテンツを カスタマイズできるAPIを提供し そのすべてをストリームに 動的に適用できます このフレームワークは ディスプレイのネイティブ解像度と フレームレートにまで対応する パフォーマンスに重点を置き 高品質のコンテンツを提供します 今年 ScreenCaptureKitは macOSの新機能と統合する 複数のデベロッパAPIを提供します プレゼンターオーバーレイは キャプチャしたコンテンツに プレゼンターを埋め込み表示することで 画面共有やプレゼンテーションを より個人的なものにできる機能です 新しい画面共有ピッカーを使えば 画面共有でキャプチャしたものを システム全体で統合できるようになります 最後に スクリーンキャプチャは ライブストリームのためだけではありません 今年は 選択したあらゆるコンテンツの 高解像度スクリーンショットをキャプチャ できるまったく新しいAPIがあります 人々は毎日 世界中で交流しています このような交流は私たちが考えやアイデアを 共有する場でもあります プロフェッショナルでもあり 個人的なものでもあります このため アプリは プレゼンターオーバーレイと呼ばれる― 新しいビデオエフェクトと シームレスに連携することができます プレゼンターオーバーレイは コンテンツを共有する際に 共有コンテンツの上にプレゼンターを表示し プレゼンターの存在感を高め より生産的なリモート通話に 個人的な要素を追加します 小さなオーバーレイは高度な セグメンテーションアルゴリズムにより プレゼンターを移動可能な ウインドウに配置します 一方 大きなオーバーレイでは プレゼンターの顔と体を背景から分離し その間に画面コンテンツを重ねることで さらにイマーシブな効果を実現します プレゼンターオーバーレイは ScreenCaptureKitを使用する すべてのアプリで使用できます SCStreamが作成されるたびに ScreenCaptureKitは 画面共有ピッカーに通知し ストリームのコントロール付き ライブプレビューが 新しいビデオのメニューバー項目に 表示されます ビデオのメニューバーにはアクティブな ストリームを持つすべてのアプリが表示され 任意のアプリに関連付けられたストリームの ライブプレビューが表示されます このメニューバーから ストリーム全体の 画面共有ピッカーを表示して ストリームのコンテンツを 制御できるようになります また ここで プレゼンターオーバーレイが有効になり コンテンツストリームに カメラフレームが埋め込まれます これを使用して 画面共有を置き換えたり 終了したりするなど ストリームを制御することもできます このほかにもカメラやマイクのエフェクトを カスタマイズする便利な機能があります
ScreenCaptureKitとカメラを 一緒に使う― アプリはすべて自動的に これらの機能が使えるようになります 現在 ストリームには ScreenCaptureKitから そのプロセスに送られる コンテンツフレームがあります 現在 アクティブなストリーム中に アプリがカメラの使用を開始すると ビデオメニュー項目で Presenter Overlayが使用可能になります 有効にすると ScreenCaptureKitが カメラを取り込み アプリが実行中の 選択したストリームに レンダリングを適用します 合成されたフレームはアクティブな ストリームから自動的に取得されます プレゼンターオーバーレイが適用されたことを 明示的に知りたい場合は?
まず 新しいストリームを作成し デリゲートとしてselfを追加します そして SCStreamの 新しいデリゲートコールバック― outputEffectDidStartを実装します これがプレゼンターオーバーレイが 適用されたことを通知する方法です 通知されたらエフェクトが 開始または停止されたかを確認します プレゼンターオーバーレイは macOSシステムの新機能であり オーバーレイが適用される際に アプリが考慮すべき点が いくつかあります
プレゼンターオーバーレイがオンの場合 AVCaptureSessionは通常の ライブカメラストリームを送信しません これはオーバーレイで カメラが直接使用されるためです この変更を考慮し アプリのUIを 更新する絶好の機会です 例えば ビデオ会議アプリでは 共有コンテンツが カメラと混在することを考慮して 音声と映像の同期を 調整するとよいでしょう プレゼンターのカメラタイルを非表示にして 外観をより最適化することもできます プレゼンターオーバーレイは カメラとビデオ機能なので アプリは高いフレームレートに 最適化する必要があります
プレゼンターオーバーレイに加えて 新しいシステム全体の 画面共有ピッカーを利用することもでき アプリは共有したいコンテンツを 選択する方法を中心とした― 複数の機能と完全に統合することができます これらはストリームを作成するために 使用する一般的な構造です 現在では SSharableContentを 呼び出して 共有可能なすべての 画面コンテンツを取得します これを使用して SCContentFilterを作成します SCContentFilterはキャプチャの内容を 決定するために使用します 現在のところ SCCSharable Contentから作成しますが 今年の新機能としてピッカーからコンテンツ フィルタを取得できるようになります ピッカーがSCContentFiltersを 生成する方法は2つあります 1つ目は システムのピッカーを使って コンテンツを共有する方法です 2つ目は 開いているウインドウから コンテンツを選択する方法です どちらの場合も システムは SCContentFilterをアプリと共有します しかし どうやって新しいコンテンツ フィルタをアプリに取り込むのでしょうか 新しいAPIである SCContentSharingPickerを使います SCContentSharingPickerは アプリとOS間の インターフェイスとして機能し 新しいストリーム 要求およびコンテンツフィルタ そして現在のストリームと コンテンツフィルタの更新を伴う デリゲートコールバックを提供します SCContentSharingPickerは ウインドウ アプリあるいはディスプレイに 基づいたコンテンツの選択が可能なシステム レベルのコンテンツピッカーを内蔵します アプリのボタン 新しいビデオのメニューバー またはウインドウから直接 コンテンツの選択を開始しても アプリは SCContentSharingPickerを利用して 進行中のストリームのアクティブな選択を 追加 削除または置き換えることができます また SCContentSharingPickerには 新しいストリームがリクエストされた際に アプリが通知を受けるための 組み込みのストリーム リクエストコールバックもあります 最後に 各ストリームに システムのエクスペリエンスが 適用される方法を定義できるストリーム ごとのカスタマイズ機能も備えています SCStreamのフィルタを 取得するためのコンストラクトは SCSharableContentを 使用することから SCContentSharingPicker― シングルトンを使用して SCContentFilterを返す― システムピッカーインターフェイスを 使用することになりました アプリがこの新しい 画面共有ピッカーを利用するのが いかに簡単かをお見せしましょう SCContentSharingPickerの 共有インスタンスから始めて selfをオブザーバーとして追加し 適切なクラスのコールバックを すべて取得できるようにします システムに私のピッカーインスタンスを 認識させるため アクティブに設定します アクティブにすると システムはあなたのピッカーを認識し あなたのアプリはシステムUIに含まれ 人々がピッカーと やりとりできるようになります ピッカーからウインドウを選択する ストリームを作りたいので シングルトンメソッド picker.presentを呼び出し nilと提示したい ピッカースタイルを渡します UIボタンを押すとピッカーが表示され キャプチャしたいウインドウを 選択できるようになります コンテンツが選択されると observerコールバックを通して 新しいフィルタが通知されます このフィルタを使用して新しいストリームを 作成するか 既存のストリームを更新することができます 残りのオブザーバーコールバックも 同様に重要です ピッカーを再度セットアップし アクティブにして提示します またピッカーの提示を要求したときに 失敗したかどうかを知りたいでしょう 失敗した場合は アプリに通知を投稿して 人々に知らせましょう また ピッカーが提示されたが キャンセルされた つまりコンテンツが ピックされなかった場合は それに応じてストリームの状態を設定します
SCContentSharingPickerには ストリーム単位で システムの動作をカスタマイズできる メソッドも用意されています SCContentSharingPickerConfiguration では 複数のカスタマイズが可能です AllowedPickingModesは ウインドウ アプリおよび コンテンツフィルタ表示選択間で許可される ピッキングモードをシステムに伝えます また excludedWindowIDs と bundleIDsを明示的に宣言し システムエクスペリエンスでのピックを 許可しないこともできます 変更されたくないストリームがある場合 SCContentSharingPickerConfiguration に 機能を強制できるプロパティがあります まず 共有ピッカーの インスタンスを取得します selfをオブザーバとして追加し ピッカーをアクティブに設定します 次に 適切な コンフィギュレーション設定を行います このストリームでは おそらく2つの特定の アプリの選択を除外し 再ピッキングを許可したくないでしょう 設定がセットアップされたらピッカーで set configurationを呼び出し 設定とアプリ ストリームを渡します
ピッカーは指定されたストリームに対して どのように動作するか正確にわかります また アプリのニーズに合わせて ストリームごとに 異なるピッカー設定も可能です
全ScreenCaptureKitストリームが macOSエクスペリエンスに統合され どのアプリでもプレゼンターオーバーレイ などの新機能を利用できるようになったのです そして 新しいシステムピッカーUIに アプリを統合する― 新しいAPI SCContentSharing Pickerを紹介しました しかし あなたのアプリにおける 画面キャプチャはライブストリームに限らず 様々な用途があります そこで新しいスクリーンショットAPIについて 詳しく説明するために 同僚のNatalieに引き継ぎます Natalie: ありがとう Christopher 今年ScreenCaptureKitに 新しいAPIが追加され 画面から静止画を簡単に 取り出せるようになりました 新しいスクリーンショットAPIは ScreenCaptureKitの ストリーミングの利点を スクリーンショットにもたらします アプリやウインドウによる 高度なフィルタリング 複数のピクセル形式や色空間 カーソルの可視性などの オプション機能が利用できます これで使い慣れたScreenCaptureKitの 構造体を使用して 必要な画面コンテンツの画像を 効率的に取得できるようになります
新しいAPIは非同期です 出力画像にはCMSampleBuffer またはCGImageフォーマットを 選択できます CMSampleBufferオプションには 利用可能なピクセルフォーマットが 追加されており 特定の フォーマットに関心がある場合に便利です コードですでにCGImageを 使用している場合は このフォーマットを使用すると 簡単に統合できます どちらのフォーマットでも スクリーンショットは ScreenCaptureKitストリーミングと ほとんど同じ設定オプションを使用し 同様のセットアップフローに従います CGWindowListCreateImageを 使用している場合 ScreenCaptureKit への移行を 簡単にするものがいくつかあります CGWindowList API で使用できる すべてのウインドウ画像オプションは ScreenCaptureKitの SCStreamConfigurationクラスの 中にあります 特定のウインドウID以上の すべてのウインドウを取得するような ウインドウリストのオプションは SCShareableContent 内で提供されます また CGImage出力の扱いに 慣れている場合 新しいスクリーンショットAPI は 既存のコードに 簡単に統合できるCGImage 出力フォーマットを提供します スクリーンショットの撮影は ScreenCaptureKitストリーミングと 同様のフローをたどりますが SCStreamを作成する代わりに スクリーンショットAPI を呼び出します 始めに ストリームの作成と同様に SCShareableContent を使用して 必要なコンテンツを取得し SCContentFilterを作成します SCStreamConfigurationに対し スクリーンショットに必要な すべてのオプションを設定することを 忘れないでください コンテンツフィルタと ストリームコンフィギュレーションが できたら スクリーンショットAPIを 呼び出して渡します このAPI は SCScreenshotManager クラスのクラスメソッドなので スクリーンショットを撮るために SCScreenshotManagerオブジェクトを 作成する必要はありません スクリーンショット画像の準備ができたら 選択したフォーマットで 非同期に返されます また 新しいシステムピッカーを使って コンテンツフィルタを作成し それを使ってスクリーンショットAPIを 呼び出すこともできます これは 直感的な方法で 欲しいコンテンツを選ぶことを可能にする 素晴らしい方法となるでしょう スクリーンショットを撮るとき APIには2つのバージョンがあり 必要なものによって選ぶことができます 1つはCMSampleBuffer出力タイプ用 もう1つはCGImage出力タイプ用です それ以外では 2つは同じように動作し 非同期にスクリーンショットを返します 以下にスクリーンショットAPIの 使用方法のコード例を示します まず SCContentFilter とSCStream Configurationをセットアップします 準備ができたら スクリーンショットAPIを呼び出して APIが返すのを待てば スクリーンショットが得られます これがScreenCaptureKitの 新機能のすべてです 要約すると SCContentFilterを 作成するための新しいAPIがあり システムレベルのUIを使用して アプリと完全に統合された 画面共有エクスペリエンスを作成します 新しいプレゼンターオーバーレイ 動画エフェクトは よりダイナミックな画面共有体験を提供し 新しいスクリーンショットAPIは ScreenCaptureKitの力で 1 回限りの画面キャプチャを取得できます ScreenCaptureKitの詳細は 昨年のセッション 「Meet ScreenCaptureKit」 と 「Take ScreenCaptureKit to the next level」をご覧ください
ご視聴ありがとうございました
-
-
3:32 - Set up delegate for stream
// Set up delegate for stream let stream = SCStream(filter: filter, configuration: config, delegate: self) // delegate method for Presenter Overlay applied func stream(_ stream: SCStream, outputEffectDidStart didStart: bool) { // if Presenter Overlay is on, present banner in app to notify if didStart == true { presentBanner() turnOffCamera() } else { turnOnCamera() } }
-
6:48 - Set up content sharing picker instance
// Set up content sharing picker instance let picker = SCContentSharingPicker.shared() picker.addObserver(self) picker.active = true // show system level picker button func showSystemPicker(sender: UIButton!) { picker.present(for stream: nil, using contentStyle:.window) } // observer call back for picker func contentSharingPicker(_ picker: SCContentSharingPicker, didUpdateWith filter: SCContentFilter, for stream: SCStream?) { if let stream = stream { stream.updateContentFilter(filter) } else { let stream = SCStream(filter: filter, configuration: config, delegate: self) } }
-
7:41 - Observer call back for picker did fail and did cancel
// Set up content sharing picker instance let picker = SCContentSharingPicker.shared() picker.addObserver(self) picker.active = true // show system level picker button func showSystemPicker(sender: UIButton!) { picker.present(for stream: nil, using contentStyle:.window) } // observer call back for picker did fail func contentSharingPicker(contentSharingPickerStartDidFailWith error:NSError) { if error { presentNotifications(error: error) } } // observer call back for picker did cancel func contentSharingPicker(_ picker: SCContentSharingPicker, didCancel for stream: SCStream?) { if stream { resetStateForStream(stream: stream) } }
-
8:41 - Per-stream configuration
// Set up content sharing picker instance let picker = SCContentSharingPicker.shared() picker.addObserver(self) picker.active = true // Create configurations let pickerConfig = SCContentSharingPickerConfiguration() // Set Picker configuration pickerConfig.excludedBundleIDs = [“com.foo.myApp”,”com.foo.myApp2”] pickerConfig.allowsRepicking = true // Create configurations picker.setConfiguration(pickerConfig, for: stream) func showSystemPicker(sender: UIButton!) { picker.present(for stream: nil, using contentStyle:.window) }
-
12:26 - Call the screenshot API
// Call the screenshot API class SCScreenshotManager : NSObject { class func captureSampleBuffer(contentFilter: SCContentFilter, configuration: SCStreamConfiguration) async throws -> CMSampleBuffer class func captureImage(contentFilter: SCContentFilter, configuration: SCStreamConfiguration) async throws -> GImage }
-
12:44 - Take a screenshot with ScreenCaptureKit
// Don't forget to customize the content you want in your screenshot // Use SCShareableContent or SCContentSharingPicker to pick your content let display = nil; // Create your SCContentFilter and SCStreamConfiguration // Customize these lines to use the content you want and desired config options let myContentFilter = SCContentFilter(display: display, excludingApplications: [], exceptingWindows: []); let myConfiguration = SCStreamConfiguration(); // Call the screenshot API and get your screenshot image if let screenshot = try? await SCScreenshotManager.captureSampleBuffer(contentFilter: myContentFilter, configuration: myConfiguration) { print("Fetched screenshot.") } else { print("Failed to fetch screenshot.") }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。