스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
ScreenCaptureKit으로 HDR 콘텐츠 캡처하기
ScreenCaptureKit으로 HDR 색상을 캡처하는 방법을 알아보고 HDR 지원, 마이크 캡처, 녹화본을 즉시 파일로 저장하기 등 새로운 기능을 확인해 보세요.
챕터
- 0:00 - Introduction and ScreenCaptureKit recap
- 1:20 - Capture HDR content
- 7:14 - Add microphone output
- 8:41 - Record to file
리소스
관련 비디오
WWDC24
WWDC23
WWDC22
-
다운로드
안녕하세요 저는 Ben이고 ScreenCaptureKit 팀의 소프트웨어 엔지니어입니다 사람들은 매일 ScreenCaptureKit으로 화면을 공유해 화상 회의에서 전 세계 다른 사람들과 고품질 스트림을 공유하고 스크린샷을 찍고 원격 데스크톱 응용 프로그램을 지원합니다 ScreenCaptureKit을 사용하면 앱이 시스템 UI 환경과 통합됩니다 앱의 내장 선택기를 표시해 익숙한 방식으로 스트림 콘텐츠를 선택할 수 있습니다
발표자 오버레이를 사용하면 앱의 화면 공유 환경을 개선할 수 있습니다 시스템 UI에서 앱이 공유하는 내용을 미리 볼 수도 있습니다 ScreenCaptureKit이 앱에서 이러한 경험을 만드는 데 도움이 되는 몇몇 새로운 방법을 소개합니다 앱에 스트리밍 기능이 있다고 가정합니다 이제 HDR로 스트림과 스크린샷을 캡처할 수 있습니다 현재 앱이 화면 및 오디오 콘텐츠를 캡처할 수 있습니다 화면, 오디오 샘플을 제공하는 동일한 스트림에서 마이크 출력을 얻는 방법을 보여 드리겠습니다
앱이 녹화된 화면 콘텐츠를 사용하는 경우 편리한 녹화 API에 관심이 있으실 겁니다 ScreenCaptureKit은 모든 에셋 작성 정보를 처리합니다
HDR 콘텐츠를 캡처하는 방법을 이해하기 위해 먼저 화면과 오디오를 캡처하는 기본 사항을 살펴봅니다
다음은 앱에서 화면, 오디오 샘플을 수신하는 데 사용하는 객체인 SCStream입니다 전체 화면이나 특정 윈도우 앱 캡처에 사용할 수 있습니다
SCContentFilter를 제공해 스트림에 캡처 대상을 알립니다 다른 해상도나 픽셀 포맷을 지정하는 등 스트림 출력을 사용자 지정하고 싶다고 가정해 보겠습니다 SCStreamConfiguration으로 스트림 출력을 맞춤화합니다
스트림을 설정한 후에는 SCStreamOutput으로 화면 및 오디오 샘플을 수신할 수 있습니다
이는 콘텐츠 캡처의 기본 구성 요소이며, 자세한 내용은 이전 ScreenCaptureKit 비디오를 확인하세요
올해부터 HDR 콘텐츠를 캡처할 수 있게 되었습니다 HDR(High Dynamic Range)은 SDR(표준 명암 대비)에 비해 더 넓은 범위의 밝기 수준과 색상을 제공합니다 HDR은 높은 명암비로 그림자와 하이라이트 모두에 더 많은 디테일을 표현합니다
또한 더 넓은 범위의 색상을 제공합니다
이제 SCStream이 캡처한 콘텐츠의 HDR을 출력한다는 소식을 전해 드립니다 이제 스트리밍 HDR 콘텐츠를 수신하는 사람들은 원본과 동일한 풍부한 디테일을 경험할 수 있습니다
앱에서 HDR 캡처를 활성화하려면 SCStreamConfiguration에서 몇 가지 새 속성을 설정하여 스트림을 구성합니다 다음과 같은 속성입니다
captureDynamicRange는 화면 콘텐츠를 SDR이나 HDR로 출력하도록 합니다 HDR은 hdrLocalDisplay나 hdrCanonicalDisplay로 설정합니다 그런데 로컬 디스플레이와 표준 디스플레이는 뭘까요?
로컬 디스플레이를 사용하면 ScreenCaptureKit에 같은 화면에서 HDR 콘텐츠의 캡처, 렌더링을 알리는 겁니다
표준 디스플레이의 경우 다른 HDR 기기와 공유하기 최적화된 HDR 콘텐츠를 캡처하고 있다는 겁니다
다음으로 구성할 속성은 pixelFormat입니다 이미지의 각 픽셀에 대한 색상 정보의 저장 방식을 설명합니다
HDR은 구성요소당 10비트 이상 포맷을 사용합니다 대부분 10비트 YCbCr이 최선의 선택입니다
세 번째 속성은 colorSpaceName이고 색상 범위와 디지털 값에 매핑하는 방법에 대한 전달 함수를 설명합니다 HDR에는 HLG 또는 PQ 전달 함수가 필요한데 디스플레이 P3 PQ 색상 공간이 그 예입니다
마지막으로 BGRA와 YCbCr 색상 공간 사이 색을 변환하는 데 사용되는 colorMatrix가 있습니다 정보가 많게 느껴지지만 걱정하지 마세요 SCStreamConfiguration이 있기 때문입니다 이는 2개의 편리한 HDR용 프리셋을 제공합니다 captureHDRStreamLocalDisplay captureHDRStreamCanonicalDisplay죠
캡처된 HDR 콘텐츠 대상이 로컬 디스플레이인 경우 Local Display 프리셋을 사용합니다 이 구성은 여기에 포함된 값으로 미리 채워집니다
HDR 콘텐츠의 대상이 다른 디스플레이인 경우 Canonical Display 프리셋을 사용합니다 이 프리셋의 값은 여기에 나와 있습니다 앱에 다른 출력 설정이 필요한 경우 앱의 필요에 맞게 이 속성을 자유롭게 변경할 수 있습니다 이제 프리셋을 사용해 HDR을 캡처하는 코드 예제입니다
SCShareableContent를 사용해 가용 콘텐츠 목록을 가져옵니다
전체 디스플레이가 여기에 캡처되므로 전체 디스플레이를 캡처 가능한 SCContentFilter를 만듭니다 새 프리셋 API를 사용해 HDR 표준 디스플레이의 구성을 가져옵니다
필터와 구성을 사용해 SCStream을 만듭니다
앱에서 HDR 화면 샘플을 받으려면 화면 유형으로 출력을 추가합니다
이제 스트림을 시작해 HDR 샘플을 받기 시작합니다 앱에 스트림 대신 스크린샷이 하나 필요하다고 가정해 봅니다 SCScreenshotManager는 스크린샷 API를 제공합니다 이 API를 사용하여 HDR로 스크린샷을 찍을 수도 있습니다
SCStream과 같이 SCScreenshotManager는 콘텐츠 필터와 스트림 구성을 사용합니다 SCStream처럼 HDR 스크린샷에 프리셋 사용이 가능합니다 다음은 로컬 또는 표준 디스플레이용 HDR 스크린샷에 권장되는 사전 설정 값입니다
이제 로컬 디스플레이 프리셋을 사용해 HDR 스크린샷을 찍는 코드의 예입니다
먼저 HDR 로컬 디스플레이용 구성을 만들어야 합니다 앱에 스크린샷을 위해 CMSampleBuffers가 필요하면 captureSampleBuffer 함수를 사용합니다
CGImage를 선호하면 captureImage를 사용합니다
이렇게 새 API를 사용해 스트림과 스크린샷 모두에서 멋진 HDR 콘텐츠를 얻을 수 있습니다 앱에서 HDR을 활용하는 방법을 자세히 알아보려면 HDR 이미지 및 미디어 지원 비디오를 확인하세요 이제 ScreenCaptureKit으로 HDR 이미지, 비디오를 캡처합니다 올해부터 시스템 오디오와 함께 마이크를 녹화해 멋진 HDR 스트림을 만들 수 있습니다 이제 스트림에 새 마이크 출력을 제공해 앱에서 화면, 시스템 오디오 마이크라는 세 가지 미디어를 캡처할 수 있습니다
앱이 스트림의 마이크 오디오 캡처에 필요한 새 2개 속성을 SCStreamConfiguration에서 제공합니다 captureMicrophone으로 앱에서 마이크 캡처를 켤 수 있습니다 microphoneCaptureDeviceID로 캡처할 마이크 기기를 선택할 수 있습니다
앱에서 마이크 샘플을 받으려면 SCStreamOutput을 사용합니다 이제 마이크 오디오를 캡처하는 몇 가지 코드를 살펴봅니다 먼저 스트림 구성을 생성해 SCStream에 마이크를 캡처하도록 지시합니다 기본 마이크를 캡처하도록 captureMicrophone 및 microphoneCaptureDeviceID 속성을 설정합니다 필터와 구성으로 SCStream을 만듭니다 여기서 새 마이크 유형으로 스트림에 출력을 추가합니다 이제 캡처를 시작하고 SCStreamOutput의 didOutputSampleBuffer 함수로 샘플을 받습니다 그러면 됩니다 앱이 SCStream의 화면, 오디오 마이크 콘텐츠를 다 가져옵니다 스트림 출력 수신의 가장 일반적인 용도 중 하나는 샘플을 파일에 쓰는 것입니다 이제 SCStream에 추가된 새 API를 사용해 이 작업을 할 수 있습니다 이 API를 사용해 앱에서 화면, 오디오 마이크 콘텐츠를 쉽게 녹화하고 저장할 수 있습니다 이제 작동 방식을 살펴보겠습니다 이전처럼 콘텐츠를 캡처하도록 SCStream을 구성합니다 녹화에도 동일한 스트림을 사용합니다 녹화하려면 이 새 출력을 추가하면 됩니다 SCRecordingOutput은 SCRecordingOutputConfiguration을 사용해 구성 가능한데 이 구성으로 파일 저장 위치 파일 유형, 비디오 코덱을 지정할 수 있습니다
스트림의 녹화 이벤트 응답에 사용할 수 있는 SCRecordingOutputDelegate 프로토콜도 있습니다 이제 이 새 API로 녹화하는 코드를 확인해 봅니다 SCRecordingOutputConfiguration 인스턴스를 생성합니다 outputURL을 설정해 파일 저장 위치를 지정합니다
저장된 파일의 유형, 비디오 코덱을 맞춤화할 수 있습니다 그 다음 녹화 구성으로 SCRecordingOutput 인스턴스를 만들고 이벤트 수신용 대리자를 설정합니다
구성된 recordingOutput을 스트림에 추가합니다 startCapture 호출로 스트림 시작 시 녹화도 시작됩니다 이후 stopCapture를 호출해 스트림과 녹화를 모두 중지할 수 있습니다 일부 경우 녹화 중단 후에도 스트리밍은 원할 수 있습니다 콘텐츠 스트리밍을 계속하려면 removeRecordingOutput을 호출해 녹화만 중지합니다
녹화하는 동안 앱이 SCRecordingOutputDelegte로 이벤트에 대한 알림을 받습니다 녹화 시작 시 오류 발생 시 녹화의 성공적인 완료 시 알림을 받게 됩니다 이제 녹화된 파일을 앱에서 사용할 준비가 됐습니다
이게 전부입니다 이 새 녹화 API는 앱에서 화면, 오디오, 마이크 콘텐츠의 간단하고 편리한 저장 방법을 제공합니다
즉, ScreenCaptureKit으로 앱 HDR 콘텐츠를 캡처합니다 스트림에서 마이크 샘플을 받는 새 마이크 출력을 사용할 수 있습니다 마지막으로, 화면, 오디오 마이크 콘텐츠를 쉽게 녹화할 수 있는 새 녹화 API가 추가됐습니다 ScreenCaptureKit의 놀라운 기능을 자세히 알아보려면 이전 동영상을 확인하세요 시청해 주셔서 정말 감사합니다
-
-
5:22 - Capture HDR
// Get content that is currently available for capture. let availableContent = try await SCShareableContent.current // Create instance of SCContentFilter to record entire display. guard let display = availableContent.displays.first else { return } let filter = SCContentFilter(display: display, excludingWindows: []) // Create a configuration using preset for HDR stream canonical display. let config = SCStreamConfiguration(preset: .captureHDRStreamCanonicalDisplay) // Create a stream with the filter and stream configuration. let stream = SCStream(filter: filter, configuration: config, delegate: self) // Add a stream output to capture screen content. try stream.addStreamOutput(self, type: .screen, sampleHandlerQueue: nil) // Start the capture session. try await stream.startCapture()
-
6:40 - Use a local display preset to capture HDR
// Create an SCStreamConfiguration with preset for HDR. let config = SCStreamConfiguration(preset: .captureHDRScreenshotLocalDisplay) // Call the screenshot API to get CMSampleBuffer representation let screenshotBuffer = try await SCScreenshotManager.captureSampleBuffer(contentFilter: filter, configuration:config) // Call the screenshot API to get CGImage representation. let screenshotImage = try await SCScreenshotManager.captureImage(contentFilter: filter, configuration:config)
-
8:05 - Capture samples of microphone audio
// Create instance of SCStreamConfiguration. let config = SCStreamConfiguration() // Enable microphone capture and set id of microphone to capture. config.captureMicrophone = true config.microphoneCaptureDeviceID = AVCaptureDevice.default(for: .audio)?.uniqueID // Create an SCStream instance. let stream = SCStream(filter: filter, configuration: config, delegate: self) // Add stream outputs for capturing screen and microphone. try stream.addStreamOutput(self, type: .screen, sampleHandlerQueue: nil) try stream.addStreamOutput(self, type: .microphone, sampleHandlerQueue: nil) // Start the capture session try await stream.startCapture() // Implement SCStreamOutput function to receive samples. func stream(_ stream: SCStream, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, of type: SCStreamOutputType) { switch type { case .screen: handleLatestScreenSample(sampleBuffer) case .audio: handleLatestAudioSample(sampleBuffer) case .microphone: handleLatestMicrophoneSample(sampleBuffer) } }
-
9:38 - Record to file
// Create a recording output configuration. let recordingConfiguration = SCRecordingOutputConfiguration() // Configure the outputURL (optionally set file type and video codec). recordingConfiguration.outputURL = url recordingConfiguration.outputFileType = .mov recordingConfiguration.videoCodecType = .hevc // Create the recording output with the configuration. let recordingOutput = SCRecordingOutput(configuration: recordingConfiguration, delegate: self) // Add an SCRecordingOutput to the stream. try stream.addRecordingOutput(recordingOutput) // Start capturing (which will also start recording). try await stream.startCapture() // Stop recording. try await stream.stopCapture() //OR // Stop recording, but keep stream running. try stream.removeRecordingOutput(recordingOutput)
-
10:27 - Respond to delegate events
func recordingOutputDidStartRecording(_ recordingOutput: SCRecordingOutput) { // Recording started asynchronously after addRecordOutput. } func recordingOutput(_ recordingOutput: SCRecordingOutput, didFailWithError error: Error) { // Recording failed with error. } func recordingOutputDidFinishRecording(_ recordingOutput: SCRecordingOutput) { // Recording finished after calling either removeRecordOutput or stopCapture. }
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.