ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
ScreenCaptureKitの紹介
ScreenCaptureKitが、macOSの画面共有・ビデオ会議・ゲームストリーミングサービスなどのAppに、高性能のスクリーンキャプチャを提供する仕組みについて解説します。このAPIの構成要素について解説し、ストリームを設定して画面上の動画およびオーディオコンテンツをキャプチャする方法や、それを既存のAppに統合するためのヒントを紹介します。
リソース
関連ビデオ
WWDC23
WWDC22
-
ダウンロード
(音楽)
こんにちは 僕はErnest ScreenCaptureKitチームの ソフトウェアエンジニアです この2年間 リモートでの共同作業で しばしば画面の共有を行います
それに加え OBS Studioのような録画アプリケーションを 使ったゲームプレイのストリーミングや コンテンツ制作そのものが 教育や娯楽において成長し続けています
このような背景から開発者のニーズに応え パフォーマンスと堅牢性に優れた スクリーンキャプチャーの フレームワークを作りました ScreenCaptureKitです
これはmacOSの新しいフレームワークで Appにおける画面共有を 実現します ScreenCaptureKit は アプリケーションのニーズに合わせて デベロッパのコントロールやトグルを使って キャプチャしたいコンテンツを 選択可能な API を提供します フィルターやコントロールは 即座に更新できます
このフレームワークはディスプレイの ネイティブの解像度や フレームレートに対応する 最高の品質と性能を実現し プライバシーにも重点を置いています
このセッションでは ScreenCaptureKit を 使い始めるためのお手伝いをします
基本を押さえた上で 「Take ScreenCaptureKit to the next level」で より高度なトピックをご覧ください
まずフレームワークの主な機能を説明します
次に ScreenCaptureKit の主な構成要素について API の概要を説明します
次にフィルタと設定を使ってストリームを セットアップする方法を説明します
そして最後にビデオとオーディオのサンプルを アプリケーションに ストリーミングする方法を説明します
では 主な特徴からです
ScreenCaptureKitは共有したいコンテンツや 除去したいコンテンツの種類を指定できます ディスプレイ アプリケーション ウィンドウの あらゆる組み合わせから 画面のコンテンツをキャプチャでき それに付随する音声もキャプチャできます
ScreenCaptureKitは ピクセルフォーマット 色空間 フレームレート 解像度 そしてオーディオ側ではサンプルレートや チャンネル数などのコントロールなど さまざまな開発者向けコントロールを サポートしています
これらのフィルターや設定は オンザフライで調節でき より柔軟なAppデザインが可能です
最大48kHzステレオの音声と ディスプレイのネイティブ解像度 フレームレートの映像を取り込むために 既存のキャプチャ方法よりも低い CPU オーバーヘッドで Mac GPU のパワーを活用します もちろんScreenCaptureKit はプライバシーを 考慮して構築されており すべてのアプリケーションに対して グローバルなプライバシー保護機能を提供します
映像と音声を取り込む前に承諾が必要で システム環境設定の Screen Recordingのプライバシー設定に 保存されます
ScreenCaptureKitが何かわかったところで APIの最も重要な概念をお見せしましょう ScreenCaptureKitの中心はSCStreamです
SCStreamはstartやstopなどの 制御メソッドを扱い SCShareableContentとSCContentFilter SCStreamConfigurationと共に作られます
これらは何のコンテンツをどう取り込むか 決定します
いざ作成されスタートすると メディアサンプルは SCStreamOutputプロトコルで Appに配信されます 後ほど説明します
Appでのストリーム設定のAPIについてです
ストリームをセットアップする際に 知っておきたいオブジェクトを紹介します
これらのオブジェクトが キャプチャーの内容や品質 パフォーマンスを決定します
SCShareableContentから始めましょう
このデスクトップ上には ウィンドウ アプリケーション ディスプレイがあります
ScreenCaptureKitには 共有コンテンツ作成のため それぞれに対応するクラスがあります
まずはSCDisplayです
ディスプレイをSCDisplaysと分類し リードオンリーのDisplay identifierと サイズのWidthとHeightのプロパティがあります
ディスプレイ内で開いているAppにはそれぞれ SCRunningApplicationがあります
SCRunningApplicationsにはApp情報の リードオンリープロパティがあり それらはBundle identifierや Application nameとProcess identifierです
この例ではKeynoteとSafariの SCRunningApplicationがあります
そしてこれらのAppにはウィンドウがあります
これらのウィンドウにはSCWindowがあり それぞれを定義する リードオンリープロパティの Window IDやFrameとTitle そしてOn screenか最小化されてるかです
またSCWindowにはOwning applicationがあり
この場合 両方のSafariのSCWindowsに 同じowning applicationのSafariがあります
SCWindows SCRunningApplications SCDisplays が SCShareableContentにまとめられて 共有できるコンテンツを提供します デバイスの共有可能なコンテンツの リストを得るか パラメーターで指定できます
共有するものを選ぶために スクリーン上のAppや ウィンドウのリストが欲しい場合 ScreenCaptureKitにはシンプルなAPIがあります
このコードはdeveloper.apple.comにある サンプルコードの一部です
画面上にあるウィンドウだけが SCShareableContent で返され 関連する SCWindows SCApplications SCDisplays が含まれます
共有可能なコンテンツが得られたので フィルターを作ります
SCContentFiltersには2種類あります ディスプレイを指定しないフィルタは 複数のディスプレイのウィンドウを取得し ディスプレイ指定のフィルタは 特定のウィンドウやアプリケーションを 含めたり除外したりするオプションがあります
音声の取り込みはAppレベルでのみ フィルター可能です
ではフィルターのデモをお見せしましょう
Keynoteのウィンドウだけを共有したいとします
ディスプレイを指定しないフィルタを使って ディスプレイ間を移動する ウィンドウを取得します
ディスプレイ内のすべてを共有したい場合も 共有したくないものがあるかもしれません 例えばキャプチャを行う自身のAppを除外して 鏡の回廊効果を回避したいはずです
また機密情報が画面上に出ている場合も キャプチャの対象から外すべきです SCContentFilterがこれらをすべて処理します コードを見てみましょう
これは先ほどのコードです
共有可能なコンテンツを検索したら このサンプルコードと同じ Bundle IDのAppを探し
ディスプレイ指定のフィルターで そのAppを除外します
ScreenCaptureKitはストリーム毎に 品質と性能を調整できます
SCStreamConfigurationで設定します
映像の調整には出力解像度やフレームレート カーソルの有無などがあります
オーディオの方は オーディオでの有無やサンプルレート チャンネル数があります
これらを調整するシナリオを見てみましょう
メモやスプレッドシートなど 文字の鮮明度が重要なコンテンツの場合 出力解像度を4K フレームを10fpsにします
このコンテンツには音声がないので 音声をオフにしておきます
休暇のビデオの共有など 動きの多いコンテンツの場合 解像度よりフレームレートを優先し 出力解像度を1080pに下げ フレームレートを60fpsに増やします
カーソルは邪魔になるので カーソルを隠します
また音声を取り込めば没入感が高まります
これらの調整はSCStreamConfigurationで 行うことができます
動きの多いコンテンツの設定例です
ここでは出力解像度が1080pになっています minimum Frame Interval は 60fpsで取り込むために 1/60の設定です
そしてstreamConfigでカーソルを隠しています
音声では captures Audio を true にして音声を取り込み サンプルレートは48kHz チャンネル数は2です
SCContentFilter と SCStreamConfiguration で Appのニーズに応えた 取り込み設定に必要な情報が 得られました
これでSCStreamが作成できます
オーバービューに戻りましょう
フィルターとコンフィグで ストリームを初期化します
エラーの対応に デリゲートを追加できます
それからStart captureしScreenCaptureKitが サンプルをSCStreamで提供します
フィルタとコンフィグが作成されたので コードでストリームを開始するのは簡単です お見せしましょう
再びフィルターとコンフィグで SCStreamを初期化します
エラー処理のデリゲートとして self を指定
SCStreamを作成しStart captureを呼びます
ストリームの初期化と起動が完了したら 次のステップはメディアサンプルを アプリケーションに取り込むことです
音声と映像サンプルはCMSampleBuffersとして Appに送られます
それらのサンプルを得るためには SCStreamOutput プロトコルを 実装したオブジェクトを ストリームに追加する必要があります
ハンドラーキューも指定します
これは余分な dispatch なしに 特定のキューにサンプルを送るのに最適です
指定しなければデフォルトキューです
ストリームが始まるとサンプルができた時 コールバックを行います
では コードでメディアサンプルを得る方法です
SCStreamOutputプロトコルの 実装を示しています 新しいサンプルができると呼び出されます
CMSampleBuffersとしてサンプルが送られ ストリームとサンプルタイプを提供します
サンプルバッファのハンドラーを実装し StreamOutputを追加するだけです
これでストリームからのサンプルが 希望するコンテンツとフォーマットで Appに送られます
CMSampleBuffersとしてサンプルを配信するので 使い方について話しましょう
映像の方では CMSampleBuffer は IOSurface-backed です
SCStreamFrameInfo で CMSampleBufferにアタッチメントを 提供しています
これにはビデオサンプルの情報が含まれています
Frame Status で現在の ストリーム状況を確認します completeは新しいビデオフレームが あることを意味し idleはサンプルに変わりがないことを意味し 新しいIOSurfaceはありません
それ以外の場合提供されるサンプルは 他の CMSampleBuffer と同様なので 既存の CMSampleBuffer ユーティリティを 使用することができます
ScreenCaptureKit には画面上の 音声と映像を選択するAPIがあります さらにフレームワークは Appのニーズに応えるコントロールを提供します
キャプチャの方法の基本も ここでカバーしました
ScreenCaptureKitの登場でCGDisplayStreamや CGWindowListは近い将来非推奨となります
ScreenCaptureKitの導入が 皆様の助けとなることを願っています
さらに高度な情報は "ScreenCaptureKitを次のレベルに" をご覧ください
ありがとうございました (音楽)
-
-
6:53 - Creating a SCShareableContent object
// Creating a SCShareableContent object // Get the content that's available to capture. let content = try await SCShareableContent.excludingDesktopWindows( false, onScreenWindowsOnly: true )
-
8:32 - Creating a SCContentFilter object
// Creating a SCContentFilter object // Get the content that's available to capture. let content = try await SCShareableContent.excludingDesktopWindows( false, onScreenWindowsOnly: true ) // Exclude the sample app by matching the bundle identifier. let excludedApps = content.applications.filter { app in Bundle.main.bundleIdentifier == app.bundleIdentifier } // Create a content filter that excludes the sample app. filter = SCContentFilter(display: display, excludingApplications: excludedApps, exceptingWindows: [])
-
10:23 - Creating a SCStreamConfiguration object
// Creating a SCStreamConfiguration object let streamConfig = SCStreamConfiguration() // Set output resolution to 1080p streamConfig.width = 1920 streamConfig.height = 1080 // Set the capture interval at 60 fps streamConfig.minimumFrameInterval = CMTime(value: 1, timescale: CMTimeScale(60)) // Hides cursor streamConfig.showsCursor = false // Enable audio capture streamConfig.capturesAudio = true // Set sample rate to 48000 kHz stereo streamConfig.sampleRate = 48000 streamConfig.channelCount = 2
-
11:46 - Creating and starting a SCStream object
// Creating and starting a SCStream object // Create a capture stream with the filter and stream configuration stream = SCStream(filter: filter, configuration: streamConfig, delegate: self) // Start the capture session try await stream?.startCapture() // ... // Error handling delegate func stream(_ stream: SCStream, didStopWithError error: Error) { DispatchQueue.main.async { self.logger.error("Stream stopped with error: \(error.localizedDescription)") self.error = error self.isRecording = false } }
-
13:07 - Getting media samples
// SCStreamOutput protocol implementation func stream(_ stream: SCStream, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, of type: SCStreamOutputType) { switch type { case .screen: handleLatestScreenSample(sampleBuffer) case .audio: handleLatestAudioSample(sampleBuffer) } } // ... // Create a capture stream with the filter and stream configuration stream = SCStream(filter: filter, configuration: streamConfig, delegate: self) // Add a stream output to capture screen and audio content try stream?.addStreamOutput(self, type: .screen, sampleHandlerQueue: screenFrameOutputQueue) try stream?.addStreamOutput(self, type: .audio, sampleHandlerQueue: audioFrameOutputQueue) // Start the capture session try await stream?.startCapture()
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。