View in English

  • Apple Developer
    • Get Started

    Explore Get Started

    • Overview
    • Learn
    • Apple Developer Program

    Stay Updated

    • Latest News
    • Hello Developer
    • Platforms

    Explore Platforms

    • Apple Platforms
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store

    Featured

    • Design
    • Distribution
    • Games
    • Accessories
    • Web
    • Home
    • CarPlay
    • Technologies

    Explore Technologies

    • Overview
    • Xcode
    • Swift
    • SwiftUI

    Featured

    • Accessibility
    • App Intents
    • Apple Intelligence
    • Games
    • Machine Learning & AI
    • Security
    • Xcode Cloud
    • Community

    Explore Community

    • Overview
    • Meet with Apple events
    • Community-driven events
    • Developer Forums
    • Open Source

    Featured

    • WWDC
    • Swift Student Challenge
    • Developer Stories
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Centers
    • Documentation

    Explore Documentation

    • Documentation Library
    • Technology Overviews
    • Sample Code
    • Human Interface Guidelines
    • Videos

    Release Notes

    • Featured Updates
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • tvOS
    • Xcode
    • Downloads

    Explore Downloads

    • All Downloads
    • Operating Systems
    • Applications
    • Design Resources

    Featured

    • Xcode
    • TestFlight
    • Fonts
    • SF Symbols
    • Icon Composer
    • Support

    Explore Support

    • Overview
    • Help Guides
    • Developer Forums
    • Feedback Assistant
    • Contact Us

    Featured

    • Account Help
    • App Review Guidelines
    • App Store Connect Help
    • Upcoming Requirements
    • Agreements and Guidelines
    • System Status
  • Quick Links

    • Events
    • News
    • Forums
    • Sample Code
    • Videos
 

Videos

Abrir menú Cerrar menú
  • Colecciones
  • Todos los videos
  • Información

Más videos

  • Información
  • Resumen
  • Código
  • Captura videos cinematográficos en tu app

    Descubre cómo con la API Cinematic Video tu app puede capturar videos de estilo cinematográfico. Mencionaremos cómo configurar una sesión de captura cinematográfica y los fundamentos de la creación de una IU de captura de video. Y exploraremos funcionalidades cinematográficas avanzadas, como los efectos de profundidad de campo para lograr el seguimiento y el enfoque en rack.

    Capítulos

    • 0:00 - Introducción
    • 0:33 - Video cinematográfico
    • 3:44 - Crea una gran experiencia de captura cinematográfica

    Recursos

    • Capturing Cinematic video
    • Cinematic
    • AVCam: Building a camera app
    • AVFoundation
      • Video HD
      • Video SD

    Videos relacionados

    WWDC25

    • Mejora la experiencia con la cámara gracias a los controles de captura

    WWDC24

    • Build a great Lock Screen camera capture experience

    WWDC23

    • Create a more responsive camera experience
    • Discover Continuity Camera for tvOS
    • Support external cameras in your iPadOS app
  • Buscar este video…
    • 4:26 - Select a video device

      // Select a video device
      
      let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDualWideCamera], mediaType: .video, position: .back)
              
      guard let camera = deviceDiscoverySession.devices.first else {
          print("Failed to find the capture device")
          return
      }
    • 5:07 - Select a format that supports Cinematic Video capture

      // Select a format that supports Cinematic Video capture
      
      for format in camera.formats {
      
          if format.isCinematicVideoCaptureSupported {
      
             try! camera.lockForConfiguration()
             camera.activeFormat = format
             camera.unlockForConfiguration()
      
             break
          }
      
      }
    • 5:51 - Select a microphone

      // Select a microphone
      
      let audioDeviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes [.microphone], mediaType: .audio, position: .unspecified)
      
      guard let microphone = audioDeviceDiscoverySession.devices.first else {
          print("Failed to find a microphone")
          return
      }
    • 6:00 - Add devices to input & add inputs to the capture session & enable Cinematic Video capture

      // Add devices to inputs
      
      let videoInput = try! AVCaptureDeviceInput(device: camera)
      guard captureSession.canAddInput(videoInput) else {
          print("Can't add the video input to the session")
          return
      }
      
      let audioInput = try! AVCaptureDeviceInput(device: microphone)
      guard captureSession.canAddInput(audioInput) else {
          print("Can't add the audio input to the session")
          return
      }
      
      // Add inputs to the capture session
      
      captureSession.addInput(videoInput)
      captureSession.addInput(audioInput)
      
      // Enable Cinematic Video capture
      
      if (videoInput.isCinematicVideoCaptureSupported) {
        videoInput.isCinematicVideoCaptureEnabled = true
      }
    • 6:17 - Capture spatial audio

      // Configure spatial audio
      
      if audioInput.isMultichannelAudioModeSupported(.firstOrderAmbisonics) {
          audioInput.multichannelAudioMode = .firstOrderAmbisonics
      }
    • 6:33 - Add outputs to the session & configure video stabilization & associate the preview layer with the capture session

      // Add outputs to the session
      
      let movieFileOutput = AVCaptureMovieFileOutput()
      guard captureSession.canAddOutput(movieFileOutput) else {
          print("Can't add the movie file output to the session")
          return
      }
      captureSession.addOutput(movieFileOutput)
              
      
      // Configure video stabilization
      
      if let connection = movieFileOutput.connection(with: .video), 
          connection.isVideoStabilizationSupported {
          connection.preferredVideoStabilizationMode = .cinematicExtendedEnhanced
      }
      
      // Add a preview layer as the view finder
      
      let previewLayer = AVCaptureVideoPreviewLayer()
      previewLayer.session = captureSession
    • 7:11 - Display the preview layer with SwiftUI

      // Display the preview layer with SwiftUI
      
      struct CameraPreviewView: UIViewRepresentable {
      
          func makeUIView(context: Context) -> PreviewView {
              return PreviewView()
          }
      
          class CameraPreviewUIView: UIView {
      	
      			override class var layerClass: AnyClass {
          		AVCaptureVideoPreviewLayer.self
      			}
      
      			var previewLayer: AVCaptureVideoPreviewLayer {
        	  	layer as! AVCaptureVideoPreviewLayer
      			}
      
      			...
      		}
      
      ...
      }
    • 7:54 - Display the preview layer with SwiftUI

      // Display the preview layer with SwiftUI
      
      @MainActor
      struct CameraView: View {       
      
          var body: some View {
              ZStack {
                  CameraPreviewView()  
                	CameraControlsView()
              }
          }
      }
    • 8:05 - Adjust bokeh strength with simulated aperture

      // Adjust bokeh strength with simulated aperture
      
      
      open class AVCaptureDeviceInput : AVCaptureInput {
      
      	open var simulatedAperture: Float
      
      	...
      
      }
    • 8:40 - Find min, max, and default simulated aperture

      // Adjust bokeh strength with simulated aperture
      
      
      extension AVCaptureDeviceFormat {
      
      	open var minSimulatedAperture: Float { get }
      
      	open var maxSimulatedAperture: Float { get }
      
      	open var defaultSimulatedAperture: Float { get }
      
      	...
      
      }
    • 9:12 - Add a metadata output

      // Add a metadata output
      
      let metadataOutput = AVCaptureMetadataOutput()
      
      guard captureSession.canAddOutput(metadataOutput) else {
          print("Can't add the metadata output to the session")
          return
      }
      captureSession.addOutput(metadataOutput)
      
      metadataOutput.metadataObjectTypes = metadataOutput.requiredMetadataObjectTypesForCinematicVideoCapture
      
      metadataOutput.setMetadataObjectsDelegate(self, queue: sessionQueue)
    • 9:50 - Update the observed manager object

      // Update the observed manager object
      
      func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
      
         self.metadataManager.metadataObjects = metadataObjects
      
      }
      
      // Pass metadata to SwiftUI
      
      @Observable
      class CinematicMetadataManager {
          
          var metadataObjects: [AVMetadataObject] = []
          
      }
    • 10:12 - Observe changes and update the view

      // Observe changes and update the view
      
      struct FocusOverlayView : View {
      
          var body: some View {
      
      	        ForEach(
      	      metadataManager.metadataObjects, id:\.objectID)
      		  	{ metadataObject in
      
          		  rectangle(for: metadataObject)
      
      			  }
      		}
      }
    • 10:18 - Make a rectangle for a metadata

      // Make a rectangle for a metadata
      
      private func rectangle(for metadata: AVMetadataObjects) -> some View {
          
          let transformedRect = previewLayer.layerRectConverted(fromMetadataOutputRect: metadata.bounds)
          
          return Rectangle()
              .frame(width:transformedRect.width,
                     height:transformedRect.height)
              .position(
                  x:transformedRect.midX,
                  y:transformedRect.midY)
      }
    • 10:53 - Focus methods

      open func setCinematicVideoTrackingFocus(detectedObjectID: Int, focusMode: AVCaptureDevice.CinematicVideoFocusMode)
      
      open func setCinematicVideoTrackingFocus(at point: CGPoint, focusMode: AVCaptureDevice.CinematicVideoFocusMode)
      
      open func setCinematicVideoFixedFocus(at point: CGPoint, focusMode: AVCaptureDevice.CinematicVideoFocusMode)
    • 10:59 - Focus method 1 & CinematicVideoFocusMode

      // Focus methods
      
      open func setCinematicVideoTrackingFocus(detectedObjectID: Int, focusMode: AVCaptureDevice.CinematicVideoFocusMode)
      
      
      public enum CinematicVideoFocusMode : Int, @unchecked Sendable {
      
          case none = 0
      
          case strong = 1
      
          case weak = 2
      }
      
      extension AVMetadataObject {
      
         open var cinematicVideoFocusMode: Int32 { get }
      
      }
    • 12:19 - Focus method no.2

      // Focus method no.2
      
      open func setCinematicVideoTrackingFocus(at point: CGPoint, focusMode: AVCaptureDevice.CinematicVideoFocusMode)
    • 12:41 - Focus method no.3

      // Focus method no.3
      
      open func setCinematicVideoFixedFocus(at point: CGPoint, focusMode: AVCaptureDevice.CinematicVideoFocusMode)
    • 13:54 - Create the spatial tap gesture

      var body: some View {
      
      let spatialTapGesture = SpatialTapGesture()
          .onEnded { event in
              Task {
                  await camera.focusTap(at: event.location)
              }
           }
      
      ...
      }
    • 14:15 - Simulate a long press gesture with a drag gesture

      @State private var pressLocation: CGPoint = .zero
      @State private var isPressing = false
      private let longPressDuration: TimeInterval = 0.3
      
      var body: some View {
        
        ...
        
      	let longPressGesture = DragGesture(minimumDistance: 0).onChanged { value in
      		if !isPressing {
      			isPressing = true
      			pressLocation = value.location
      			startLoopPressTimer()
      		}
      	}.onEnded { _ in
      		isPressing = false
      	}
        
      	...
        
      }
      
      private func startLoopPressTimer() {
      	DispatchQueue.main.asyncAfter(deadline: .now() + longPressDuration) {
      		if isPressing {
      			Task {
      				await camera.focusLongPress(at: pressLocation)
      			}
      		}
      	}
      }
    • 14:36 - Create a rectangle view to receive gestures.

      var body: some View {
      
      let spatialTapGesture = ...
      let longPressGesture = ...
      
      ZStack {
        ForEach(
          metadataManager.metadataObjects,
          id:\.objectID)
        { metadataObject in
      
          rectangle(for: metadataObject)
      
        }
        Rectangle()
            .fill(Color.clear)
            .contentShape(Rectangle())
            .gesture(spatialTapGesture)
        .gesture(longPressGesture)}
      
        }
      }
    • 15:03 - Create the rectangle view

      private func rectangle(for metadata: AVMetadataObject) -> some View {
          
          let transformedRect = previewLayer.layerRectConverted(fromMetadataOutputRect: metadata.bounds)
          var color: Color
          var strokeStyle: StrokeStyle
          
          switch metadata.focusMode {
          case .weak:
              color = .yellow
              strokeStyle = StrokeStyle(lineWidth: 2, dash: [5,4])
          case .strong:
              color = .yellow
              strokeStyle = StrokeStyle(lineWidth: 2)
          case .none:
              color = .white
              strokeStyle = StrokeStyle(lineWidth: 2)
          }
          
          return Rectangle()
              .stroke(color, style: strokeStyle)
              .contentShape(Rectangle())
              .frame(width: transformedRect.width, height: transformedRect.height)
              .position(x: transformedRect.midX, 
                        y: transformedRect.midY)
      }
    • 15:30 - Implement focusTap

      func focusTap(at point:CGPoint) {
          
         try! camera.lockForConfiguration()
              
          if let metadataObject = findTappedMetadataObject(at: point) {
              if metadataObject.cinematicVideoFocusMode == .weak {
                  camera.setCinematicVideoTrackingFocus(detectedObjectID: metadataObject.objectID, focusMode: .strong)
                  
              }
              else {
                  camera.setCinematicVideoTrackingFocus(detectedObjectID: metadataObject.objectID, focusMode: .weak)
              }
          }
          else {
              let transformedPoint = previewLayer.metadataOutputRectConverted(fromLayerRect: CGRect(origin:point, size:.zero)).origin
              camera.setCinematicVideoTrackingFocus(at: transformedPoint, focusMode: .weak)
          }
          
          camera.unlockForConfiguration()
      }
    • 15:42 - Implement findTappedMetadataObject

      private func findTappedMetadataObject(at point: CGPoint) -> AVMetadataObject? {
          
          var metadataObjectToReturn: AVMetadataObject?
          
          for metadataObject in metadataObjectsArray {
              let layerRect = previewLayer.layerRectConverted(fromMetadataOutputRect: metadataObject.bounds)
              if layerRect.contains(point) {
                  metadataObjectToReturn = metadataObject
                  break
              }
          }
          
          return metadataObjectToReturn
      }
    • 16:01 - focusTap implementation continued

      func focusTap(at point:CGPoint) {
          
         try! camera.lockForConfiguration()
              
          if let metadataObject = findTappedMetadataObject(at: point) {
              if metadataObject.cinematicVideoFocusMode == .weak {
                  camera.setCinematicVideoTrackingFocus(detectedObjectID: metadataObject.objectID, focusMode: .strong)
                  
              }
              else {
                  camera.setCinematicVideoTrackingFocus(detectedObjectID: metadataObject.objectID, focusMode: .weak)
              }
          }
          else {
              let transformedPoint = previewLayer.metadataOutputRectConverted(fromLayerRect: CGRect(origin:point, size:.zero)).origin
              camera.setCinematicVideoTrackingFocus(at: transformedPoint, focusMode: .weak)
          }
          
          camera.unlockForConfiguration()
      }
    • 16:23 - Implement focusLongPress

      func focusLongPress(at point:CGPoint) {
          
         try! camera.lockForConfiguration()
      
         let transformedPoint = previewLayer.metadataOutputRectConverted(fromLayerRect:CGRect(origin: point, size: CGSizeZero)).origin
             camera.setCinematicVideoFixedFocus(at: pointInMetadataOutputSpace, focusMode: .strong)
         
          camera.unlockForConfiguration()
      }
    • 17:10 - Introduce cinematicVideoCaptureSceneMonitoringStatuses

      extension AVCaptureDevice {
      
         open var cinematicVideoCaptureSceneMonitoringStatuses: Set<AVCaptureSceneMonitoringStatus> { get }
      
      }
      
      extension AVCaptureSceneMonitoringStatus {
      
         public static let notEnoughLight: AVCaptureSceneMonitoringStatus
      
      }
    • 17:42 - KVO handler for cinematicVideoCaptureSceneMonitoringStatuses

      private var observation: NSKeyValueObservation?
      
      observation = camera.observe(\.cinematicVideoCaptureSceneMonitoringStatuses, options: [.new, .old]) { _, value in
          
          if let newStatuses = value.newValue {
              if newStatuses.contains(.notEnoughLight) {
                  // Update UI (e.g., "Not enough light")
              }
              else if newStatuses.count == 0 {
                  // Back to normal.
              }
          }
      }
    • 0:00 - Introducción
    • Usa la API Cinematic Video para capturar videos de estilo cinematográfico de nivel profesional en tus apps. El iPhone 13 y 13 Pro presentaron el modo Cine, que transformó al iPhone en una potencia cinematográfica.

    • 0:33 - Video cinematográfico
    • El Video cinematográfico utiliza poca profundidad de campo y seguimiento del enfoque para guiar la atención del espectador, imitando técnicas cinematográficas. La API Cinematic Video en iOS 26 simplifica este proceso, permitiendo que las apps enfoquen y rastreen automáticamente. Para crear una experiencia de captura cinematográfica, configura una sesión de captura, selecciona un dispositivo y, a continuación, habilita la captura de video cinematográfica configurando “isCinematicVideoCaptureEnabled” como true en la clase “AVCaptureDeviceInput”. Esto configura la sesión para emitir video cinemático con datos de disparidad, metadatos y el video original, lo que permite una edición no destructiva. Puedes reproducir o editar el renderizado de bokeh con Cinematic Framework.

    • 3:44 - Crea una gran experiencia de captura cinematográfica
    • El ejemplo comienza configurando una “AVCaptureSession” para habilitar la captura de video cinematográfico en dispositivos compatibles, como la cámara amplia doble en la parte posterior y la cámara TrueDepth en la parte frontal. El ejemplo selecciona un formato de video apropiado, donde “isCinematicVideoCaptureSupported” retorna como true, y, a continuación, agrega entrada de audio del micrófono a la sesión. La captura de audio espacial está habilitada para mejorar la experiencia cinematográfica. Para obtener más información sobre audio espacial, consulta “Mejora las capacidades de creación de contenido de audio de tu app”. A continuación, se habilita la estabilización de video para mejorar la experiencia del usuario y se obtiene una vista previa de la sesión de captura mediante una vista SwiftUI. Luego, el ejemplo crea una estructura representable personalizada para envolver “AVCaptureVideoPreviewLayer”, lo que permite integrarlo perfectamente en la interfaz SwiftUI. El ejemplo luego profundiza en el control del efecto de video cinematográfico, específicamente la profundidad de campo reducida. Al ajustar “simulatedAperture”, se puede fortalecer o debilitar el efecto bokeh, que brinda un control más creativo sobre el video. Para habilitar el control del enfoque manual, el ejemplo implementa la detección de metadatos para identificar candidatos al enfoque, como rostros. Luego, dibuja rectángulos en la pantalla para representar a estos candidatos, lo que permite a los usuarios tocar y centrarse en elementos específicos. La API Cinematic Video proporciona varios métodos para controlar el enfoque durante la grabación de video. La API genera objetos de metadatos que incluyen información sobre los sujetos detectados en el marco. El parámetro de configuración “focusMode” determina el comportamiento de seguimiento del video cinematográfico. Hay tres casos para esta enumeración: “ninguno”, “fuerte” y “débil”. El enfoque fuerte se centra en un sujeto, ignorando otros posibles candidatos para el enfoque. El enfoque débil permite que el algoritmo ajuste automáticamente el enfoque en función de la escena. El caso ninguno se utiliza principalmente para determinar el estado del enfoque en lugar de establecerlo. La API ofrece tres métodos de enfoque: el método “setCinematicVideoTrackingFocus” toma un ID de objeto detectado como entrada y establece el foco en ese objeto. El método “setCinematicVideoTrackingFocus” toma un punto en la vista como entrada. A continuación, el video cinematográfico busca un objeto interesante en ese punto y crea un nuevo objeto de metadatos del tipo “objeto destacado”, en el que luego se puede centrarse. “setCinematicVideoFixedFocus” establece un foco fijo en un punto específico de la escena, calculando la distancia internamente mediante señales de profundidad. Cuando se combina con un modo de enfoque fuerte, bloquea el enfoque en un plano particular, ignorando otras actividades en la escena. Puedes implementar lógica de enfoque personalizada en tus apps. Por ejemplo, al tocar un rectángulo de detección se puede cambiar el enfoque entre elementos, y un toque prolongado puede establecer un enfoque fijo fuerte. La app diferencia visualmente entre débil, fuerte y sin foco para guiar al usuario. Además, la API permite la captura de imágenes fijas durante la grabación, que recibirán automáticamente el tratamiento cinematográfico con el efecto bokeh. La app también puede usar la observación de valor clave para observar la propiedad “cinematicVideoCaptureSceneMonitoringStatuses” e informar al usuario cuando no hay suficiente luz para una captura de video cinematográfica adecuada.

Developer Footer

  • Videos
  • WWDC25
  • Captura videos cinematográficos en tu app
  • Open Menu Close Menu
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • Icon Composer
    • SF Symbols
    Open Menu Close Menu
    • Accessibility
    • Accessories
    • Apple Intelligence
    • Audio & Video
    • Augmented Reality
    • Business
    • Design
    • Distribution
    • Education
    • Games
    • Health & Fitness
    • In-App Purchase
    • Localization
    • Maps & Location
    • Machine Learning & AI
    • Security
    • Safari & Web
    Open Menu Close Menu
    • Documentation
    • Downloads
    • Sample Code
    • Videos
    Open Menu Close Menu
    • Help Guides & Articles
    • Contact Us
    • Forums
    • Feedback & Bug Reporting
    • System Status
    Open Menu Close Menu
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles
    • Feedback Assistant
    Open Menu Close Menu
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program
    • Mini Apps Partner Program
    • News Partner Program
    • Video Partner Program
    • Security Bounty Program
    • Security Research Device Program
    Open Menu Close Menu
    • Meet with Apple
    • Apple Developer Centers
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Academies
    • WWDC
    Read the latest news.
    Get the Apple Developer app.
    Copyright © 2026 Apple Inc. All rights reserved.
    Terms of Use Privacy Policy Agreements and Guidelines