SkillAgentSearch skills...

media-playback-footguns

Media player traps on Media3/ExoPlayer and desktop engines: crossfade, audio focus, fades, loudness, DSP, queues and shuffle, position restore, service lifecycle, group listening

Install / Use

npx skills add maxrave-dev/kotlin-footguns --skill media-playback-footguns

Installs into whichever agent you are using.

About this skill
📄

SKILL.md

Installable skill definition

Quality Score

84/100

Supported Platforms

Universal

Our assessment of media-playback-footguns

media-playback-footguns scores 84/100 on our quality scale, 2954th of 4,592 Development & Engineering skills we index.

Its SKILL.md is 18 KB long, split into 5 sections and no code examples: a thorough specification that gives an agent plenty to work with.

With 1,440 GitHub stars, it is one of the more widely adopted skills in the catalogue.

Substance
30/30
Structure
11/20
Description
15/15
Adoption
13/20
Freshness
15/15

Maintenance, license and trust

  • The repository was last updated 7 days ago, so media-playback-footguns is actively maintained.
  • It is released under GPL-3.0, a copyleft license: you can use it, but modified versions you distribute must carry the same license.
  • Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

media-playback-footguns compared with similar skills

All 4 of these similar skills score higher than media-playback-footguns; compare them before choosing.

SkillScoreStarsUpdatedFormat
media-playback-footguns (this skill)by maxrave-dev841.4k7d agoSKILL.md
taste-skillby Leonxlnx100102.3ktodayCLAUDE.md
ai-job-searchby ai-job-search-dev10065.4k4d agoCLAUDE.md
claude-howtoby luongnv8910044.9k5d agoCLAUDE.md
algorithmic-artby anthropics100177.9k33d agoSKILL.md

Frequently asked questions

How do I install media-playback-footguns?
Run npx skills add maxrave-dev/kotlin-footguns --skill media-playback-footguns. The install tabs above show the steps for each supported agent.
Which AI agents does media-playback-footguns work with?
It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
Is media-playback-footguns safe to use?
It is GPL-3.0-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is media-playback-footguns still maintained?
The repository was last updated 7 days ago, so media-playback-footguns is actively maintained.

name: media-playback-footguns description: "Media player traps on Media3/ExoPlayer and desktop engines: crossfade, audio focus, fades, loudness, DSP, queues and shuffle, position restore, service lifecycle, group listening. Use when playback state, queue or audio levels go wrong."

Media playback footguns

33 traps mined from a production Kotlin and Compose Multiplatform app, one short file each under references/. Every file gives the working pattern, the Traps (the specific ways it fails in practice, and why), and a Verifying it section with commands to run against the user's own tree.

How to use this index. Match the code about to be written, or the symptom being chased, against the entries below: each names its topic and the symptom that should send you to it. Read every file that plausibly applies with the Read tool before proposing code or a fix; each is under 150 lines. Where a Verifying command names the source project's paths, substitute the equivalent paths in the user's tree.

Cross-references. A backticked trap name inside a file that is not listed here lives in a sibling area skill: glob ../*/references/<name>.md to open it.

Players, crossfade and engine lifecycle

  • crossfade-dual-player — Build a crossfade between two media items with one player instance per item and a second live instance during the blend, then keep transport commands and playback settings correct while two players are audible. Use when adding a fade to a player, or when pausing mid-fade leaves the old track playing underneath, a seek appears to do nothing, playback speed reverts to 1.0x after a skip, or the volume slider fights the ramp.
  • guard-on-every-trigger-path — Keep the start conditions of a feature that fires from two entry points — typically a polling loop and an end-of-item callback — identical on both paths, because a condition added to only one of them is dead code that produces no error, no log and no crash. Use when a newly added guard, exclusion or feature flag appears to have no effect at all, or when a feature behaves correctly most of the time and wrongly in one specific timing.
  • crossfade-exclusion-heuristics — Decide when a crossfade must NOT run — the item plays as video, the item is too short for the fade, or two consecutive items belong to the same album — and encode each rule so it survives shuffle, an auto-length fade and a queue that keeps growing. Use when a fade cuts a song short, a video jumps to its first frame under the previous track, a 25-second interlude spends half its length fading, or an album sequenced to run continuously is interrupted between every track.
  • beatmatched-automix — Derive an automatic crossfade duration and a tempo/key match from how far apart two tracks are, the way a DJ would — halftime normalisation before comparing tempos, beat-quantised durations, a front-loaded ramp and quantised gain/speed steps. Use when an automatic transition length feels arbitrary, when tracks an octave apart in tempo are treated as a huge gap, when tempo matching only lands after the outgoing track is inaudible, or when ramping speed produces ticks.
  • forwarding-player-hot-swap — Swap the underlying player beneath a ForwardingPlayer at runtime while the media session and the UI keep one stable reference — re-attaching listeners and the video output, and answering the playlist questions a one-item timeline cannot. Use when next/previous buttons vanish from the system notification, when nothing updates after the first swap, when video stops rendering after a track change, or when reporting a playlist index makes the app stop.
  • fgs-state-ended-trap — Suppress the "ended" playback state at a forwarding-player boundary while the underlying player is being replaced, so the media service is not torn down in the gap between one player finishing and the next starting. Use when background playback stops partway through a queue on some devices but never on your development phone, when the playback notification disappears between tracks, or when the app is frozen by the system mid-queue.
  • polymorphic-load-media-entry-point — One generic "load this item and start playing" function normalizes several item types into a single internal shape, routes the queue-seeding strategy off a discriminator, and gates every pre-enqueue policy at that one place. Use when playback can start from many screens and a rule (content filter, dedup, analytics, resume-without-autoplay) keeps getting forgotten on one of the paths.
  • play-intent-decided-before-load — Decide whether the freshly-loaded item should start, and where it should start, before you build it — then pass both into the load call, rather than loading with a hardcoded "start playing" and correcting it a moment later. Reach for it when a follower in a synchronised room bursts into sound in a session everyone else has paused, or when a newly loaded item audibly starts and then stops.
  • intent-flag-not-observed-state — A component that is committed to running but not yet running reports "not running", so anything that means intent must read the intent flag, not the observed one — and at a transition the intent flag must be waited for with a timeout rather than sampled inline. Use when one client's buffering hiccup stops a whole synchronised group, when appending to a queue in the background silences the track that was about to start, when a resume command is issued on every tick, or when a state read is wrong on exactly the transitions it exists for.
  • derive-seek-from-progress-flow — Detect a scrub as a playhead that moved further than wall-clock time can account for, from the progress stream every platform already emits, because the platform's own discontinuity callback exists on one backend only and neither the item stream nor the transport stream fires when a scrubber is dragged. Use when a seek by one member of a shared session is never sent, or when a cross-platform layer needs an event only one platform provides.
  • optional-engine-feature-degrade-in-tiers — An optional build-time dependency of a media engine may be missing from another platform's bundle, and the engine rejects the WHOLE chain string when one stage in it is unknown — so retry without the optional stage rather than losing the mandatory one, and return which tiers were accepted so callers never drive a stage that is not there. Use when a feature works on one platform's bundle and silently does nothing on another.

Audio processing: focus, fades, loudness and DSP

  • media3-custom-audio-processor — Write a custom audio processor for a Media3/ExoPlayer audio pipeline — a filter, a fade, a gain stage — that is toggled at runtime and shared across several concurrent players. Use when a processor you added does nothing until the next track, when playback wedges with no error, when put(ByteBuffer) throws on your own output buffer, or when two simultaneous players need one parameter to reach both.
  • realtime-biquad-dsp — Build a small real-time IIR filter in pure Kotlin from the audio-EQ-cookbook formulas — low-pass, high-pass, or a bank of peaking sections — with cascaded stages for a steeper slope, independent state per channel, neutral stages that keep the state size fixed, and lazy coefficient recompute. Use when a sweepable filter is needed inside an audio callback, when a stereo filter collapses the stereo image, when the filter output is silence or NaN, or when sweeping a cutoff or dragging a band produces ticks.
  • audio-fade-separate-gain-line — Implement a programmatic audio fade — a sleep timer, an alarm ramp, a duck — on a gain line of its own instead of the user's volume, and restore that gain from the player's own completion path. Use when a fade drags the volume slider down in the UI, when the app comes back permanently silent with a full slider, when a fade still ends in an audible click, or when audio briefly swells back after a fade completes.
  • audio-focus-multiplayer — Hold Android audio focus once at app level when several player instances are alive at the same time — dual-player crossfade, precached players — and keep focus-driven ducking off whatever gain line a fade already owns. Use when background playback dies between tracks, autoplay stalls after the first item, a duck never takes effect or never lifts, or volume jumps back to full in the middle of a transition.
  • per-track-loudness-normalization — Apply per-track loudness normalisation with the platform's loudness enhancer when each track gets its own player — re-creating the effect per track because it stays attached to one audio session, skipping it while a remote-playback session is active, and clamping the gain that comes from metadata. Use when normalisation works on the first track and silently stops afterwards, when enabling it throws while nothing is playing, or when every other track in a queue comes out louder.
  • filter-chain-two-owners-one-writer — Two independent features want entries in one engine property that holds the WHOLE chain, so writing it replaces everything — keep each feature's entries in its own field, compose them in a single writer, and let "clear" drop only its own tier. Use when a second effect is added beside an existing one, or when one of two effects works and then randomly stops working after a transition.
  • sampled-supplier-vs-per-handle-reapply — Two playback backends need opposite plumbing for the same setting — one whose per-stream consumers sample a shared field needs no push at all, one whose every new handle starts blank needs an explicit re-apply at each creation site. Use when a setting reaches the current track but not the next one, when it survives on one platform and not the other, or when a level set on several handles keeps reverting.
  • one-setting-two-backends — Make one stored value mean the same thing on two unrelated audio backends by defining the band centres, the width and the range once, verifying both against a reference implementation instead of by ear, and declining the platform's built-in effect whose parameters vary per device. Use when a tone or gain setting is being added on more than one platform, or when the same saved setting sounds different on each.

Queues, shuffle and position

  • queue-index-vs-shuffle-space — A player's "current index" is exposed to the UI but freezes on track change or highlights the wrong row once shuffle is on, because the engine's timeline order and the shuffled play order are two different index spaces. Use when the now-playing marker in a queue list is stuck, points one row off, or lights up every copy of a repeated track.
  • custom-shuffle-order — Replacing a media engine's default shuffle order so that tracks added mid-playback land contiguously after the current one instead of being scattered through the rest of the queue. Use when "play next" or an appended continuation page ends up in random positions while shuffle is on, or when writing any custom shuffle order

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars1.4k
CategoryDevelopment
Updated7d ago
Forks6

Languages

Python

Trust signals

100/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

No cautions