PrismCore

Swift package · vibecoded

PrismCore

Aether's native playback engine — FFmpeg demuxes, Apple plays

PrismCore takes any container libavformat can read — MKV, MPEG-TS, AVI — remuxes it on the fly into HLS-fMP4, serves it from a loopback server on 127.0.0.1 and hands a plain AVPlayer a playlist URL. Apple's stack then does what only it can do on its own platforms: hardware decode, Dolby Atmos passthrough, Dolby Vision, Match Content.

  • Swift 6
  • iOS 16+ · tvOS 17+ · macOS 14+ · visionOS 1+
  • Aether's default engine
  • LGPL-2.1

Why I built it

Aether's two engines split playback down the middle: AVPlayer did Atmos, Dolby Vision and hardware decode but only Apple's containers; libmpv played everything but rendered its own frames and decoded audio to PCM, so Atmos and DV died at its door. PrismCore closed that gap, and it is now the engine Aether reaches for first. libmpv stays on as the fallback for what PrismCore cannot take yet — and retires at parity.

Where it fits

  • Aether — the engine it ships, on by default on every platform
  • Any Swift app that wants MKV or MPEG-TS playback through a plain AVPlayer
  • Anyone who cares that Atmos and Dolby Vision survive the trip to the screen

What it does

Remux, don't transcode

Video and audio are stream-copied into HLS-fMP4 segments as the demuxer reads — no re-encode, no quality loss, no CPU burn. VideoToolbox does the decoding in hardware, exactly as if the file had been Apple-native all along.

Dolby Atmos passthrough

EAC3+JOC is copied untouched, never decoded to PCM — and PrismCore patches the dec3 box FFmpeg drops on a stream copy, the one signal that makes AVFoundation take the Dolby route instead of playing plain DD+.

Dolby Vision, signaled honestly

Profile 5 gets its dvh1 sample entry, Profile 7 is rewritten to single-layer 8.1 through libdovi, and the master playlist only claims what the current display can actually engage — with a muxed fallback for when AVPlayer refuses a master anyway.

Every track survives

Each audio track becomes an HLS alternate rendition with its name, language and channel count, so AVKit's track menu just works. Text subtitles convert to segmented WebVTT renditions that survive PiP and AirPlay, and external SRT/VTT sidecars join the same way. Even PGS and VOBSUB make it: they carry only bitmaps, so they are read on the device with Vision's OCR — no upload, no service — and become ordinary renditions too.

Seek like a local file

A keyframe-aligned segment plan is published before the first packet, and a seek outside the produced window re-anchors the demuxer to the right keyframe on demand. A byte-budgeted cache bounds disk, not seekability — evicted segments are simply reproduced.

A software path for the rest

Codecs AVPlayer can't decode at all — VP9, MPEG-2, VC-1 — decode through libavcodec into AVSampleBufferDisplayLayer, zero-copy where VideoToolbox has a hardware decoder. AV1 asks the actual silicon, not the chip name. Verified-interlaced sources leave the native path so bwdif can take them.

A service, not a player

PrismCore is deliberately narrow: no view, no transport, no published state. A session takes a URL and returns a playlist URL; the host's existing AVPlayer infrastructure stays in charge. One entry point — PrismCoreEngine.open — probes the source and hands back the remux session or the software pipeline, already started.

Built with

  • Swift 6 actors
  • FFmpeg (via MPVKit)
  • HLS-fMP4
  • AVPlayer & AVFoundation
  • libdovi
  • Network.framework
  • SwiftPM
  • LGPL-2.1

Where it's at

It ships. PrismCore came out of Aether's Developer section in August 2026 and now sits in Settings ▸ Playback, on by default on every platform — a fresh install gets it without touching a thing. The two headline claims that no fixture could ever prove are device-verified: Dolby Atmos reaches the receiver over HDMI, and an Apple TV switches into Dolby Vision on the first try, with a retry that keeps every audio track and subtitle when a TV's Match Content settings refuse the switch. The audio bridge is live too, so TrueHD and DTS arrive as EAC3 instead of being flattened.

On the roadmap

  • Retire Prism — libmpv is still the fallback for sources PrismCore can't take, and only goes at parity
  • Close the last coverage gaps that keep that fallback alive
  • A/V sync on the software path, proven on a device under real load rather than against renderer stand-ins

PrismCore is vibecoded — designed and built with AI in the loop, the same way I help teams adopt AI day to day.