Skip to content

Releases: yuroyami/KitePlayer

KitePlayer 0.3.0

Choose a tag to compare

@yuroyami yuroyami released this 09 Oct 02:50

0.3.0 is a big one: 193 issues closed since 0.2.0. A good part of the engine changed under the hood. If something that used to work now acts up, tell me on the tracker.

The main things that landed:

  • HLS and DASH run on KitePlayer's own network stack now. The player lists the qualities, then steps between them on its own. Most switches happen in place. Segments can also be cached on disk (opt-in).
  • Live sources: RTSP, RTMP, UDP, RTP. Internet radio reconnects when the server drops it, showing the current song as the title.
  • HDR10 and HLG show as real HDR on Apple or Android screens that can do it, instead of being tone mapped down. Dolby Vision profile 5 gets its colours right.
  • Subtitles: closed captions (CEA-608/708), DVB teletext, PGS, VobSub, SAMI, MicroDVD, TTML, synced lyrics. A second subtitle can follow your language list.
  • Audio: speed changes without a seek or a gap, pitch shift, night mode, dialogue level, stereo modes, skip silence, crossfade between queue items.
  • Playlists (M3U, PLS, XSPF) open straight into the queue, cue sheets too. The queue can skip past an item that will not open.
  • The browser gets a player that lives in a Web Worker.
  • Setup is shorter: KitePlayer(), rememberKitePlayer(), PlayerConfig { }, attachMediaSession, built-in player controls, a Java layer (KitePlayerJava).
  • The Anime4K upscaler runs on the Android GPU renderer or on Metal.
  • Windows decodes video on the GPU through Direct3D 11.

Under all of it is still FFmpeg 9.0.2, which I build for every platform as KiteFFmpeg 0.5.1.

Usage

// Native views, no Compose: the engine, FFmpeg, HTTP(S), libass subtitles, the input doors
implementation("io.github.yuroyami:kiteplayer:0.3.0")

// Compose: everything above, plus KitePlayerVideo, which picks a video path at runtime
implementation("io.github.yuroyami:kiteplayer-compose:0.3.0")

// Optional, next to either line
implementation("io.github.yuroyami:kiteplayer-audioviz:0.3.0")          // an audio visualiser for files with no picture, in Compose

// Or build your own player from the parts
implementation("io.github.yuroyami:kiteplayer-core:0.3.0")              // the engine and its service interfaces, with no FFmpeg, Ktor or Compose
implementation("io.github.yuroyami:kiteplayer-ffmpeg:0.3.0")            // the FFmpeg backend (pulls KiteFFmpeg)
implementation("io.github.yuroyami:kiteplayer-output:0.3.0")            // audio sinks and video renderers for each platform
implementation("io.github.yuroyami:kiteplayer-network:0.3.0")           // HTTP and HTTPS through Ktor, with the DASH reader
implementation("io.github.yuroyami:kiteplayer-io:0.3.0")                // input doors for files, streams, content URIs and assets
implementation("io.github.yuroyami:kiteplayer-libass:0.3.0")            // libass typesetting for ASS and SSA subtitles
implementation("io.github.yuroyami:kiteplayer-view:0.3.0")              // native video views
implementation("io.github.yuroyami:kiteplayer-compose-ui:0.3.0")        // KitePlayerVideo, for a player you build yourself
implementation("io.github.yuroyami:kiteplayer-compose-video:0.3.0")     // KiteVideo, the Compose-drawn video path, to use it directly
implementation("io.github.yuroyami:kiteplayer-compose-interop:0.3.0")   // KitePlayerSurface, the platform-view video path, to use it directly

kiteplayer-rt, kiteplayer-subtitles, kiteplayer-adaptive and kiteplayer-view-bindings arrive with the lines above. Do not add them yourself. kiteplayer-phone is gone.

Changelog

🔴 Breaking changes

Change What to do
#387: kiteplayer-compose-ui no longer exposes KitePlayerSurface, KiteVideo, rememberKiteVideoState or KiteVideoState. kiteplayer-compose loses them too Add kiteplayer-compose-interop or kiteplayer-compose-video yourself. Or draw with KitePlayerVideo
#387: kiteplayer-phone is gone, with its phoneBackends(), KitePlayerView, KitePlayerUIView Depend on kiteplayer. Use the views of kiteplayer-view
#91, #209, #376, #392, #430, #433, #453, #461, #487, #497, #547: PlaybackWarning has 11 new values: ExternalClockSilent, SegmentSkipped, VariantLowered, AudioSourceUnreadable, GrowthUnavailable, ThumbnailsUnreadable, AddressRenewed, Reconnecting, QueueItemSkipped, CropIgnored, SegmentStoreFailed Handle them in a when that has no else
#102, #395: PlaybackError has new RendererIncompatible and SchemeUnsupported values Handle them in a when that has no else
#509, 7517c2b: PlayerEvent has new values: TracksAdded, TrackChosenByPlayer, AudioOutputBecameNoisy Handle them in a when that has no else
#68, 7517c2b: The service interface events have new values: RendererEvent.HdrShown, AudioSinkEvent.BecameNoisy Handle them in a when that has no else
#389: VizNeed has new WaveformHistory and MemoryField values Handle them in a when that has no else
#497: The onVideoGeometry callback of AndroidPlayerViewRendererFactory.create takes a third parameter, the PictureCrop?. So does the one of the AndroidSurfaceVideoRenderer constructor Add the parameter to your lambda or override
#513: PlayerSnapshot and PlayerMemento have a new forcedPicturesOnly parameter in the middle of their constructors Pass the parameters after it by name
5634c33: The Android artifacts need an app compileSdk of 37 with minor API level 2 (0.2.0 needed 37) Set compileSdk { version = release(37) { minorApiLevel = 2 } }
#392: PlayerMemento.FORMAT_VERSION is 10. An older build refuses a memento that this one wrote Update every reader of stored mementos
#376, #447, #543: HLS and DASH streams now list their qualities, switching between them by themselves. The first choice follows the renderer: HDR on an HDR display, never larger than the drawn size Call selectVariant to hold one quality. DemuxPolicy.fit = VariantFit() gives the old first choice
#68: HdrPolicy.Auto is the default, so HDR10 and HLG show as HDR on a display that can Set HdrPolicy.ToneMap to keep the tone mapped picture
#238: The native Mac renderer keeps the display awake while a picture plays. The web renderers do too Pass keepDisplayAwake = false to manage the display yourself
e0f33b2: PlayerConfig.flashGuard is FlashGuard.FollowSystem, so Apple renderers dim flashing video when Dim Flashing Lights is on Pass FlashGuard.Off to leave the picture as it is
#499: SubtitleConfig.assColorMatching is on, so ASS colours follow the video's colour matrix when the script names another Set assColorMatching = false to keep the colours as written
30d282f: On Windows HwdecPolicy.Auto decodes H.264, HEVC, VP9, MPEG-2, VC-1, WMV3 through Direct3D 11. Those frames report PlayerPixelFormat.Opaque Read planes through planeFormat, or pass HwdecPolicy.Off
#452: An open that FFmpeg refuses as invalid data fails with PlaybackError.NotMedia, not SourceUnavailable Check for NotMedia where you handled bad input
#467: A repeated item or A-B loop no longer passes through Ended or Buffering. PlayerEvent.Opened no longer fires at each turn Count the turns of a repeated item with PlayerEvent.Ended
#483: A call made while 1024 requests already wait throws IllegalStateException Await earlier calls before you send more
#390: The Fireworks, Musical Spectrum and Muser drawings left the catalogue. A saved name of one now opens the first drawing Offer the user another drawing

The last ten rows still compile. They change behaviour only. A by wrapper of PlayerMediaSource that overrides only the old seekToKeyframe misses its new overload.

Everything since 0.2.0

...
AreaTypeChange
Read more

KitePlayer 0.2.0

Choose a tag to compare

@yuroyami yuroyami released this 29 Sep 23:52

Closing 180 issues.

Usage

// Native views, no Compose: the engine, FFmpeg, HTTP and HTTPS, libass subtitles and the input doors
implementation("io.github.yuroyami:kiteplayer:0.2.0")

// Compose: everything above, plus both Compose video paths
implementation("io.github.yuroyami:kiteplayer-compose:0.2.0")

// Optional, next to either line
implementation("io.github.yuroyami:kiteplayer-audioviz:0.2.0")      // an audio visualiser for files with no picture, in Compose

// Or build your own player from the parts
implementation("io.github.yuroyami:kiteplayer-core:0.2.0")          // the engine and its service interfaces, with no FFmpeg, Ktor or Compose
implementation("io.github.yuroyami:kiteplayer-ffmpeg:0.2.0")        // the FFmpeg backend (pulls KiteFFmpeg)
implementation("io.github.yuroyami:kiteplayer-output:0.2.0")        // audio sinks and video renderers for each platform
implementation("io.github.yuroyami:kiteplayer-network:0.2.0")       // HTTP and HTTPS through Ktor
implementation("io.github.yuroyami:kiteplayer-io:0.2.0")            // input doors for files, streams, content URIs and assets
implementation("io.github.yuroyami:kiteplayer-libass:0.2.0")        // libass typesetting for ASS and SSA subtitles
implementation("io.github.yuroyami:kiteplayer-view:0.2.0")          // native video views
implementation("io.github.yuroyami:kiteplayer-compose-ui:0.2.0")    // both Compose video paths, for a player you build yourself

kiteplayer-rt, kiteplayer-subtitles, kiteplayer-view-bindings, kiteplayer-compose-video, kiteplayer-compose-interop and kiteplayer-phone arrive with the lines above. Do not add them yourself.

Changelog

🔴 Breaking changes

Change What to do
#75: PlaybackWarning has a new GaplessFallback value Handle GaplessFallback in a when that has no else
#75: Queue items now follow each other without a gap, and the status stays Playing between items Set PlayerConfig.queue to QueueConfig(gapless = false) to keep the old path
#71: PlaybackWarning has a new DeinterlaceUnavailable value Handle DeinterlaceUnavailable in a when that has no else
#71: PlayerConfig.deinterlace is Auto by default, so an interlaced stream now decodes in software Pass DeinterlacePolicy.Off to keep hardware decoding
0e003dc: PlaybackWarning has a new SubtitlesNotDrawn value Handle SubtitlesNotDrawn in a when that has no else
0e003dc: The engine holds every subtitle rasterizer to the limits in the SubtitleRasterizer companion object, and cues past a limit are not drawn Throw SubtitleOverlayLimitException from a custom rasterizer to show part of an overlay
e54f920: AudioSinkEvent has a new Failed value Handle Failed in a when that has no else
#228: RendererEvent has a new ColorApproximated value Handle ColorApproximated in a when that has no else
#92: PlaybackError.AudioDeviceUnavailable now takes device and detail Pass both arguments
#97: KiteFFmpegVideoFrame.frame and AudioSamples are internal Draw web frames with KiteFFmpegWebPainter instead of WebRgbaConverter
#218: MasterClock.External, PlaybackError.DecoderUnavailable, OutputBackend.videoRenderer and AudioSinkBuffer.writePlane are removed Delete the when branches, and delete the overrides of the last two
#218: KitePlayer.create refuses SyncMode.ExternalMaster with ConfigurationInvalid Use another SyncMode
#220: AudioPlayback.submit is internal Call submitDecoded
#274: XmlMini and XmlElement are internal Use DashManifestParser.parse for a DASH manifest
#217: setSleepTimer throws IllegalArgumentException for a negative fade or an After that is not in the future Pass a valid fade and time
#256: openQueue refuses a session that is not Idle, Ended or Failed Call stop() first
#219: setAudioDelay, setSubtitleDelay, SubtitleConfig.delay and restore refuse a value that is not finite or is beyond KitePlayer.DELAY_MAX Keep delays within one hour either way
#203: ReplayGain no longer raises a track whose tags carry no peak, and AudioConfig.volumeCeiling no longer widens its clamp Raise the volume to make such a track louder
#280: InterruptionPolicy.duckVolume is now a factor on the listener's volume, not an absolute volume Set it as a share, for example 0.2 for a fifth
#214: PlayerMemento.FORMAT_VERSION is 4, and an older build refuses a memento that this one wrote Update every reader of stored mementos
#204: Every KitePlayer call that can fail declares @Throws, and KitePlayer.create throws a checked PlaybackException for Java Call them with try in Swift, and handle PlaybackException in Java
#240: Dash.mediaItemFor throws DashUnsupportedException for audio in its own adaptation set, live manifests and several Periods Catch it and fall back to another source
#237: On macOS the desktop JVM decodes with VideoToolbox under HwdecPolicy.Auto, and such frames report PlayerPixelFormat.Opaque Read planes through planeFormat, or pass HwdecPolicy.Off
#238: keepDisplayAwake is true by default, so the display no longer dims while video plays Pass keepDisplayAwake = false to manage the display yourself
#309: KitePlayerVideo has new trailing parameters, so a trailing lambda now binds to accessibilityStateFormat Pass onRendererAttached by name
264fbf6: The DASH door applies DashUrlPolicy to every redirect and follows at most five. Under DashUrlPolicy.SameOrigin a redirect to another scheme, host or port fails with DashUrlRefusedException Use DashUrlPolicy.Default for a CDN that redirects to another host
d2b315d: An external subtitle gets the item's headers only when it has the item's scheme, host and port Give its SubtitleSource its own io to send headers to another server

The rows about a default or a behaviour (the gapless queue, deinterlace, keepDisplayAwake, ReplayGain, ducking, redirects and subtitle headers) still compile. A by wrapper of VideoDecoderFactory that overrides only the old create also misses its new overload.

Everything since 0.0.27

AreaTypeChange
Playback (16)API Changes🔴 #217: setSleepTimer now throws IllegalArgumentException at the call for a bad fade or an After that is not in the future, and a refused A-B loop is published as CommandRefused.
🔴 #218: KitePlayer.create refuses SyncMode.ExternalMaster with ConfigurationInvalid. Removed MasterClock.External, PlaybackError.DecoderUnavailable, OutputBackend.videoRenderer and AudioSinkBuffer.writePlane, which nothing used.
#264: Thumbnail and Waveform now compare and hash their arrays by content.
Performance#245: Stopped a paused player from waking about 700 times a second.
Fixes#30: Made every read of the player's own doors interruptible and every wait bounded.
#31: Passed a cancel into FFmpeg's own protocols, so a stop or close ends an open that reads through the URL fallback or a file descriptor.
#200: Kept playing at the old position when a seek aborts because a worker could not park.
#202: Made inspect resolve readers the way open does, fail with a typed error and run off the caller's thread.
#213: Made restore check every setting befo...
Read more

KitePlayer 0.0.27

Choose a tag to compare

@yuroyami yuroyami released this 25 Sep 17:07

KitePlayer 0.0.27 now plays in the background on Android with its own media service and notification, and opens media through typed input doors in the new kiteplayer-io module. It ships native libraries for 32-bit ARM Android through KiteFFmpeg 0.3.0, and closes more than seventy issues (78 issues, plus 16 changes that never had one). Ten of them break-change the API or its defaults (they are marked 🔴 below).

Usage

// Native views, no Compose: the engine, FFmpeg, HTTP and HTTPS, libass subtitles and the input doors
implementation("io.github.yuroyami:kiteplayer:0.0.27")

// Compose: everything above, plus both Compose video paths
implementation("io.github.yuroyami:kiteplayer-compose:0.0.27")

// Optional, next to either line
implementation("io.github.yuroyami:kiteplayer-audioviz:0.0.27")      // an audio visualiser for files with no picture, in Compose

// Or build your own player from the parts
implementation("io.github.yuroyami:kiteplayer-core:0.0.27")          // the engine and its service interfaces, with no FFmpeg, Ktor or Compose
implementation("io.github.yuroyami:kiteplayer-ffmpeg:0.0.27")        // the FFmpeg backend (pulls KiteFFmpeg)
implementation("io.github.yuroyami:kiteplayer-output:0.0.27")        // audio sinks and video renderers for each platform
implementation("io.github.yuroyami:kiteplayer-network:0.0.27")       // HTTP and HTTPS through Ktor
implementation("io.github.yuroyami:kiteplayer-io:0.0.27")            // input doors for files, streams, content URIs and assets (new in 0.0.27)
implementation("io.github.yuroyami:kiteplayer-libass:0.0.27")        // libass typesetting for ASS and SSA subtitles
implementation("io.github.yuroyami:kiteplayer-view:0.0.27")          // native video views
implementation("io.github.yuroyami:kiteplayer-compose-ui:0.0.27")    // both Compose video paths, for a player you build yourself

kiteplayer-rt, kiteplayer-subtitles, kiteplayer-view-bindings, kiteplayer-compose-video, kiteplayer-compose-interop and kiteplayer-phone arrive with the lines above. Do not add them yourself.

Changelog

🔴 Breaking changes

Change What to do
#42: Reading MediaItem.openOptions needs @OptIn(KitePlayerLowLevelApi::class) Add the opt-in, or move the option to a typed field
450c61c: VizFamily, Visualization.family, VizCatalog.byFamily() and the category argument of the drawing constructors are gone Use VizCatalog.create(), and fall back when a saved drawing name is gone
#32: PlaybackError has a new SourceStalled subtype Handle SourceStalled in a when that has no else
#96: PlaybackWarning has new SourceReconnecting, RecordingStopped (#86) and ResamplerUnavailable (#87) subtypes Handle them in a when that has no else
c0bb8ab: KiteFFmpeg 0.3.0 names a decoder with DecoderId and an encoder with EncoderId Update your own KiteFFmpeg calls, if you make any
#32: A source that sends nothing for 30 seconds now ends the session (BufferPolicy.stallTimeout) Set stallTimeout = Duration.INFINITE to wait as before
#96: The HTTP reader reconnects up to five times when a connection drops Set HttpReaderPolicy.maxReconnects = 0 to fail on the first drop
#50: A raw open option that a typed field also sets refuses the open with PlaybackError.ConfigurationInvalid Set each option in one place
#104: PlaybackWarning.SubtitleCharsetGuessed.detected names one encoding, such as Shift_JIS or EUC-KR Match on the new names
76010f6: MediaItem.label, printed errors and diagnosticsDump() hide URL queries and header values Read MediaItem.uri for the full URI

The last five still compile, but the player behaves differently.

Everything since 0.0.26

AreaTypeChange
Opening media (11)New Features#44: Added a bounded pipe for media that arrives by push, such as a socket or a decryptor
#45: Added kiteplayer-io, a module of input doors, with doors for JVM files, paths, channels and streams
#46: Added a file path door for Apple and Linux, and a file URL door for Apple
#47: Added Android doors for content URIs and bundled assets (MediaIo.ofUri, MediaIo.ofAsset)
API Changes🔴 #42: Required @OptIn(KitePlayerLowLevelApi::class) to read MediaItem.openOptions, which carries raw FFmpeg syntax
#48: Added typed container-open settings (MediaItem.demux) and the mediaItem { } builder
Fixes#34: Read a caller's descriptor by position, so no open moves its file offset
🔴 #50: Refused an open option that is set both raw and typed, and applied the typed demux settings
#148: Opened an item the same way for playback, thumbnails, waveforms and loudness
#149: Kept each item's demux settings in a saved session
Docs#51: Documented which input door to use for the media an app has, and the item builder
Playback (7)New Features#69: Stepped a paused player back one frame (StepDirection)
#80: Added KiteTrace and ChromeTraceFormat, a timeline of the player that Chrome's trace viewer and Perfetto open
🔴 #86: Added startRecording and stopRecording, which copy what the player reads into a Matroska file without a re-encode, everywhere except the web
Fixes#152: Resumed from the picture after forward frame steps, instead of playing the skipped audio under a still picture
#153: Kept the position from jumping ahead by the paused time after a resume
#156: Showed exactly the next frame on every forward step, even when the schedule runs late
3498eef: Closed every part of an FFmpeg source even when one part fails
Audio (4)New Features🔴 #87: Let an app replace the engine's rate conversion with AudioConfig.resampler, and added KiteFFmpegResampler, which runs FFmpeg's libswresample
f54e46e: Reported a change of the default audio output on macOS as an AudioDeviceChanged warning, and kept playing on the new output
Fixes8a51014: Refused to build the audio ring on a target where its 64-bit counters would take a lock, so it cannot click or drift there
fc819ca: Turned the iOS audio session on again when playback resumes after an interruption, such as a phone call
Video and rendering (6)New Features#70: Reported the display's own presented time for each Metal frame
#72: Added a gamma control to the picture adjustments (VideoAdjustments.gamma)
Fixes#66: Made RenderQuality.linearLight scale the picture in linear light on both GPU renderers
#95: Attached VideoToolbox to FFmpeg's own AV1 decoder on Apple, so hardware AV1 can engage
#129: Converted Identity video a...
Read more

KitePlayer 0.0.26

Choose a tag to compare

@yuroyami yuroyami released this 22 Sep 09:40

Usage

// Native views, no Compose.
implementation("io.github.yuroyami:kiteplayer:0.0.26")

// Compose playback, including the default player and both video paths.
implementation("io.github.yuroyami:kiteplayer-compose:0.0.26")

// Optional Compose audio visualiser, alongside either playback dependency.
implementation("io.github.yuroyami:kiteplayer-audioviz:0.0.26")

Changelog

  • Added KitePlayer.scanAudio, which decodes an audio track a second time without playing it, a background song scan that builds a song map, and SongMapStore to keep a finished map between runs. Fixes #140.
  • Added live detection of sections, drops and breakdowns, and a live key estimate, for a song with no map yet.
  • Added KitePlayer.audioClock: the audible position, its rate and its generation in one read.
  • Added AudioVizState.framesPerSecond, a cap on how often the visualiser redraws. Fixes #146.
  • Added Odyssey, a journey through districts generated from a seed drawn at launch, so two runs show two different worlds, and Neon Lo-Fi, which replaces Terrain March and still answers to that name. See #147.
  • Changed the catalogue to 46 drawings, down from 78. Thirty-four are gone, and only Terrain March has a replacement that answers to its old name. No published symbol changed.
  • Fixed a flying drawing travelling while the player was paused, and drifting on through a silence. Fixes #144.
  • Fixed Android hardware frames counting as presented when the display never showed them, and the Compose video view redrawing on every display refresh. Fixes #137 and #138.
  • Fixed a video track change answering before the snapshot showed the new selection. Fixes #142.
  • Breaking: rememberAudioVizState takes a songScan policy and a songMapStore, both with defaults. SpectrumAnalyzer.feed and the VisualizerSurface composables are gone.

See the full changelog for the complete list.

Dependencies

  • Kotlin 2.4.10, Compose Multiplatform 1.12.0
  • Android Gradle Plugin 9.4.0, Gradle 9.7.1, JDK 21; Android minSdk 26
  • KiteFFmpeg 0.2.0, Kite3D 0.2.0 for the optional visualiser
  • Ktor 3.5.2, libass 0.17.4

KitePlayer 0.0.25

Choose a tag to compare

@yuroyami yuroyami released this 15 Sep 02:37

The audio visualiser no longer crashes on Android 13 and newer, and the media session behaves on every platform: buffering shows as buffering, the lock screen and the now playing card are written only when they would be wrong, and the web gets browser media controls.

Usage

// Native views, no Compose.
implementation("io.github.yuroyami:kiteplayer:0.0.25")

// Compose playback, including the default player and both video paths.
implementation("io.github.yuroyami:kiteplayer-compose:0.0.25")

// Optional Compose audio visualiser, alongside either playback dependency.
implementation("io.github.yuroyami:kiteplayer-audioviz:0.0.25")

Changelog

  • Fixed the audio visualiser crashing on Android 13 and newer with "Software rendering doesn't support RuntimeShader". On Android, warp drawings now leave a plain echo instead of a bent one. Fixes #135.
  • Fixed a stalled stream showing as paused on the Android lock screen, and the lock screen being rewritten on every tick.
  • Fixed the iOS now playing card being rebuilt five times a second. Live streams are marked live and get no scrub bar.
  • Added browser media controls on the web through KitePlayerMediaSession, and a desktop stub that reports it is unavailable.
  • Both samples now use the media session and the playback guards. Fixes #77.
  • Breaking: MediaSessionState takes a phase and a hasVideo flag. Code that builds or copies one needs the new parameters; reading playing works as before.

See the full changelog for the complete list.

Dependencies

  • Kotlin 2.4.10, Compose Multiplatform 1.12.0
  • Android Gradle Plugin 9.4.0, Gradle 9.7.1, JDK 21; Android minSdk 26
  • KiteFFmpeg 0.2.0, Kite3D 0.2.0 for the optional visualiser
  • Ktor 3.5.2, libass 0.17.4

KitePlayer 0.0.24

Choose a tag to compare

@yuroyami yuroyami released this 12 Sep 12:58

Audio-only media gets a picture. The optional audio visualiser follows the sound through seeks and track changes, with 78 drawings, palettes and a director that changes drawings with the music.

Usage

// Native views, no Compose.
implementation("io.github.yuroyami:kiteplayer:0.0.24")

// Compose playback, including the default player and both video paths.
implementation("io.github.yuroyami:kiteplayer-compose:0.0.24")

// Optional Compose audio visualiser, alongside either playback dependency.
implementation("io.github.yuroyami:kiteplayer-audioviz:0.0.24")

The visualiser supports Android, iOS and the desktop JVM. Show KiteAudioViz when PlayerSnapshot.isAudioOnly is true. Attached album art still counts as audio-only media. The README has the integration example.

Changelog

  • Added the optional audio visualiser and public audio taps for meters and custom drawings. Scene pixels, uploads and buffers are reused; bloom uses a filtered image pyramid and trail resolution adapts to frame cost. Measurements and limits.
  • Added interruption and background handling, platform media sessions, iOS picture in picture, and Android picture-in-picture helpers.
  • Added media inspection without playback, frame capture with subtitles, HTTP external subtitles, and mementos carrying picture, subtitle and audio settings.
  • Added MediaIo.ofBytes and MediaItem.from for media already held in memory. Each open gets an independent reader without copying the bytes. Fixes #43.
  • Backward seeks first request a two-second window, then retry without it if the container refuses. Fixes #35.
  • Fixed Android Surface changes blocking the main thread, and software video ignoring picture adjustments.
  • Fixed downmixing to mono and quad layouts, YCgCo colours, Metal chroma placement, WebVTT positioning, and the last subtitle being cut off at EOF.
  • Breaking: kiteplayer-mobile is removed. Use kiteplayer; Kotlin package names are unchanged.
  • Breaking: MediaItem.io uses the named MediaIoFactory interface. Lambdas at call sites still convert. Recompile consumers.
  • Breaking: fflags=fastseek and usetoc are refused because the engine owns the MP3 seek strategy.

See the full changelog for the complete list.

Dependencies

  • Kotlin 2.4.10, Compose Multiplatform 1.12.0
  • Android Gradle Plugin 9.4.0, Gradle 9.7.1, JDK 21; Android minSdk 26
  • KiteFFmpeg 0.2.0, Kite3D 0.2.0 for the optional visualiser
  • Ktor 3.5.2, libass 0.17.4

KitePlayer 0.0.23

Choose a tag to compare

@yuroyami yuroyami released this 06 Sep 06:21

ASS and SSA subtitles are drawn by libass. HTTP and HTTPS links play with no setup.

Usage

/** Native views, no Compose. */
implementation("io.github.yuroyami:kiteplayer:0.0.23")

/** Compose. Everything above, plus both Compose video paths. */
implementation("io.github.yuroyami:kiteplayer-compose:0.0.23")
kiteplayer-compose
├── kiteplayer                       also kiteplayer-mobile
│   ├── kiteplayer-core
│   │   └── kiteplayer-rt            native targets only
│   ├── kiteplayer-ffmpeg            KiteFFmpeg 0.2.0
│   │   └── kiteplayer-subtitles
│   ├── kiteplayer-output
│   ├── kiteplayer-view-bindings
│   │   └── kiteplayer-view
│   ├── kiteplayer-network           HTTP and HTTPS
│   └── kiteplayer-libass            ASS and SSA
├── kiteplayer-compose-ui
│   ├── kiteplayer-compose-interop
│   └── kiteplayer-compose-video
└── kiteplayer-phone                 deprecated

Changelog

  • ASS and SSA subtitles render through libass on every platform, redrawn each video frame. Attached fonts load; SubtitleConfig.fonts adds yours. SubtitleConfig.typesetting = false keeps the old styling.
  • HTTP and HTTPS work with no setup. NetworkConfig.autoResolve = false turns that off. Per-item headers reach the transport.
  • New artifacts: kiteplayer, kiteplayer-view-bindings, kiteplayer-network, kiteplayer-libass.
  • Breaking: kiteplayer-compose-ui no longer includes the player factory or network. Use kiteplayer-compose, or add kiteplayer beside it.
  • Breaking: SubtitleConfig, PlayerSnapshot and NetworkConfig gained fields. Positional copy() calls need a recompile.
  • Breaking: AndroidPlayerViewRendererFactory.create takes a third callback, onScaleMode.
  • Web: libass is a separate module (kiteass.mjs and kiteass.wasm) in the web zip attached to the wasmJs artifact. Browsers have no system fonts; supply your own.
  • Fixed: fill and stretch on the Android view looked like fit; headers on the automatic transport (#49); credentials shown in diagnostics for a URL with no path (#115); a sleep timer replaced during its fade (#121); quadratic time on bad SRT and WebVTT durations (#120).

Dependencies

  • Kotlin 2.4.10, Compose Multiplatform 1.12.0-rc01
  • Android Gradle Plugin 9.2.1, Gradle 9.6.0, JDK 21
  • Android min SDK 26
  • KiteFFmpeg 0.2.0, with FFmpeg n8.1.2 and dav1d 1.5.4 inside
  • Ktor 3.5.2 inside kiteplayer-network, libass 0.17.4 inside kiteplayer-libass

KitePlayer 0.0.22

Choose a tag to compare

@yuroyami yuroyami released this 04 Sep 20:55

Audio gains an equaliser, balance, ReplayGain and a loudness meter. The queue is editable while it plays. Seeks are twice as fast.

Usage

/** Phones and desktop, native video view. */
implementation("io.github.yuroyami:kiteplayer-mobile:0.0.22")

/** Compose. Includes the stack above. */
implementation("io.github.yuroyami:kiteplayer-compose-ui:0.0.22")

Convenience coordinates

kiteplayer-compose-ui contains everything. Pick one of these only when you want less.

Coordinate Use it when
kiteplayer-mobile Native views, no Compose.
kiteplayer-core Engine only. You bring the decoders and the output.
kiteplayer-compose, kiteplayer-phone Never in new code. Deprecated old combined coordinates.

Every coordinate

kiteplayer-compose-ui
├── kiteplayer-compose-interop
│   └── kiteplayer-mobile
│       ├── kiteplayer-core
│       │   └── kiteplayer-rt        native targets only
│       ├── kiteplayer-ffmpeg        KiteFFmpeg 0.2.0
│       │   └── kiteplayer-subtitles
│       ├── kiteplayer-output
│       └── kiteplayer-view
└── kiteplayer-compose-video

Changelog

  • Audio: ten band equaliser, stereo balance, ReplayGain, volume up to 2.0 through a limiter, a loudness meter (LoudnessMeter, AudioAnalysis.measureLoudness), the Android audio session id.
  • Queue: edit it while it plays (addToQueue, removeFromQueue, moveInQueue, clearQueue), shuffle, chapter navigation, markers, a sleep timer with a fade, memento() and restore() for resume.
  • setVideoEnabled(false) parks video decoding without reopening. Two players in one process are tested.
  • Subtitles: a secondary track at the top, SubtitleStyleOverride with a background box, player.subtitleCues.
  • kiteplayer-ffmpeg: encode a captured frame to PNG or JPEG, Thumbnails, Waveforms, typed filter chains.
  • Android view: secure flag, picture in picture parameters, screen reader text, display rate matching. PlayerEvent.FramePresented behind PlayerConfig.frameEvents.
  • Diagnostics: KiteLog.installStructured, URIs redacted by default, five new PlaybackStats numbers.
  • Breaking: AudioConfig, PlayerConfig and PlaybackStats gained fields. Positional copy() calls need a recompile.
  • Desktop: Compose controls drawn over the native video view get no clicks on macOS. Use KiteRenderPath.ComposeCanvas, or keep controls beside the video.
  • Fixed: seeks about twice as fast; a CoreAudio zero frame request no longer replays audio; subtitle cue lookup is a binary search.

Dependencies

  • Kotlin 2.4.10, Compose Multiplatform 1.12.0-rc01
  • Android Gradle Plugin 9.2.1, Gradle 9.6.0, JDK 21
  • Android min SDK 26
  • KiteFFmpeg 0.2.0, up from 0.1.0, with FFmpeg n8.1.2 and dav1d 1.5.4 inside

KitePlayer 0.0.21

Choose a tag to compare

@yuroyami yuroyami released this 31 Aug 14:12

First public release.

Usage

/** Phones and desktop, native video view. */
implementation("io.github.yuroyami:kiteplayer-mobile:0.0.21")

/** Compose. Includes the stack above. */
implementation("io.github.yuroyami:kiteplayer-compose-ui:0.0.21")

Convenience coordinates

kiteplayer-compose-ui contains everything. Pick one of these only when you want less.

Coordinate Use it when
kiteplayer-mobile Native views, no Compose.
kiteplayer-core Engine only. You bring the decoders and the output.
kiteplayer-compose, kiteplayer-phone Never in new code. Deprecated old combined coordinates.

Every coordinate

kiteplayer-compose-ui
├── kiteplayer-compose-interop
│   └── kiteplayer-mobile
│       ├── kiteplayer-core
│       │   └── kiteplayer-rt        native targets only
│       ├── kiteplayer-ffmpeg        KiteFFmpeg 0.1.0
│       │   └── kiteplayer-subtitles
│       ├── kiteplayer-output
│       └── kiteplayer-view
└── kiteplayer-compose-video

Changelog

  • Open, play, pause, stop, seek (exact, or keyframe first and exact after), frame stepping, A-B loop, playlists with next and previous.
  • Speed 0.25x to 4x, pitch preserved or free.
  • Picture: fit, fill, stretch, brightness, contrast, saturation, hue, forced aspect, zoom, pan. All live.
  • Subtitles: SubRip, WebVTT, SubStation Alpha. External files load during playback.
  • Tracks, chapters, metadata, screenshots, renderer swap while playing, typed errors, four flows (state, progress, stats, events).
  • Hardware decoding: VideoToolbox on Apple, MediaCodec on Android, software fallback.
  • Plays on Android, iOS, macOS arm64, desktop JVM (macOS arm64 host) and Linux (no audio sink yet). Windows x64 links, never run.
  • Not yet: adaptive streaming (HLS, DASH), good audio resampling, a stable API.

Dependencies

  • Kotlin 2.4.10, Compose Multiplatform 1.12.0-rc01
  • Android Gradle Plugin 9.2.1, Gradle 9.6.0, JDK 21
  • Android min SDK 26
  • KiteFFmpeg 0.1.0, with FFmpeg n8.1.2 and dav1d 1.5.4 inside