-
빠르게 실행되는 반응성이 뛰어난 카메라 앱 빌드하기
완벽한 순간을 절대 놓치는 일이 없도록 즉시 실행되는 카메라 앱을 빌드하는 방법을 알아보세요. 앱 시동부터 첫 번째 미리보기 프레임까지, 전체 카메라 실행 시퀀스를 최적화하는 방법을 살펴보세요. 더 빠른 실행을 지원하는 새로운 API와 원활한 미리보기 렌더링 및 지속 가능한 성능 유지를 위한 모범 사례에 대해 알아보고 앱에서 세련된 카메라 경험을 선사해 보세요.
챕터
- 0:00 - Introduction
- 2:02 - Fast Launch
- 6:52 - Adopt deferred start
- 15:06 - Steady preview
- 18:04 - Sustained performance
- 21:14 - Deterministic file writing
리소스
관련 비디오
WWDC26
WWDC23
-
비디오 검색…
-
-
9:14 - Automatic deferred start delegate
import AVFoundation class DeferredStartDelegate: NSObject, AVCaptureSessionDeferredStartDelegate { func sessionWillRunDeferredStart(_ session: AVCaptureSession) { // This is called before deferred start begins for the deferred outputs } func sessionDidRunDeferredStart(_ session: AVCaptureSession) { // This is called after deferred start completes for all outputs } } -
9:46 - Adopt automatic deferred start
import AVFoundation let captureSession = AVCaptureSession() captureSession.beginConfiguration() captureSession.automaticallyRunsDeferredStart = true let videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession) videoPreviewLayer.isDeferredStartEnabled = false let photoOutput = AVCapturePhotoOutput() photoOutput.isDeferredStartEnabled = true captureSession.addOutput(photoOutput) captureSession.setDeferredStartDelegate(deferredStartDelegate, deferredStartDelegateCallbackQueue: sessionQueue) captureSession.commitConfiguration() captureSession.startRunning() -
11:30 - Adopt manual deferred start
import AVFoundation let captureSession = AVCaptureSession() captureSession.beginConfiguration() captureSession.automaticallyRunsDeferredStart = false let videoOutput = AVCaptureVideoDataOutput() captureSession.addOutput(videoOutput) videoOutput.isDeferredStartEnabled = false let photoOutput = AVCapturePhotoOutput() photoOutput.isDeferredStartEnabled = true captureSession.addOutput(photoOutput) captureSession.setDeferredStartDelegate(deferredStartDelegate, deferredStartDelegateCallbackQueue: sessionQueue) captureSession.commitConfiguration() captureSession.startRunning() -
11:53 - Manage runDeferredStartWhenNeeded
import AVFoundation import QuartzCore private var firstFramePresented = false guard let drawable = layer.nextDrawable() if (!firstFramePresented) { drawable.addPresentedHandler({ drawable in // Set up postponed UI elements captureSession.runDeferredStartWhenNeeded() }) firstFramePresented = true } -
14:07 - Enable responsive capture
import AVFoundation func configurePhotoOutput(for session: AVCaptureSession, device: AVCaptureDevice) { let photoOutput = AVCapturePhotoOutput() guard session.canAddOutput(photoOutput) else { return } session.addOutput(photoOutput) photoOutput.maxPhotoQualityPrioritization = .quality // Responsive capture lets the photo output capture immediately photoOutput.isResponsiveCaptureEnabled = photoOutput.isResponsiveCaptureSupported } -
20:16 - Monitor for system pressure
import AVFoundation let captureSession = AVCaptureSession() let device = activeVideoInput?.device captureSession.beginConfiguration() // ... captureSession.commitConfiguration() guard captureSession.hardwareCost <= 1.0 else { print("hardwareCost \(captureSession.hardwareCost) — cannot start session. Reconfiguring.") setupLowCostConfiguration() } captureSession.startRunning() let systemPressureObserver = device?.observe(\.systemPressureState, options: [.initial, .new], changeHandler: { /* Handle state change */ }) -
22:17 - Manage pro video storage
import AVFoundation func configureProVideoStorage() { guard AVProVideoStorage.isSupported else { return } let storage = AVProVideoStorage.shared guard storage.remainingCapacity != 0 else { storage.openSettings() return } } -
22:43 - Adopt AVProVideoStorage for deterministic file write speeds
import AVFoundation guard AVProVideoStorage.isSupported else { return } guard let pvs = AVProVideoStorage.shared else { return } // Configure and set up AVCaptureSession, AVCaptureConnections and format // ... let movieOutput = AVCaptureMovieFileOutput() guard movieOutput.isProVideoStorageSupported else { return } guard !pvs.isBusy else { return } let movieFileURL = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString) .appendingPathExtension("mov") movieOutput.usesProVideoStorage = true // Also available with AVAssetWriter movieOutput.startRecording(to: movieFileURL, recordingDelegate: delegate)
-
-
- 0:00 - Introduction
Why a fast-appearing preview frame is the single biggest factor in a camera launch feeling responsive, and what the session covers — accelerating launch, rendering best practices, and capturing the moment without missing it.
- 2:02 - Fast Launch
Learn how to minimize UI overhead and explore best practices for creating and configuring AVCaptureSession to get the camera preview on screen faster.
- 6:52 - Adopt deferred start
Discover the deferred start API that allows you to defer the initialization of expensive capture outputs until after the preview is running, featuring both automatic and manual modes.
- 15:06 - Steady preview
Explore best practices for rendering preview frames, comparing the simplicity of AVCaptureVideoPreviewLayer against the flexibility of AVCaptureVideoDataOutput.
- 18:04 - Sustained performance
Learn how to assess hardware cost and adapt to system pressure using new APIs to maintain a smooth and responsive camera experience under demanding conditions.
- 21:14 - Deterministic file writing
Adopt the AVProVideoStorage API to achieve sustained high-bandwidth input/output required for high data-rate video captures like ProRes.