SkillAgentSearch skills...

Klarity

A media (video and audio) player for Compose Multiplatform (desktop-only), built on top of the native FFMpeg and PortAudio libraries, and rendered using the Skiko library

Install / Use

/learn @numq/Klarity

README

<div align="center" style="display: flex; justify-content: center;"> <img src="media/logo.png" alt="logo" height="128px"/> <h1>Klarity</h1> </div>

Klarity is a media (video and audio) player for Compose Multiplatform (desktop-only), built on top of the native FFMpeg and PortAudio libraries, and rendered using the Skiko library.

Since frames are rendered directly into the Composable, this eliminates the need for compatibility components like SwingPanel, making it possible to display any Composable as an overlay on top of a frame.

<div align="center"> <img src="media/preview.png" alt="preview"/> </div>

Table of Content

Changelog

1.1.0

Changed

  • Rendering pipeline optimization
  • Rendering computation optimization
  • Rendering operations synchronization optimization

<details> <summary>📦 Previous versions</summary>

1.0.6

Fixed

  • Video-only media playback synchronization

1.0.5

[!WARNING]
Video-only media playback synchronization doesn't work

Changed

  • Code refactoring
  • Performance optimizations

Fixed

  • Bug fixes and stability improvements

1.0.4

Changed

  • Renderer no longer depends on video format - uses width and height instead

1.0.3

Fixed

  • Fixed incorrect argument names

Changed

  • Enhanced seeking precision
  • Extended external state machine
  • Changed rendering behavior - renders first video frame during: preparation, playback stop, seeking
  • Performance and stability enhancements

1.0.2

Fixed

  • Fixed delayed external state updates after command execution
  • Fixed incorrect first frame display after seeking
  • Fixed event handling issues
  • Fixed improper loop stopping
  • Fixed buffer cleanup errors during channel closure

1.0.1

Changed

  • Improved internal state machine
  • Improved playback synchronization
  • Improved seeking

1.0.0

  • Stable release
</details>

Supported platforms

The library provides pre-built JARs for the following platforms:

| Platform | Architecture | JAR | |----------|--------------|-----------------------------| | Windows | x64 | klarity-windows-x64-*.jar | | Linux | x64 | klarity-linux-x64-*.jar | | macOS | x64 | klarity-macos-x64-*.jar | | macOS | arm64 | klarity-macos-arm64-*.jar |

Custom builds

If you need support for other platforms or architectures, you can build the library from source using the CI/CD configuration as a reference for the complete build process.

Features

  • Media files probing
  • Audio and video playback of media files
  • Slow down and speed up playback speed without changing pitch
  • Getting a preview of a media file
  • Getting frames (snapshots) of a media file
  • Coroutine/Flow API

Roadmap

Hardware-Accelerated Rendering

While hardware-accelerated decoding is technically available through FFmpeg, its practical application is currently limited:

  • Rendering bottleneck: Decoded frames are processed through CPU-bound Skia components

  • Latency issues: This creates a pipeline bottleneck that negates the benefits of hardware decoding

  • Architectural constraints: DirectX 12 and OpenGL implementations would require compatibility components, eliminating key advantages of the current architecture

Future solution:

  • Implement Vulkan-based rendering when stable support becomes available in Skia, provided it maintains the current seamless Compose integration without compatibility layers.

Architecture

Klarity implements an event-driven architecture designed for Kotlin developers. It focuses on simplicity and easy integration with minimal setup.

Layers

  • JVM Layer (Kotlin):

    • Contains all business logic and state management

    • Provides a modern, coroutine-based public API

    • Uses Kotlin Flows for event-driven communication

    • Manages playback control, seeking, and synchronization

  • JNI Layer::

    • Bridges Kotlin code with native C++ performance

    • Handles efficient data marshaling between layers

    • Minimizes overhead for data transfer

  • Native Layer (C++):

    • Uses FFmpeg for video/audio decoding

    • Employs PortAudio for low-latency audio playback

    • Handles audio playback including polyphonic audio time-stretching

Rendering

The pipeline combines FFmpeg and Skia to decode video frames directly into native memory. The decoded frame data is directly interpreted as a Pixmap via pointer reference, then written to a Skia Surface and rendered to a Compose Canvas.

This efficient approach eliminates compatibility layers like SwingPanel and enables seamless overlaying of any Composable on top of video content.

Dependency graph

graph TD
    KlarityPlayer --> PlayerController
    PlayerController --> Pipeline
    PlayerController --> BufferLoop
    PlayerController --> PlaybackLoop
    PlayerController --> Settings
    PlayerController --> PlayerState
    PlayerController --> BufferTimestamp
    PlayerController --> PlaybackTimestamp
    PlayerController --> Events
    PlayerController --> Renderer
    
    BufferLoop --> Pipeline
    PlaybackLoop --> BufferLoop
    PlaybackLoop --> Pipeline
    PlaybackLoop --> Renderer
    PlaybackLoop --> Settings
    
    subgraph Media Pipeline
        Pipeline --> Media
        Pipeline --> AudioPipeline
        Pipeline --> VideoPipeline
        
        AudioPipeline --> AudioDecoder
        AudioPipeline --> AudioBuffer
        AudioPipeline --> Sampler
        
        VideoPipeline --> VideoDecoder
        VideoPipeline --> VideoBuffer
        VideoPipeline --> VideoPool
    end
    
    subgraph Native Components
        Sampler --> NativeSampler[C++/JNI]
        AudioDecoder --> NativeDecoder[C++/JNI]
        VideoDecoder --> NativeDecoder[C++/JNI]
    end
    
    subgraph Loops
        BufferLoop --> BufferHandler
        PlaybackLoop --> PlaybackHandler
    end
    
    subgraph Media
        Media --> AudioFormat
        Media --> VideoFormat
    end

State diagram

stateDiagram-v2
    state PlayerState {
        [*] --> Empty
        Empty --> Preparing: Prepare
        Preparing --> Ready: Success
        Preparing --> Error: Error
        Preparing --> Empty: Release
        
        state Ready {
            [*] --> Stopped
            Stopped --> Playing: Play
            Playing --> Paused: Pause
            Playing --> Stopped: Stop
            Playing --> Seeking: SeekTo
            Playing --> Error: Error
            Paused --> Playing: Resume
            Paused --> Stopped: Stop
            Paused --> Seeking: SeekTo
            Paused --> Error: Error
            Stopped --> Completed: Playback Complete
            Stopped --> Seeking: SeekTo
            Stopped --> Error: Error
            Completed --> Stopped: Stop
            Completed --> Seeking: SeekTo
            Completed --> Error: Error
            Seeking --> Paused: Seek Complete
            Seeking --> Stopped: Stop
            Seeking --> Seeking: SeekTo
            Seeking --> Error: Error
        }
        
        Ready --> Releasing: Release
        Releasing --> Empty: Success
        Releasing --> Error: Error
        Error --> Empty: Reset
    }

Transition table

| Current State \ Action | Empty | Preparing | Releasing | Ready.Stopped | Ready.Playing | Ready.Paused | Ready.Completed | Ready.Seeking | Error | |------------------------|---------|-----------|-----------|---------------|---------------|---------------|-------------------|---------------|-------| | Empty | - | Prepare | - | - | - | - | - | - | - | | Preparing | Release | - | - | Success | - | - | - | - | Error | | Releasing | Success | - | - | - | - | - | - | - | Error | | Error | Reset | - | - | - | - | - | - | - | - | | Ready.Stopped | - | - | Release | - | Play | - | Playback Complete | SeekTo | Error | | Ready.Playing | - | - | Release | Stop | - | Pause | - | SeekTo | Error | | Ready.Paused | - | - | Release | Stop | Resume | - | - | SeekTo | Error | | Ready.Completed | - | - | Release | Stop | - | - | - | SeekTo | Error | | Ready.Seeking | - | - | Release | Stop | - | Seek Complete | - | SeekTo | Error |

Installation

Download the [latest release](https://github.com/numq/Klarity/

Related Skills

View on GitHub
GitHub Stars67
CategoryContent
Updated7d ago
Forks5

Languages

Kotlin

Security Score

100/100

Audited on Mar 23, 2026

No findings