Engineer resilient Swift playback
Define the outcome
Produce a playback flow with one explicit session owner, a reducible product
state, bounded asynchronous work, deterministic teardown, coherent system
integration, and evidence for startup, stalls, failures, and memory.
Treat AVPlayer as an engine rather than a UI state model. Keep user intent,
item readiness, transport activity, presentation lifecycle, and system
conditions distinct. A compiling player is not complete if stale observations,
unbounded preloading, interruption bugs, or unmeasured stalls remain.
Read references selectively
- Read
references/architecture-and-state.md before choosing session ownership,
state inputs, Observation or KVO boundaries, and SwiftUI identity.
- Read
references/lifecycle-and-transport.md before preparing or replacing an
item, seeking, observing time, handling completion, or tearing down playback.
- Read
references/presentation-and-system-integration.md for VideoPlayer,
AVPlayerLayer, AVPlayerViewController, full-screen, Picture in Picture,
audio sessions, background playback, Now Playing, remote commands, media
selection, accessibility, AirPlay, or external playback.
- Read
references/streaming-and-multiview.md for HLS, buffering, quality,
queues, looping, feeds, custom resource loading, offline media, FairPlay, or
coordinated simultaneous players.
- Read
references/diagnostics-and-testing.md before diagnosing a playback
symptom, making a performance claim, defining telemetry, or reporting
implementation completeness.
- Read
references/sources.md whenever a claim is SDK-sensitive, unfamiliar,
disputed, or requires an Apple sample or canonical API reference.
Repository instructions, supported platforms, the selected SDK, deployment
targets, content contracts, and the user's requested scope override generic
examples. Availability-check APIs at the call site; never raise a deployment
target silently.
Route the request
Choose one lead mode:
- Explain: clarify engine, item, transport, buffering, and presentation
semantics without editing.
- Design: specify ownership, state transitions, cancellation, content
policy, system integration, failure behavior, and evidence before APIs.
- Review or diagnose: inspect the actual ownership graph and event sequence;
report root causes and prioritized findings without fixing unless requested.
- Implement: make the smallest lifecycle-complete change and validate it.
- Profile: for measurement-dependent playback tuning or a performance claim,
establish an equivalent scenario, measure, change one supported mechanism,
and measure again.
- Research: prefer current Apple documentation and samples; separate
verified behavior from inference and older deployment-target fallbacks.
In Implement mode, apply a safe correction immediately when ownership, event
ordering, cancellation, observation teardown, or API semantics prove it.
Do not leave it as advice because a network profile, Simulator, physical
device, or performance baseline is unavailable. Run available correctness
checks and keep startup, stall, memory, and buffering claims pending until
measured.
Lead with $swift-player when the core question is media-session behavior.
Use $swift-concurrency for a deeper isolation or task-graph problem,
$swiftui-optimization for view invalidation or scrolling behavior, and
$app-performance for a whole-app performance investigation.
Do not lead with this skill for camera or microphone capture, recording,
editing, composition, export, transcoding, AVAudioEngine, DSP, or
backend-only HLS authoring unless playback is the specific boundary in scope.
Establish the playback contract
Before editing:
- Read repository instructions and inspect version-control status.
- Record platform, Xcode and SDK, deployment targets, UI framework, and whether
the project enables AVFoundation Observation.
- Classify the media: audio or video; local, progressive, HLS VOD, live,
low-latency live, offline, protected, queued, looped, or multiview.
- Record product semantics for autoplay, mute, resume, end, retry, scrubbing,
backgrounding, interruptions, routes, full-screen, PiP, and remote commands.
- Name the owner of the player, current item, preparation task, observations,
time observers, notification tokens, metric streams, and presentation
adapters. Give each one an end condition.
- Define the focused build, tests, network conditions, device checks, and
measurements that will prove the requested outcome.
Do not invent server, manifest, key-server, entitlement, audio-session, or
background-mode behavior. Surface missing contracts before encoding policy.
Preserve a stable session
Keep AVPlayer or AVQueuePlayer in a playback-session object whose lifetime
matches the product flow, not a transient SwiftUI body, list cell, or
presentation controller. Attach VideoPlayer, AVPlayerLayer, or
AVPlayerViewController as presentation adapters.
Use the system player by default when it meets the product requirements. A
custom control surface inherits responsibility for accessibility, media
selection, full-screen, PiP, remote input, and platform conventions.
For inline → full-screen → PiP transitions, move or reconnect presentation
while retaining the session and item. Do not pause merely because a presenting
view receives onDisappear. Keep a poster until the active output reports a
displayable first frame.
Reduce signals into product state
Keep requested playback intent separate from observed transport state. Reduce
at least these inputs:
AVPlayerItem.status;
AVPlayer.timeControlStatus and reasonForWaitingToPlay;
- current and seekable time, duration, and buffer signals;
- end, stall, and failure notifications;
- preparation, seek, and retry generations;
- interruption, route, background, PiP, and external-playback events;
- first-frame readiness for video.
Model domain states such as idle, preparing, readyPaused, playing,
waiting(reason), seeking, ended, and failed(error). Represent
interruption and presentation facts orthogonally when collapsing them would
lose user intent. Never use rate == 0 as the sole definition of paused,
buffering, ended, or failed.
Make replacement and teardown symmetric
When replacing an item:
- Advance a request generation and cancel the preparation task.
- Cancel pending seeks and prerolls.
- Remove old item observations, notifications, metric streams, and derived
item state.
- Create the new item context and install observations with initial delivery
or an explicit current-value snapshot.
- Replace the current item and seed player-derived state.
- Publish readiness or failure only if the request generation is still
current.
- Restore playback only when current user intent and policy allow it.
Explicitly remove every periodic or boundary time observer from the player that
created it. Do not defer correctness to deinit; teardown must also run for
item replacement, session reset, and cancelled presentation flows.
Apply deliberate media policy
- Load asset properties asynchronously in cancellable work. Do not perform
media I/O through synchronous property access on the main actor.
- Coalesce scrubber seeks, cancel obsolete seeks, use tolerances during
interactive movement, and reserve exact seeking for a justified final target.
- Leave forward-buffer selection to AVFoundation by default. Override startup,
bitrate, resolution, and buffer policy per measured scenario.
- Bound active players and prewarming in feeds. Prefer posters or async
thumbnails for offscreen content.
- Treat HLS authoring, CDN responses, content keys, and playlist continuity as
part of playback correctness.
AVQueuePlayer alone does not guarantee a
gapless transition.
- Use Apple offline-download and content-key lifecycles where they fit. Do not
build a whole-file
Data cache behind AVAssetResourceLoader.
Integrate with the system coherently
Configure the audio session and background capabilities from the product
contract. Handle interruptions and route changes as state-machine inputs, and
resume only when system options and the prior user intent both permit it.
Keep Now Playing metadata, elapsed time, rate, and command availability aligned
with the same domain state as in-app controls. Gate the current Now Playing
framework by SDK and deployment target; preserve a deliberate
MPNowPlayingInfoCenter and MPRemoteCommandCenter fallback when required.
Treat PiP, AirPlay, external playback, captions, alternate audio, and
accessibility as first-class playback behavior. Verify custom controls with
VoiceOver, Dynamic Type, hardware input where applicable, and the system's
media-selection expectations.
Verify and report
Run the repository's formatting, static analysis, focused tests, and affected
builds. Exercise rapid item replacement, repeated seeks, slow and lossy
networks, background and foreground, interruption and route changes, end and
retry, inline/full-screen/PiP, and every supported multi-player mode.
Measure user-intent-to-first-frame or first-audio latency, stall count and
duration, seek latency, failures by stage, active player and task counts, and a
memory baseline across repeated open/close cycles. Use AVMetrics for supported
HLS paths and retain access logs, error logs, notifications, signposts, and
device traces for other paths.
Finish with the mode, environment, content contract, ownership graph, state and
cancellation model, changes or findings, checks run, measured evidence, system
integration, public behavior changes, and remaining uncertainty. Never claim
seamless playback, a fixed leak, or better buffering without corresponding
evidence.
1---2name: swift-player3description: Use when designing, implementing, refactoring, reviewing, debugging, or profiling Swift media playback for iOS, iPadOS, tvOS, visionOS, macOS, or Mac Catalyst with AVFoundation, AVKit, SwiftUI, or UIKit/AppKit. Trigger for AVPlayer, AVQueuePlayer, AVPlayerItem, audio or video players, HLS/VOD/live/offline playback, loading or seeking, buffering and stalls, playback state, player lifetime, observation teardown, inline/full-screen/Picture in Picture transitions, background audio, interruptions and route changes, Now Playing or remote commands, subtitles and accessibility, multiple synchronized players, AirPlay, FairPlay or resource loading, playback metrics, memory, and playback tests.4---56# Engineer resilient Swift playback78## Define the outcome910Produce a playback flow with one explicit session owner, a reducible product11state, bounded asynchronous work, deterministic teardown, coherent system12integration, and evidence for startup, stalls, failures, and memory.1314Treat `AVPlayer` as an engine rather than a UI state model. Keep user intent,15item readiness, transport activity, presentation lifecycle, and system16conditions distinct. A compiling player is not complete if stale observations,17unbounded preloading, interruption bugs, or unmeasured stalls remain.1819## Read references selectively2021- Read `references/architecture-and-state.md` before choosing session ownership,22 state inputs, Observation or KVO boundaries, and SwiftUI identity.23- Read `references/lifecycle-and-transport.md` before preparing or replacing an24 item, seeking, observing time, handling completion, or tearing down playback.25- Read `references/presentation-and-system-integration.md` for `VideoPlayer`,26 `AVPlayerLayer`, `AVPlayerViewController`, full-screen, Picture in Picture,27 audio sessions, background playback, Now Playing, remote commands, media28 selection, accessibility, AirPlay, or external playback.29- Read `references/streaming-and-multiview.md` for HLS, buffering, quality,30 queues, looping, feeds, custom resource loading, offline media, FairPlay, or31 coordinated simultaneous players.32- Read `references/diagnostics-and-testing.md` before diagnosing a playback33 symptom, making a performance claim, defining telemetry, or reporting34 implementation completeness.35- Read `references/sources.md` whenever a claim is SDK-sensitive, unfamiliar,36 disputed, or requires an Apple sample or canonical API reference.3738Repository instructions, supported platforms, the selected SDK, deployment39targets, content contracts, and the user's requested scope override generic40examples. Availability-check APIs at the call site; never raise a deployment41target silently.4243## Route the request4445Choose one lead mode:4647- **Explain**: clarify engine, item, transport, buffering, and presentation48 semantics without editing.49- **Design**: specify ownership, state transitions, cancellation, content50 policy, system integration, failure behavior, and evidence before APIs.51- **Review or diagnose**: inspect the actual ownership graph and event sequence;52 report root causes and prioritized findings without fixing unless requested.53- **Implement**: make the smallest lifecycle-complete change and validate it.54- **Profile**: for measurement-dependent playback tuning or a performance claim,55 establish an equivalent scenario, measure, change one supported mechanism,56 and measure again.57- **Research**: prefer current Apple documentation and samples; separate58 verified behavior from inference and older deployment-target fallbacks.5960In Implement mode, apply a safe correction immediately when ownership, event61ordering, cancellation, observation teardown, or API semantics prove it.62Do not leave it as advice because a network profile, Simulator, physical63device, or performance baseline is unavailable. Run available correctness64checks and keep startup, stall, memory, and buffering claims pending until65measured.6667Lead with `$swift-player` when the core question is media-session behavior.68Use `$swift-concurrency` for a deeper isolation or task-graph problem,69`$swiftui-optimization` for view invalidation or scrolling behavior, and70`$app-performance` for a whole-app performance investigation.7172Do not lead with this skill for camera or microphone capture, recording,73editing, composition, export, transcoding, `AVAudioEngine`, DSP, or74backend-only HLS authoring unless playback is the specific boundary in scope.7576## Establish the playback contract7778Before editing:79801. Read repository instructions and inspect version-control status.812. Record platform, Xcode and SDK, deployment targets, UI framework, and whether82 the project enables AVFoundation Observation.833. Classify the media: audio or video; local, progressive, HLS VOD, live,84 low-latency live, offline, protected, queued, looped, or multiview.854. Record product semantics for autoplay, mute, resume, end, retry, scrubbing,86 backgrounding, interruptions, routes, full-screen, PiP, and remote commands.875. Name the owner of the player, current item, preparation task, observations,88 time observers, notification tokens, metric streams, and presentation89 adapters. Give each one an end condition.906. Define the focused build, tests, network conditions, device checks, and91 measurements that will prove the requested outcome.9293Do not invent server, manifest, key-server, entitlement, audio-session, or94background-mode behavior. Surface missing contracts before encoding policy.9596## Preserve a stable session9798Keep `AVPlayer` or `AVQueuePlayer` in a playback-session object whose lifetime99matches the product flow, not a transient SwiftUI `body`, list cell, or100presentation controller. Attach `VideoPlayer`, `AVPlayerLayer`, or101`AVPlayerViewController` as presentation adapters.102103Use the system player by default when it meets the product requirements. A104custom control surface inherits responsibility for accessibility, media105selection, full-screen, PiP, remote input, and platform conventions.106107For inline → full-screen → PiP transitions, move or reconnect presentation108while retaining the session and item. Do not pause merely because a presenting109view receives `onDisappear`. Keep a poster until the active output reports a110displayable first frame.111112## Reduce signals into product state113114Keep requested playback intent separate from observed transport state. Reduce115at least these inputs:116117- `AVPlayerItem.status`;118- `AVPlayer.timeControlStatus` and `reasonForWaitingToPlay`;119- current and seekable time, duration, and buffer signals;120- end, stall, and failure notifications;121- preparation, seek, and retry generations;122- interruption, route, background, PiP, and external-playback events;123- first-frame readiness for video.124125Model domain states such as `idle`, `preparing`, `readyPaused`, `playing`,126`waiting(reason)`, `seeking`, `ended`, and `failed(error)`. Represent127interruption and presentation facts orthogonally when collapsing them would128lose user intent. Never use `rate == 0` as the sole definition of paused,129buffering, ended, or failed.130131## Make replacement and teardown symmetric132133When replacing an item:1341351. Advance a request generation and cancel the preparation task.1362. Cancel pending seeks and prerolls.1373. Remove old item observations, notifications, metric streams, and derived138 item state.1394. Create the new item context and install observations with initial delivery140 or an explicit current-value snapshot.1415. Replace the current item and seed player-derived state.1426. Publish readiness or failure only if the request generation is still143 current.1447. Restore playback only when current user intent and policy allow it.145146Explicitly remove every periodic or boundary time observer from the player that147created it. Do not defer correctness to `deinit`; teardown must also run for148item replacement, session reset, and cancelled presentation flows.149150## Apply deliberate media policy151152- Load asset properties asynchronously in cancellable work. Do not perform153 media I/O through synchronous property access on the main actor.154- Coalesce scrubber seeks, cancel obsolete seeks, use tolerances during155 interactive movement, and reserve exact seeking for a justified final target.156- Leave forward-buffer selection to AVFoundation by default. Override startup,157 bitrate, resolution, and buffer policy per measured scenario.158- Bound active players and prewarming in feeds. Prefer posters or async159 thumbnails for offscreen content.160- Treat HLS authoring, CDN responses, content keys, and playlist continuity as161 part of playback correctness. `AVQueuePlayer` alone does not guarantee a162 gapless transition.163- Use Apple offline-download and content-key lifecycles where they fit. Do not164 build a whole-file `Data` cache behind `AVAssetResourceLoader`.165166## Integrate with the system coherently167168Configure the audio session and background capabilities from the product169contract. Handle interruptions and route changes as state-machine inputs, and170resume only when system options and the prior user intent both permit it.171172Keep Now Playing metadata, elapsed time, rate, and command availability aligned173with the same domain state as in-app controls. Gate the current Now Playing174framework by SDK and deployment target; preserve a deliberate175`MPNowPlayingInfoCenter` and `MPRemoteCommandCenter` fallback when required.176177Treat PiP, AirPlay, external playback, captions, alternate audio, and178accessibility as first-class playback behavior. Verify custom controls with179VoiceOver, Dynamic Type, hardware input where applicable, and the system's180media-selection expectations.181182## Verify and report183184Run the repository's formatting, static analysis, focused tests, and affected185builds. Exercise rapid item replacement, repeated seeks, slow and lossy186networks, background and foreground, interruption and route changes, end and187retry, inline/full-screen/PiP, and every supported multi-player mode.188189Measure user-intent-to-first-frame or first-audio latency, stall count and190duration, seek latency, failures by stage, active player and task counts, and a191memory baseline across repeated open/close cycles. Use `AVMetrics` for supported192HLS paths and retain access logs, error logs, notifications, signposts, and193device traces for other paths.194195Finish with the mode, environment, content contract, ownership graph, state and196cancellation model, changes or findings, checks run, measured evidence, system197integration, public behavior changes, and remaining uncertainty. Never claim198seamless playback, a fixed leak, or better buffering without corresponding199evidence.