iOS 27 introduces APIs and standards for building live production tools for Apple Immersive Video, enabling developers to capture, transport, record, and play back 3D immersive video using ProRes over SMPTE 2110 with spatial audio and per-frame metadata. The format combines ProRes-encoded stereo video (2110-22), ASAF spatial audio (2110-30), and JSON metadata (2110-41) into a unified production pipeline.
⢠Enables developers to build professional live broadcast tools (switchers, replay systems, graphics engines) that natively support Apple Immersive Video at full quality
⢠Recording to disk via AVAssetWriter requires no re-encode step since live ProRes frames are copied directly into MOV files, eliminating generational quality loss
⢠A new VideoToolbox property (kVTProjectionKind_AppleImmersiveVideo) ensures correct stereo projection metadata is embedded in MOV files for compatibility with the full immersive ecosystem
Demonstrates how to record a live Apple Immersive Video ProRes stream to a QuickTime MOV file using AVAssetWriter, including setting the required kVTProjectionKind_AppleImmersiveVideo compression property so the output file carries correct stereo immersive metadata.
import AVFoundation
import VideoToolbox
import CoreMedia
class ImmersiveVideoRecorder {
private var assetWriter: AVAssetWriter?
private var videoInput: AVAssetWriterInput?
private var audioInput: AVAssetWriterInput?
/// Width and height for a single eye; the codec carries both eyes as dual essences.
private let eyeWidth = 5760
private let eyeHeight = 2880
private let frameRate: Double = 60
func startRecording(to outputURL: URL) throws {
let writer = try AVAssetWriter(outputURL: outputURL, fileType: .mov)
// Video settings: ProRes 4444 for maximum fidelity
let videoSettings: [String: Any] = [
AVVideoCodecKey: AVVideoCodecType.proRes4444,
AVVideoWidthKey: eyeWidth,
AVVideoHeightKey: eyeHeight,
AVVideoCompressionPropertiesKey: [
// Required: marks the MOV with correct Apple Immersive Video
// stereo projection metadata (vexu box) for ecosystem interoperability.
kVTProjectionKind_AppleImmersiveVideo as String: true
] as [String: Any]
]
let videoInput = AVAssetWriterInput(
mediaType: .video,
outputSettings: videoSettings
)
// Live sources deliver frames in real time; do not wait for additional frames.
videoInput.expectsMediaDataInRealTime = true
guard writer.canAdd(videoInput) else {
throw RecorderError.cannotAddVideoInput
}
writer.add(videoInput)
// ASAF spatial audio: 64-channel PCM (high-order ambisonics + objects)
let channelLayout = AudioChannelLayout()
let audioSettings: [String: Any] = [
AVFormatIDKey: kAudioFormatLinearPCM,
AVSampleRateKey: 48000,
AVNumberOfChannelsKey: 64,
AVLinearPCMBitDepthKey: 32,
AVLinearPCMIsFloatKey: true,
AVLinearPCMIsNonInterleaved: false
]
let audioInput = AVAssetWriterInput(
mediaType: .audio,
outputSettings: audioSettings
)
audioInput.expectsMediaDataInRealTime = true
if writer.canAdd(audioInput) {
writer.add(audioInput)
}
self.assetWriter = writer
self.videoInput = videoInput
self.audioInput = audioInput
writer.startWriting()
writer.startSession(atSourceTime: .zero)
print("Recording started: \(outputURL.lastPathComponent)")
}
/// Call with each ProRes CMSampleBuffer arriving from the 2110-22 live stream.
/// Because the live payload is already ProRes, frames are copied directly ā
/// no re-encode step, no generational quality loss.
func appendVideoFrame(_ sampleBuffer: CMSampleBuffer) {
guard let input = videoInput, input.isReadyForMoreMediaData else { return }
input.append(sampleBuffer)
}
/// Call with each ASAF PCM CMSampleBuffer arriving from the 2110-30 live stream.
func appendAudioBuffer(_ sampleBuffer: CMSampleBuffer) {
guard let input = audioInput, input.isReadyForMoreMediaData else { return }
input.append(sampleBuffer)
}
func stopRecording() async {
videoInput?.markAsFinished()
audioInput?.markAsFinished()
await assetWriter?.finishWriting()
print("Recording finished. Status: \(assetWriter?.status.rawValue ?? -1)")
}
enum RecorderError: Error {
case cannotAddVideoInput
}
}
iOS 27 adds sectioned queries, codable model attributes, ResultsObserver for non-SwiftUI change observation, and HistoryObserver for reacting to persistent history changes in SwiftData.
USDKit is a new first-party Swift framework introduced in iOS/macOS 27 that brings native USD scene creation, composition, modification, and export capabilities to Apple platform apps, with deep RealityKit and Spatial Preview integration.
LiveCommunicationKit is the modern replacement for CXProvider that delivers rich, native conversation UIs integrated with the Lock Screen, Dynamic Island, Phone app Recents, and Siri. It provides a unified lifecycle model for audio and video conversations with a single delegate-driven action pipeline.
kVTProjectionKind_AppleImmersiveVideo must be set in AVVideoCompressionPropertiesKey or the video extended usage (vexu) box will be missing, breaking ecosystem interoperability; left and right eye frames are carried as two separate data essences within a single 2110-22 stream ā do not frame-pack side-by-side; ASAF mixes can contain 64+ channels which requires careful channel mapping when writing audio tracks
Full pipeline requires Apple Silicon for optimized ProRes processing; Apple Vision Pro required for playback of Apple Immersive Video content; live production hardware must support SMPTE 2110 IP transport
The NowPlaying framework introduces a first-class Swift API for surfacing app media in system-wide now-playing surfaces ā Lock Screen, Control Center, Dynamic Island, StandBy, CarPlay, Apple Watch, and Apple TV ā via a declarative MediaSessionRepresentable protocol. It also supports remote media sessions (for controlling external speakers/TVs) and Media Sharing Extensions for routing media to third-party devices.