Georgii EmelianovEngineering

Best App Demo Video Makers for SwiftUI Developers (2026): ScreenCaptureKit Guide & iOS App Preview Video Generator from Simulator

SwiftUI developers are shipping features faster than ever. But turning those features into crisp, launch‑ready app demo videos still feels like a separate job.

SwiftUI developer using ScreenCaptureKit on macOS to record iOS Simulator app demo footage for launch video

SwiftUI developers are shipping features faster than ever. But turning those features into crisp, launch‑ready app demo videos still feels like a separate job.

This tutorial shows you, step by step, how to use Apple’s ScreenCaptureKit on macOS to capture high‑quality iOS Simulator footage that plugs cleanly into tools like Reely, Screen Studio, and RocketSim — so you can go from code → simulator → demo reel in minutes.

Why ScreenCaptureKit matters for SwiftUI app demo videos

Apple has positioned ScreenCaptureKit as the primary framework for screen and audio capture on macOS. It’s designed for high‑quality recording, not just casual screen sharing.

Key facts developers should know:

  • ScreenCaptureKit is available on macOS 12.3 and later.
  • Apple’s latest sample and WWDC24 sessions target macOS 15+ and Xcode 16+ for HDR and straight‑to‑file workflows.
  • It’s meant to replace ReplayKit for screen streaming/mirroring on macOS.
  • 2024–2026 updates add HDR capture, microphone capture, and direct file recording.

When your goal is an App Store app preview video generator or a prompt‑to‑promo tool, good raw capture is non‑negotiable. ScreenCaptureKit gives you:

  • Precise targeting: capture just the iOS Simulator window, not your entire desktop.
  • Low‑latency frames and audio sample buffers tuned for production output.
  • A clean pipeline into AVFoundation, which is exactly what Reely and other tools expect.

Prerequisites: OS, Xcode, permissions, and project setup

Before we dive into code, get the environment right.

1. OS + Xcode versions

To follow this tutorial comfortably:

  • macOS version
    • Minimum: macOS 12.3 (ScreenCaptureKit introduction)
    • Recommended: macOS 15+ for the latest HDR and straight‑to‑file features (per Apple’s 2024 sample project).
  • Xcode version
    • Minimum: Xcode 13.3+ for early ScreenCaptureKit APIs.
    • Recommended: Xcode 16+ for the current API surface and WWDC24 samples.

Apple’s official docs:

2. Privacy & permissions (critical on macOS)

ScreenCaptureKit doesn’t bypass macOS privacy. You must respect user permissions.

Screen Recording permission

To record other apps (like the iOS Simulator), macOS requires Screen Recording access:

  • Users must enable:
    • System Settings → Privacy & Security → Screen Recording → [Your app]
  • Without this, ScreenCaptureKit can’t capture other windows.
  • Note: Signings & Capabilities entitlements do NOT auto‑grant capture of other apps — user consent still rules.

Info.plist keys

Add usage descriptions so macOS can show a clear permission prompt:

  • NSMicrophoneUsageDescription
    • Example: "This app records your app demo and needs microphone access to capture voice‑over audio."
  • If your app uses camera (not required for ScreenCaptureKit alone): NSCameraUsageDescription.

Microphone permission flow

If you want live narration in your demo:

  • Call AVAudioSession / AVCaptureDevice (depending on your stack) to trigger the microphone permission prompt.
  • Handle denial gracefully: fall back to silent footage or show UI that explains voice‑over can be added later.

Step 1: Create a macOS helper app for simulator recording

The cleanest workflow is a small macOS helper app that:

  • Detects the iOS Simulator window.
  • Starts a ScreenCaptureKit stream.
  • Writes video + audio into a launch‑ready file via AVFoundation.

You can keep your SwiftUI app code separate and treat this as a tool auto generate app demo reels after build — especially when hooked into CI.

Basic setup:

  1. In Xcode, create a new macOS app (SwiftUI or AppKit is fine).
  2. Add ScreenCaptureKit and AVFoundation:

import ScreenCaptureKit
import AVFoundation

  1. Make sure the app is sandboxed and has necessary permissions configured in its entitlements and Info.plist.

Step 2: Discover shareable content and filter to iOS Simulator

ScreenCaptureKit starts with shareable content discovery. You ask the system what windows/displays are available, then filter to what you want.

Fetch SCShareableContent

func fetchShareableContent() async throws -> SCShareableContent {
return try await SCShareableContent.current
}

This gives you:

  • displays: connected screens.
  • windows: all capturable windows.

Pick the iOS Simulator window

You can match by window.title or bundleIdentifier. The Simulator usually has a recognizable title like “iPhone 16 Pro – MyApp”.

func simulatorWindow(from content: SCShareableContent) -> SCWindow? {
return content.windows.first { window in
guard let title = window.title?.lowercased() else { return false }
return title.contains("iphone") ||
title.contains("ipad") ||
title.contains("simulator")
}
}

Create a content filter

Once you’ve got the window:

func makeContentFilter(for window: SCWindow) -> SCContentFilter {
return SCContentFilter(desktopIndependentWindow: window)
}

This filter tells ScreenCaptureKit to focus solely on that window — ideal for iOS app preview video generator from simulator workflows.

Step 3: Configure SCStream for video and audio

Now we create an SCStream that delivers video frames and audio samples.

Define stream configuration

ScreenCaptureKit lets you configure resolution, pixel format, and more.

func makeStreamConfiguration() -> SCStreamConfiguration {
let config = SCStreamConfiguration()

// Target App Store spec: 30 fps max
config.minimumFrameInterval = CMTime(value: 1, timescale: 30)

// Example target size – match your simulator or scale down
config.width = 1280
config.height = 720

// Let ScreenCaptureKit choose efficient pixel formats (often NV12/YUV)
// We'll handle conversion later via AVAssetWriterInputPixelBufferAdaptor.

config.showsCursor = false
config.capturesAudio = true

return config
}

Important:

  • SCStream commonly emits NV12/YUV pixel buffers, not always kCVPixelFormatType_32BGRA.
  • Don’t hard‑code BGRA assumptions; plan for conversion when wiring AVAssetWriter.

Create the stream

func makeStream(filter: SCContentFilter,
configuration: SCStreamConfiguration,
delegateQueue: DispatchQueue) throws -> SCStream {
let stream = SCStream(filter: filter, configuration: configuration, delegate: nil)
try stream.addStreamOutput(self,
type: .screen,
sampleHandlerQueue: delegateQueue)
try stream.addStreamOutput(self,
type: .audio,
sampleHandlerQueue: delegateQueue)
return stream
}

Use a background queue (not .main) for sampleHandlerQueue to avoid blocking UI when writing frames.

Step 4: Wire AVAssetWriter for launch‑ready output

To create App Store‑ready or Reely‑ready clips, use AVAssetWriter. This step is where a lot of tutorials go wrong — especially around timing.

Create AVAssetWriter

class DemoRecorder {
private var assetWriter: AVAssetWriter?
private var videoInput: AVAssetWriterInput?
private var pixelBufferAdaptor: AVAssetWriterInputPixelBufferAdaptor?
private var audioInput: AVAssetWriterInput?

private var isSessionStarted = false

func prepareWriter(outputURL: URL) throws {
assetWriter = try AVAssetWriter(outputURL: outputURL, fileType: .mov)

// Video settings – align with App Store preview specs
let videoSettings: [String: Any] = [
AVVideoCodecKey: AVVideoCodecType.h264,
AVVideoWidthKey: 1280,
AVVideoHeightKey: 720
]

let vInput = AVAssetWriterInput(mediaType: .video, outputSettings: videoSettings)
vInput.expectsMediaDataInRealTime = true

// Handle NV12/YUV via pixel buffer adaptor
let sourcePixelBufferAttributes: [String: Any] = [
kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange,
kCVPixelBufferWidthKey as String: 1280,
kCVPixelBufferHeightKey as String: 720
]

let adaptor = AVAssetWriterInputPixelBufferAdaptor(
assetWriterInput: vInput,
sourcePixelBufferAttributes: sourcePixelBufferAttributes
)

// Audio settings – basic AAC
let audioSettings: [String: Any] = [
AVFormatIDKey: kAudioFormatMPEG4AAC,
AVNumberOfChannelsKey: 2,
AVSampleRateKey: 44_100,
AVEncoderBitRateKey: 128_000
]

let aInput = AVAssetWriterInput(mediaType: .audio, outputSettings: audioSettings)
aInput.expectsMediaDataInRealTime = true

if let writer = assetWriter {
if writer.canAdd(vInput) { writer.add(vInput) }
if writer.canAdd(aInput) { writer.add(aInput) }
}

videoInput = vInput
pixelBufferAdaptor = adaptor
audioInput = aInput
}
}

Correct timing: startSession from first sample buffer

A common mistake is calling startSession(atSourceTime: .zero). Instead, you must use the first sample buffer’s presentation timestamp.

extension DemoRecorder {
func handleFirstSampleIfNeeded(_ sampleBuffer: CMSampleBuffer) {
guard let writer = assetWriter, !isSessionStarted else { return }

let pts = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
writer.startWriting()
writer.startSession(atSourceTime: pts)
isSessionStarted = true
}
}

This keeps audio and video correctly aligned and avoids drift.

Robust error handling and writer status

Always watch assetWriter.status:

func checkWriterStatus(context: String) {
guard let writer = assetWriter else { return }
switch writer.status {
case .writing:
break // OK
case .completed:
print("Writer completed: \(context)")
case .failed:
print("Writer failed: \(context), error: \(writer.error?.localizedDescription ?? "unknown")")
case .cancelled:
print("Writer cancelled: \(context)")
default:
break
}
}

Run finishWriting on a background queue and use its completion handler:

func stopRecording(completion: @escaping (Result<URL, Error>) -> Void) {
guard let writer = assetWriter else { return }

videoInput?.markAsFinished()
audioInput?.markAsFinished()

writer.finishWriting { [weak self] in
self?.checkWriterStatus(context: "finishWriting")
if writer.status == .completed {
completion(.success(writer.outputURL))
} else {
completion(.failure(writer.error ?? NSError(domain: "DemoRecorder", code: -1)))
}
}
}

All heavy work — sample handling and finishWriting — should be done off the main thread to keep UI responsive.

Step 5: Handle video sample buffers on a background queue

ScreenCaptureKit gives you CMSampleBuffer objects via SCStreamOutput. You convert those into pixel buffers and append them via the adaptor.

Implement SCStreamOutput for video

extension DemoRecorder: SCStreamOutput {
func stream(_ stream: SCStream,
didOutputSampleBuffer sampleBuffer: CMSampleBuffer,
of type: SCStreamOutputType) {
switch type {
case .screen:
handleVideoSampleBuffer(sampleBuffer)
case .audio:
handleAudioSampleBuffer(sampleBuffer)
default:
break
}
}
}

Process video samples

func handleVideoSampleBuffer(_ sampleBuffer: CMSampleBuffer) {
handleFirstSampleIfNeeded(sampleBuffer)
guard let writer = assetWriter,
let vInput = videoInput,
let adaptor = pixelBufferAdaptor else { return }

checkWriterStatus(context: "video")

// Do not write on main queue
DispatchQueue.global(qos: .userInitiated).async {
guard vInput.isReadyForMoreMediaData,
let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
return
}

let pts = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
let success = adaptor.append(pixelBuffer, withPresentationTime: pts)
if !success {
print("Failed to append pixel buffer at \(pts)")
}
}
}

Notes:

  • isReadyForMoreMediaData prevents overloading the writer when it’s not ready.
  • If you need to convert formats (e.g., NV12 → BGRA), add a Core Image or vImage conversion step before appending.

Step 6: Audio capture, permissions, and sync

For launch videos, you may want:

  • Live narration via the microphone.
  • App sounds from the Simulator.

ScreenCaptureKit can capture audio samples, but you must handle permissions and timing.

Microphone and app audio

  • Ensure config.capturesAudio = true on SCStreamConfiguration.
  • Request microphone access via AVFoundation if you use direct mic input.
  • Audio sample buffers can have different timestamps than video — you must respect and align them.

Process audio samples

func handleAudioSampleBuffer(_ sampleBuffer: CMSampleBuffer) {
handleFirstSampleIfNeeded(sampleBuffer)
guard let aInput = audioInput, aInput.isReadyForMoreMediaData else { return }

DispatchQueue.global(qos: .utility).async {
let success = aInput.append(sampleBuffer)
if !success {
print("Failed to append audio sample buffer")
}
}
}

Because you started the writing session at the first sample’s presentation timestamp, subsequent audio and video samples share a common timeline. That keeps your SwiftUI animations, taps, and voice‑over in sync.

Step 7: Export settings tuned for App Store previews and launch promos

Once you have a .mov file from AVAssetWriter, you may want to transcode or trim for specific destinations.

App Store preview specs (2026)

From Apple’s latest documentation:

  • Length: 15–30 seconds per preview.
  • Max file size: 500 MB.
  • Frame rate: 30 fps max.
  • Codec: H.264 or ProRes 422 HQ.
  • Audio: AAC stereo.
  • Up to three previews per language.

Source: developer.apple.com/app-store/app-previews/

To comply:

  • Capture at 30 fps or lower (config already set above).
  • Use H.264 + AAC in AVAssetWriter.
  • Use tools like HandBrake (local transcoding; recommends 16 GB RAM for HD, 32 GB for 4K) to down‑scale or compress while staying on‑device.

Feeding capture into iOS app preview video generator tools

Once you have clean simulator footage, you can plug it into:

  • Reely – AI‑native app launch video generator that:
    • Recreates flows in the iOS Simulator via its MCP agent.
    • Auto‑cuts dead air and adds kinetic typography and device choreography.
    • Keeps everything editable in its macOS motion studio.
  • Screen Studio – polished recorder/editor that adds:
    • Smooth cursor motion (“SmoothCapture”) and animated zooms.
    • A timeline for manual editing.
  • RocketSim – simulator companion that:
    • Lets AI agents inspect and interact with your app, capturing screenshots and recordings.

For many SwiftUI developers, the workflow is:

  1. Capture with ScreenCaptureKit for exact flows and local control.
  2. Import into Reely to auto‑generate 10–20s feature teasers and 30–60s launch promos.
  3. Optionally polish specific shots in Screen Studio or RocketSim.

iOS app preview video generator from simulator: workflows & examples

If your goal is an iOS app preview video generator from simulator, ScreenCaptureKit is the capture layer. Generator tools sit on top.

Example workflow: Reely iOS app demo from simulator

  1. Run your SwiftUI app in the iOS Simulator.
  2. Use your ScreenCaptureKit helper to record a clean flow:
    • Onboarding
    • Key feature use
    • Closing call‑to‑action.
  3. Feed the resulting clip and/or code + screenshots into Reely.
  4. In Reely, describe the reel:
    • “30‑second Product Hunt trailer highlighting dark‑mode calendar views and AI scheduling.”
  5. Reely’s agent recreates the flow, then:
    • Auto‑cuts dead air between taps.
    • Adds native gesture callouts, kinetic type, and music.

This keeps the source of truth in your app and simulator, but removes the need to manually edit timelines.

Example workflow: Screen Studio iOS app demo

  1. Use ScreenCaptureKit if you want custom control or simulator‑only capture.
  2. Or record directly in Screen Studio using its built‑in recorder.
  3. Use Screen Studio’s effects (zoom, pan, cursor smoothing) to highlight interactions.
  4. Export at 30 fps, H.264, and upload to App Store Connect.

Reely vs Screen Studio iOS app demos

SwiftUI developers often ask how Reely vs Screen Studio iOS app demos compare. They serve different purposes.

Reely: AI‑native app launch video generator

Pros:

  • Built specifically as an app launch video generator for mobile developers.
  • Deep MCP/agent integration: the same AI agent that builds your SwiftUI feature can:
    • Drive the iOS Simulator.
    • Capture flows.
    • Hand footage and specs into Reely’s motion studio.
  • Local macOS app: rendering and simulator recording happen on‑device (no cloud upload of builds).
  • Rich motion system:
    • 13+ typography systems.
    • Device choreography presets.
    • Auto dead‑air removal tuned for app demos.
  • Simple pricing (2026):
    • $19/month or $123/year, plus a trust‑based “2 + 1 Honor Offer.”

Cons:

  • Focused on mobile app promos — not a general screen recorder.
  • Requires macOS; no Windows/Linux build.

Website: getreely.co

Screen Studio: polished recorder/editor with SmoothCapture

Pros:

  • Strong at manual craft for product demos.
  • “SmoothCapture” gives very fluid cursor and motion.
  • Built‑in recorder + timeline editing.
  • Indie‑friendly pricing:
    • $20/month.
    • Or $9/month billed yearly.
    • ~40% educational discount for verified students.

Cons:

  • No agent/MCP integration – you do the recording and editing manually.
  • Not specialized for App Store preview constraints; you tweak settings yourself.

Website: screen.studio

When to pick which

  • Choose Reely if you want:
    • Promo from code in minutes.
    • Agent‑driven flows from simulator to finished reel.
    • Automatic pacing, typography, and device motion.
  • Choose Screen Studio if you want:
    • Manual timeline control and handcrafted motion.
    • A general best screen recording tool for app demos on macOS.

Most teams can benefit from both: ScreenCaptureKit + Reely for AI‑native launches, Screen Studio for occasional handcrafted hero videos.

Automatically generate app demo reels from build artifacts

Agentic workflows mean your CI can now automatically generate app demo reels from build artifacts.

How this typically works:

  • CI pipeline builds your iOS app.
  • An MCP server or agent spins up the iOS Simulator.
  • ScreenCaptureKit‑style capture runs scripted flows:
    • Log in, navigate to key feature, perform core action.
  • Footage is handed to app demo reel auto generate after build tools like Reely.

Common hooks:

  • Post‑build step:
    • Trigger a script that launches the simulator and runs a UI automation sequence.
  • Agent orchestration:
    • Use test targets or agent scripts to drive the UI.
  • Asset publishing:
    • Reely or another generator produces feature teasers.
    • Artifacts are attached to the build or pushed to a marketing asset bucket.
Timeline of app demo workflows from manual recording to simulator tools to AI-native generators

From manual editing to agentic pipelines: tools like Reely and RocketSim are moving app demo creation from ad‑hoc screen recording to scripted, simulator‑driven workflows that plug directly into CI.

This is where the thesis “Your agent built the app. Let it build the demo reel too.” becomes real.

AI video creator offline/local rendering & self‑hosted options

SwiftUI developers care deeply about privacy and local control. Especially when recording unreleased UIs.

AI video generator supports local rendering

Tools and components that keep work on‑device include:

  • Reely – native macOS app, local rendering, no cloud upload of your simulator builds.
  • HandBrake – fully local transcoder (supports Apple Silicon M1+; recommends 16 GB RAM for HD and 32 GB for 4K).
  • OpenCut – markets local/CPU‑powered AI editing, including running 7B models on 8 GB RAM.

These align with developers wanting an AI video creator offline local processing code story.

Self‑hosted automated app demo video generator from code

If you need self‑hosting:

  • Use ScreenCaptureKit + AVFoundation in your own macOS app.
  • Combine with self‑hosted MCP servers that control the simulator.
  • Pipe output into:
    • Local FFmpeg/HandBrake for transcoding.
    • In‑house motion templates for branding.

This gives you a self‑hosted automated app demo video generator from code, with no external services touching your footage.

Putting it all together: a minimal capture‑to‑promo workflow

Here’s a practical recipe SwiftUI developers can implement this week:

  1. Build a macOS helper app
    • Uses ScreenCaptureKit + AVAssetWriter (as shown above).
    • Targets the iOS Simulator window via SCShareableContent.
  2. Record a core feature flow
    • 20–30 seconds.
    • Start/stop around the main narrative arc.
  3. Transcode and trim locally
    • Use AVFoundation or HandBrake to ensure:
      • 30 fps.
      • H.264 + AAC.
      • Clean length for App Store preview (≤30s).
  4. Feed into Reely
    • Let Reely’s agent recreate flows and generate:
      • 10–20s feature teaser.
      • 30–60s full launch promo.
  5. Publish
    • App Store preview.
    • Product Hunt launch video.
    • X, LinkedIn, YouTube Shorts snippets.

Minimal manual editing, maximum reuse of your code, simulator flow, and AI tools.

FAQ

Q1: Why use ScreenCaptureKit instead of a generic macOS screen recorder?

ScreenCaptureKit is Apple’s recommended framework for high‑quality screen capture. It gives:

  • Per‑window capture (e.g., just the iOS Simulator).
  • Access to sample buffers for precise editing and sync.
  • Integration with AVFoundation and HDR/mic features from WWDC24.

Generic recorders are fine for quick clips, but ScreenCaptureKit is better when you want agent‑driven capture and App Store‑ready outputs.

Q2: Can ScreenCaptureKit record my SwiftUI app running directly on macOS?

Yes. You can target your macOS SwiftUI app window via SCShareableContent.windows and SCContentFilter. The same pipeline (SCStream + AVAssetWriter) works — making it a strong choice among best screen capture software mac options when you care about precise control.

Q3: How do I avoid audio/video desync in my app demo recordings?

The two key rules:

  • Start your AVAssetWriter session at the first sample’s presentation timestamp using CMSampleBufferGetPresentationTimeStamp.
  • Always append both audio and video sample buffers using their own timestamps, not arbitrary values.

This ensures the timeline is consistent and prevents drift in your SwiftUI animations and voice‑over.

Q4: Is 4K overkill for App Store previews?

App Store previews cap at 30 fps and 500 MB per clip. 4K can be overkill unless you’re targeting other platforms like YouTube. For App Store:

  • 1280×720 or 1920×1080 with H.264 is usually sufficient.
  • Consider 4K masters for Reely or Screen Studio workflows, then downscale for the store.

Q5: How does this compare to template/mockup tools like Previewed?

Template/mockup tools like Previewed focus on device frames and 3D scenes, not exact simulator flows. They’re great for marketing banners and static promos. But if you want accurate, tappable SwiftUI UI in motion — especially for App Store previews — ScreenCaptureKit + simulator recording + AI generators like Reely give you a more truthful, flow‑driven demo.

If your agent can build the app, it should also build the demo reel. ScreenCaptureKit is the capture foundation that lets you do exactly that — from SwiftUI code to polished launch motion, all on your Mac.

← All posts