A new set of APIs and standards enabling developers to build live production tools for Apple Immersive Video, using ProRes-over-SMPTE-2110 transport and AVFoundation for recording spatial video to QuickTime MOV files with the correct immersive metadata.
⢠Enables third-party developers to build broadcast-grade live production tools (switchers, replay systems, graphics generators) that are interoperable with Apple's immersive live pipeline
⢠Recording live immersive ProRes streams to disk via AVAssetWriter requires zero re-encoding, preserving full quality through the entire production workflow
⢠The new kVTProjectionKind_AppleImmersiveVideo VideoToolbox constant ensures MOV files carry correct stereo/spatial metadata (vexu box), making files immediately usable in editorial and post-production
Demonstrates how to record a live Apple Immersive Video ProRes stream to a QuickTime MOV file using AVAssetWriter, setting the required kVTProjectionKind_AppleImmersiveVideo compression property so the file carries correct spatial/stereo metadata for editorial and replay workflows.
import AVFoundation
import VideoToolbox
import CoreMedia
class ImmersiveLiveRecorder {
private var assetWriter: AVAssetWriter?
private var videoInput: AVAssetWriterInput?
private let outputURL: URL
init(outputURL: URL) {
self.outputURL = outputURL
}
func startRecording(width: Int, height: Int, frameRate: CMTimeScale) throws {
// Remove any existing file at the output URL
try? FileManager.default.removeItem(at: outputURL)
let writer = try AVAssetWriter(outputURL: outputURL, fileType: .mov)
// ProRes 4444 for maximum fidelity ā matches live 2110-22 stream payload
let videoSettings: [String: Any] = [
AVVideoCodecKey: AVVideoCodecType.proRes4444,
AVVideoWidthKey: width,
AVVideoHeightKey: height,
AVVideoCompressionPropertiesKey: [
// Required: marks the MOV as Apple Immersive Video (writes vexu box)
kVTProjectionKind_AppleImmersiveVideo as String: true
] as [String: Any]
]
let input = AVAssetWriterInput(
mediaType: .video,
outputSettings: videoSettings
)
input.expectsMediaDataInRealTime = true // Critical for live production
guard writer.canAdd(input) else {
throw RecorderError.cannotAddInput
}
writer.add(input)
self.assetWriter = writer
self.videoInput = input
writer.startWriting()
writer.startSession(atSourceTime: .zero)
}
/// Called once per ProRes frame received from the 2110-22 network stream.
/// Frames are copied directly ā no re-encode, no quality loss.
func appendFrame(_ sampleBuffer: CMSampleBuffer) {
guard
let input = videoInput,
input.isReadyForMoreMediaData
else { return }
input.append(sampleBuffer)
}
func stopRecording() async throws {
videoInput?.markAsFinished()
await assetWriter?.finishWriting()
if let error = assetWriter?.error {
throw error
}
print("Immersive MOV saved to: \(outputURL.path)")
}
enum RecorderError: Error {
case cannotAddInput
}
}
The kVTProjectionKind_AppleImmersiveVideo constant must be set in AVVideoCompressionPropertiesKey when writing the MOV video track ā omitting it will produce a file missing the required vexu (video extended usage) metadata box, breaking compatibility with immersive playback. SMPTE 2110-22 dual-essence streams (left+right eye in one flow) are a new workflow concept; traditional side-by-side frame packing is not used here.
Apple Silicon required for ProRes hardware acceleration; Apple Vision Pro or compatible immersive video hardware needed for full pipeline; SMPTE 2110 network infrastructure required for live transport
More iOS 27 APIs land every week.
Get notified when new capabilities are published ā no noise, just signal.