Skip to content

3.1.0

Choose a tag to compare

@superuser404notfound superuser404notfound released this 10 Jun 22:11
· 180 commits to main since this release

Minor release: the data surface for host-side styled ASS/SSA rendering (#30) and a muxer fix that removes post-scrub A/V desync on the software path.

Added

Host-side ASS rendering contract (#30)

AetherEngine stays backend-only: it ships the data, the host renders. Two new pieces complete the contract started by LoadOptions.preserveASSMarkup and TrackInfo.assHeader in 3.0.0:

  • engine.fontAttachments exposes the container's embedded font attachments (TTF / OTF) as [FontAttachment] (filename, MIME type, raw data). Hosts stage them into a font directory for their renderer. Populated on every load(), cleared on stop(), and intentionally preserved across the in-session audio-switch reload.
  • ASSScriptBuilder reassembles the engine's raw paced event cues plus assHeader into a complete ASS script, ready for whole-file renderers such as swift-ass-renderer's loadTrack(content:). It is hardened against what real Matroska files actually contain:
    • synthesizes the [Events] section header when the track's CodecPrivate lacks it (libass otherwise reports 0 events),
    • strips NUL terminators from CodecPrivate (libass parses C-string style and silently stops at the first NUL),
    • dedupes by event content (start, end, text) instead of ReadOrder, because real muxes hardcode ReadOrder: 0 on every line.

Reference host integration: Sodalite's ASSRenderCoordinator (batched reloadTrack with imminent-flush, font staging, reload-nil suppression).

Fixed

Post-scrub lipsync drift and picture jumps (software path)

The fragmented-MP4 muxer wrote an edit list into init.mp4, baking the producer's restart position into elst. AVPlayer pins the first EXT-X-MAP it sees, so after a backward scrub the stale edit list shifted the presentation timeline: audio led or trailed the picture and the image visibly jumped. Edit lists are now disabled (use_editlist=0); the restart offset travels exclusively via per-track tfdt, making init.mp4 restart-invariant across producer restarts.

Compatibility

No breaking changes. Pin from: "3.1.0":

.package(url: "https://github.com/superuser404notfound/AetherEngine", from: "3.1.0")