Embedding ChapterPlayer
ChapterPlayer is a Swift package that runs ChapterScript documents on Apple Vision Pro. It bundles the sequence engine, spatial audio and video managers, entity factory, gate detection, and live-development client, so your app ships its UI, its content, and its product-specific extensions, and nothing else.
Installing
// Package.swift .package(url: "https://github.com/mike-bundy/ChapterPlayer.git", branch: "main")
ChapterPlayer tracks the ChapterScript
format package at main while the wire format is pre-1.0; both will
pin to tagged versions once the format settles. A local sibling checkout of
ChapterScript overrides the remote by package identity, the standard
local-override workflow.
Requirements
- visionOS 26+
- Swift 6.2 / Xcode 26+
- ChapterScript, resolved automatically as a dependency
What's inside
| Piece | What it does |
|---|---|
| SequenceEngine | The declarative sequence/step choreographer. Always resets entities on sequence change; pluggable executor protocols for entity, audio, video, attachment, and effect actions. |
| GateDetectionController | Holds a step until its gate resolves (tap, gaze, approach, grab, or timeout), behind the GateDetecting protocol. |
| SpatialAudioManager | AVAudioEngine-based channel system with audio buses, ducking rules, audio zones, and loop configs. |
| VideoPlaybackManager | Per-channel AVPlayer orchestrator: flat scene panels, attachment-based SwiftUI overlays, and 360°/180° immersive skybox playback. |
| EntityFactory | Builds RealityKit entities from ChapterScript definitions: primitives, USDZ models, 3D text, lights, and video panels, with a registry for app-specific custom factories. |
| DocumentEntityLoader | Materializes a document's entities into the immersive scene and registers them with the executors. |
| BackdropCueDriver | Drives sequence backdrop presentation (video and image skyboxes, full USDZ backdrop scenes) behind BackdropCuePresenting. |
| MotionCurveEvaluator | A thin delegate over ChapterScript's canonical curve sampling, so playback matches editor previews and motion trails exactly. |
| PulseRingEntity / SparkBurstEntity | Procedural VFX primitives fired by the corresponding step actions. |
| AssetPreloader | Warms media before playback so first frames land on time. |
Loading content
Content arrives through an ExperienceProvider paired with a MediaResolver:
- BundledExperienceProvider +
BundleMediaResolver: chapters shipped inside your app bundle. - LocalFolderExperienceProvider +
LocalFolderMediaResolver: chapters from a folder on device. - LiveDevExperienceProvider +
LiveMediaResolver: live development against an authoring tool on your network.LiveServerBrowserdiscovers peers over Bonjour, aLiveSubscriptionstreams document updates, and assets prefetch concurrently.
What your app provides
- The visionOS scenes:
@main,WindowGroup,ImmersiveSpace, withopenImmersiveSpace/dismissImmersiveSpaceinjected into the player. - Custom action handlers, registered through the effect executor's custom-action escape hatch (the format's
customaction kind). - Product-specific entity factories layered on the built-in registry: bespoke USDZs, audio-reactive elements, anything the declarative catalog doesn't cover.
- A
MediaResolverfor your distribution model, or one of the built-ins above.
The runtime is deliberately tool-agnostic: any document that decodes as valid ChapterScript plays, no matter what wrote it.