PlaybackWarning
Something went wrong and playback continued.
Every warning names a degradation the developer would otherwise have to discover by measurement.
Inheritors
Types
A server refused an address of the item with status, 401 or 403, after it opened, as one does when a signed address expires, and the player opened the item again through its resolver or its io factory, at the position it had reached (#453). uri is the refused address's file name alone, so no token of a signed address shows. The picture holds for that moment. The player does this once until playback has moved on, so a resolver that hands out the refused address again ends in the server's answer as before.
The audio device restarted, changed or was replaced.
The DEVICE reported that it ran dry, through the sink's own event feed.
The device never reported its buffer empty at the end of the media, so the drain was bounded out.
The sink cannot report its latency usefully, so the audio clock is counted rather than measured and synchronisation is approximate. Emitted once per sink.
The decoder started producing a different audio format part way through the same stream.
An AudioTap threw. It was detached so the sound could carry on, and detail is what it threw.
The audio device ran out of data.
Timestamps in the stream are broken and the engine is compensating.
The source's channel layout could not be identified well enough to mix by speaker, so the layout was guessed from the channel count or the channels were passed through in source order. Emitted once per audio format.
The colour of this stream is APPROXIMATED, and it is shown anyway. Emitted once per stream.
A control the engine could not honour, named so a fire-and-forget caller still finds out The suspending form of the same member throws instead; this warning is how the refusal reaches KitePlayer.events and the warning history when the caller never awaited a reply: a refused loop repeat on an unseekable source, a speed or pitch-law change such a source cannot anchor, or a renderer swap whose scheduler never quiesced.
The container declared one thing about a stream and its decoder produced another.
A crop the container states for stream streamIndex leaves nothing of its pictures, or has a negative count, so the pictures are shown whole (#497). Emitted once each time the stream is opened. See PictureCrop.
An interlaced stream plays without deinterlacing, although PlayerConfig.deinterlace asked for it, because this build has no deinterlacing filter: the web build has no filters at all.
Playback follows no external clock right now: none is set although the sync mode is SyncMode.ExternalMaster, or the clock has given no moving answer for 2 s. Playback goes on at its own pace on its audio clock. Sent once, and armed again when answers move again.
Frames are being dropped to keep up with the clock.
The queue item at index did not follow the one before it without a gap. The device stopped at the end of that item, and this one opened from scratch, as it does with QueueConfig.gapless off. reason names what stopped the gapless handoff.
The item is marked as still being written (MediaItem.growth), but nothing gave it a reader: it has no io of its own, and no installed provider serves its address, which for a local path is one that serves local files, so it plays as the file stood when it opened (#430). Adding kiteplayer-io, or giving the item an io factory, cures it. uri is the file's name alone.
A hardware decoder was unavailable or failed and policy allowed playback to continue in software.
HDR was rolled off to standard dynamic range so this display can show it. Once per open.
The renderer lost its surface. Audio continues and video frames are discarded.
Open options the demuxer never consumed: a typo'd key, or one this protocol does not take. The open succeeded; the option did nothing, and pretending otherwise is how a configuration bug survives for months.
The file is interleaved so badly that one stream had to be truncated to keep the other playing.
The queue item at index could not be opened, with error, and the queue moved past it, because QueueConfig.onItemFailure is QueueItemFailure.Skip (#487).
A recording ended without KitePlayer.stopRecording, KitePlayer.stop or KitePlayer.close, or its file could not be finished. The file at path keeps what was recorded until then.
The attached renderer reported an unrecoverable failure through its own event feed. Playback continues; the schedule keeps pacing and the renderer keeps refusing, so the degradation is a black or frozen picture, which is exactly why it is worth a warning.
The configured AudioConfig.resampler could not make a resampler, so the engine converts the sample rate with its own windowed sinc instead. The usual cause is a factory with no implementation on this platform: KiteFFmpegResampler has none on the web. Once per player; the audio plays.
Tearing a session down did not release everything cleanly.
An address that an HLS stream names could not be read: a segment, the key of a segment, or a playlist that a live stream reloads. detail says what failed. The demuxer skips a segment it cannot read, so the picture and the sound jump past it. A stream that ends while its last addresses fail ends with PlaybackError.SourceUnavailable instead of as complete.
The reader lost its connection to the source at byte position and is connecting again, for the attempt-th time in one read. detail says what failed. Playback waits meanwhile, and it fails only when the reader gives up or BufferPolicy.stallTimeout passes.
The item asked to start somewhere the open could not take it: an unseekable source, or a position past the end. Playback starts where the container does instead, and this says so rather than leaving the caller to notice the position report.
Open completed before the initial fill reached readiness: the source is slow, so playback will begin in Buffering instead of with a ready pipeline. Opened is still truthful about the session existing; this says the pipeline behind it is not yet primed.
An external subtitle file whose encoding had to be guessed, or could not be decoded properly.
Some subtitles were not drawn, or none were. detail says why: the cues on screen went past a limit of io.github.yuroyami.kiteplayer.spi.SubtitleRasterizer, or the rasterizer or the renderer failed. Playback continues, and the next change of the subtitles draws again. Once per opened item for a limit, and once per player for a failure.
An external subtitle could not be read or parsed, so it was skipped.
The item's WebVTT thumbnail file at uri could not be read or held no picture, so the seek bar has none of its pictures (#433). The item plays on, and the stream's own pictures, when it has any, stand in.
DEPRECATED 2026-08-25 and NEVER EMITTED.
A non-essential track failed and was deselected.
An ASS track met an installed typesetting engine that could not start, so the Kotlin dialogue tier draws it instead: styles and positions, no animated typesetting.
The player stepped an HLS stream down from the variant at from to the one at to, with a lower bitrate. Either playback waited too long for data, or the link read less media per second than playback uses. detail says which, with the wait or the measured rate. The stream opens again on the lower variant at the current position.
Properties
Functions
The type and the message, with every URI cut to its file name, as for PlaybackError.