PrismCore
A Swift playback engine for Apple platforms. FFmpeg demuxes, Apple plays — any container libavformat can read is remuxed on the fly into HLS-fMP4 for a plain AVPlayer, with Dolby Atmos and Dolby Vision intact.
PrismCore remuxes media into HLS with fragmented-MP4 segments, serves it from a loopback HTTP server on 127.0.0.1, and hands your AVPlayer a playlist URL. Not a single video frame is re-encoded. Apple's own stack then does what only it can do on its platforms: VideoToolbox hardware decode, Dolby Atmos passthrough, the Dolby Vision display handshake, Match Content on tvOS, system HDR10/HLG tone-mapping — and everything that comes with AVPlayer itself: Picture in Picture, AirPlay, Now Playing and spatial audio.
It is an engine core, not a player. There is no view, no transport bar and no published playback state: you keep your AVPlayer and your UI.
import PrismCore
switch try await PrismCoreEngine.open(url: mkvURL) {
case .remux(let session, let playlist):
player.replaceCurrentItem(with: AVPlayerItem(url: playlist))
// … play; when done:
await session.stop()
case .software(let pipeline):
hostLayer.addSublayer(pipeline.displayLayer!) // the pipeline draws the frames
pipeline.play()
}Two paths, one entry point
| Path | Used for | What the host gets |
|---|---|---|
Remux (PrismCoreSession) | Video AVPlayer can decode — H.264, HEVC, and AV1 where the device has a hardware decoder | A playlist URL for its own AVPlayer |
Software (SoftwarePlaybackPipeline) | Video AVPlayer cannot decode at all — VP9, VP8, MPEG-2, MPEG-4 Part 2, VC-1, AV1 without hardware — and verified-interlaced H.264 | An AVSampleBufferDisplayLayer to put in a view |
PrismCoreEngine.open(url:) probes the source once, decides, and returns whichever path is already started. PrismCoreEngine.decide(for:) exposes the same decision without starting anything, so a host can log it or unit-test its own routing. See Capabilities for the exact rules.
What it handles
- Containers — anything libavformat demuxes: MKV, MP4, MPEG-TS, AVI, WebM, FLV and more.
- Audio — AAC, AC-3, E-AC-3, FLAC and ALAC are copied bit for bit (Atmos included). TrueHD, DTS (incl. DTS-HD MA), MP3, MP2, Opus, Vorbis and PCM are bridged to E-AC-3, or to AAC on an FFmpeg build without an
eac3encoder. - Subtitles — text tracks (SubRip, ASS/SSA, WebVTT, mov_text) and sidecar
.srt/.vttfiles become segmented WebVTT renditions; bitmap tracks (PGS, DVB, DVD) are read with on-device Vision OCR; CEA-608 captions carried in the video become real caption renditions. - Seeking — a keyframe-aligned segment plan is published before the first packet, production is demand-driven, and a container with no index of its own learns one on first play and remembers it.
- Diagnostics — classified errors, startup checkpoints, playback events and one redacted
Codablereport per session.
The full list, with limits, is on Capabilities.
Where to go next
- Installation — add the package with Swift Package Manager.
- Quick start — your first playback, then driving a session directly.
- How it works — the pipeline, and the design decisions behind it.
- API reference — every public symbol in 3.5.4, generated from the source.