{"id":24698792,"url":"https://github.com/kdroidfilter/composemediaplayer","last_synced_at":"2026-02-02T23:20:29.922Z","repository":{"id":272879584,"uuid":"918046791","full_name":"kdroidFilter/ComposeMediaPlayer","owner":"kdroidFilter","description":"Compose Media Player is a video player library designed for Compose Multiplatform, supporting multiple platforms including Android, macOS, Windows, Linux, iOS and Compose Web (Wasm)","archived":false,"fork":false,"pushed_at":"2025-04-06T04:52:07.000Z","size":12564,"stargazers_count":121,"open_issues_count":7,"forks_count":8,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-06T05:24:28.892Z","etag":null,"topics":["android","audio-visualization","compose-desktop","compose-ios","compose-multiplatform","customizable-ui","ios","jetpack-compose","kotlin","linux","macos","media-controls","multiplatform","open-source","video-player","windows"],"latest_commit_sha":null,"homepage":"https://kdroidfilter.github.io/ComposeMediaPlayer/","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kdroidFilter.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-17T06:29:26.000Z","updated_at":"2025-04-05T23:45:24.000Z","dependencies_parsed_at":"2025-01-17T07:29:07.682Z","dependency_job_id":"44511cfd-eadc-425e-bf50-4358fbf5ae42","html_url":"https://github.com/kdroidFilter/ComposeMediaPlayer","commit_stats":null,"previous_names":["kdroidfilter/compose-media-player","kdroidfilter/composemediaplayer"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kdroidFilter%2FComposeMediaPlayer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kdroidFilter%2FComposeMediaPlayer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kdroidFilter%2FComposeMediaPlayer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kdroidFilter%2FComposeMediaPlayer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kdroidFilter","download_url":"https://codeload.github.com/kdroidFilter/ComposeMediaPlayer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247631834,"owners_count":20970069,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","audio-visualization","compose-desktop","compose-ios","compose-multiplatform","customizable-ui","ios","jetpack-compose","kotlin","linux","macos","media-controls","multiplatform","open-source","video-player","windows"],"created_at":"2025-01-27T04:30:08.346Z","updated_at":"2026-02-02T23:20:29.915Z","avatar_url":"https://github.com/kdroidFilter.png","language":"Kotlin","readme":"# 🎥 Compose Media Player\n\n\u003cimg src=\"/assets/banner.jpg\" style=\"border-radius: 10px;\"/\u003e\n\n[![Maven Central](https://img.shields.io/maven-central/v/io.github.kdroidfilter/composemediaplayer.svg)](https://search.maven.org/artifact/io.github.kdroidfilter/composemediaplayer)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Kotlin](https://img.shields.io/badge/kotlin-multiplatform-blue.svg?logo=kotlin)](https://kotlinlang.org/docs/multiplatform.html)\n[![Platforms](https://img.shields.io/badge/platforms-Android%20|%20iOS%20|%20macOS%20JVM%20|%20Windows%20JVM%20|%20Linux%20JVM%20|%20Web-lightgrey.svg)](https://github.com/kdroidfilter/ComposeMediaPlayer)\n[![Contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/kdroidfilter/ComposeMediaPlayer/issues)\n[![Documentation](https://img.shields.io/badge/docs-Dokka-blue.svg)](https://kdroidfilter.github.io/ComposeMediaPlayer/)\n[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/kdroidfilter/ComposeMediaPlayer/publish-documentation-and-sample.yml?branch=master)](https://github.com/kdroidfilter/ComposeMediaPlayer/actions/workflows/publish-documentation-and-sample.yml)\n[![GitHub last commit](https://img.shields.io/github/last-commit/kdroidfilter/ComposeMediaPlayer)](https://github.com/kdroidfilter/ComposeMediaPlayer/commits/master)\n\n### Supported by\n[![JetBrains logo.](https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg)](https://jb.gg/OpenSource)\n\n**Compose Media Player** is a video player library designed for Compose Multiplatform, supporting multiple platforms including Android, macOS, Windows, and Linux. It is the first fully functional multiplatform video player for Compose for Desktop that requires no additional software installations. The library leverages:\n\n- **GStreamer** for Linux\n- **Media Foundation** for Windows\n- **AVPlayer** for macOS and iOS\n- **Media3** for Android\n- **HTML5 Player** for WASMJS\n\n## Table of Contents\n- [Live Demo](#-live-demo)\n- [Features](#-features)\n- [Supported Video Formats](#-supported-video-formats)\n- [Installation](#-installation)\n- [Compatibility Table](#-compatibility-table)\n- [Getting Started](#-getting-started)\n  - [Initialization](#initialization)\n  - [Displaying the Video Surface](#displaying-the-video-surface)\n    - [Content Scaling](#content-scaling)\n    - [Surface type](#surface-type)\n    - [Custom Overlay UI](#custom-overlay-ui)\n  - [Video Playback via URL or Local Files](#video-playback-via-url-or-local-files)\n  - [Full Controls](#full-controls)\n  - [Progress Indicators](#progress-indicators)\n  - [Display Left and Right Volume Levels](#display-left-and-right-volume-levels)\n  - [Error Handling](#error-handling)\n  - [Loading Indicator](#loading-indicator)\n  - [Using Subtitles](#using-subtitles)\n    - [Supported Formats](#-supported-formats)\n    - [Adding Subtitles from URL or Local File](#-adding-subtitles-from-url-or-local-file)\n    - [Customizing Subtitle Appearance](#-customizing-subtitle-appearance)\n    - [Disabling Subtitles](#-disabling-subtitles)\n  - [Fullscreen Mode](#️-fullscreen-mode)\n- [Metadata Support](#-metadata-support)\n  - [Example Usage](#example-usage)\n  - [Basic Example](#-basic-example)\n- [License](#-license)\n- [Roadmap](#-roadmap)\n- [Applications Using This Library](#-applications-using-this-library)\n- [Star History](#-star-history)\n\n## 🚀 Live Demo\n\nTry the online demo here : [🎥 Live Demo](https://kdroidfilter.github.io/ComposeMediaPlayer/sample/)\n\n## ✨ Features\n\n- **Multiplatform Support**: Works seamlessly on Android, macOS, Windows, Linux and Compose Web (Wasm).\n- **File and URL Support**: Play videos from local files or directly from URLs.\n- **Media Controls**: Includes play, pause, loop toggle, volume control, playback speed, loop playback and timeline slider.\n- **Initial Playback Control**: Choose whether videos automatically play or remain paused after opening.\n- **Custom Video Player UI**: Fully customizable using Compose Multiplatform, with support for custom overlays that display even in fullscreen mode.\n- **Audio Levels**: Displays left and right audio levels in real time.\n- **Fullscreen Mode**: Toggle between windowed and fullscreen playback modes.\n- **Error handling** Simple error handling for network or playback issues.\n\n## ✨ Supported Video Formats\n| Format | Windows                                                                                                           | Linux  | macOS \u0026 iOS                                                       | Android | WasmJS |\n|--------|-------------------------------------------------------------------------------------------------------------------|-------------------|-----------------------------------------------------------------------------|-----------------|-------------------|\n| **Player** | [MediaFoundation](https://learn.microsoft.com/en-us/windows/win32/medfound/microsoft-media-foundation-sdk) | [GStreamer](https://gstreamer.freedesktop.org/) | [AVPlayer](https://developer.apple.com/documentation/avfoundation/avplayer) | [Media 3](https://developer.android.com/media/media3) | [HTML5 Video](https://www.w3schools.com/html/html5_video.asp) |\n| MP4 (H.264) | ✅                                                                                                                 | ✅ | ✅                                                                           | ✅ | ✅ |\n| AVI | ❌                                                                                                                 | ✅ | ❌                                                                           | ❌ | ❌ |\n| MKV | ❌                                                                                                                 | ✅ | ❌                                                                           | ✅ | ❌ |\n| MOV | ✅                                                                                                                 | ✅ | ✅                                                                           | ❌ | ✅ |\n| FLV | ❌                                                                                                                 | ✅ | ❌                                                                           | ❌ | ❌ |\n| WEBM | ❌                                                                                                                 | ✅ | ❌                                                                           | ✅ | ✅ |\n| WMV | ✅                                                                                                                 | ✅ | ❌                                                                           | ❌ | ❌ |\n| 3GP | ✅                                                                                                                 | ✅ | ✅                                                                           | ✅ | ❌ |\n\n\n## 🔧 Installation\n\nTo add Compose Media Player to your project, include the following dependency in your `build.gradle.kts` file:\n\n```kotlin\ndependencies {\n    implementation(\"io.github.kdroidfilter:composemediaplayer:\u003cversion\u003e\")\n}\n```\n\n## 📊 Compatibility Table\n\n| Library Version | Kotlin Version | Compose Version |\n|-----------------|----------------|-----------------|\n| 0.8.6           | 2.3.0          | 1.9.3           |\n| 0.8.3           | 2.2.20         | 1.9.0           |\n| 0.7.11          | 2.2.0          | 1.8.2           |\n| 0.7.10          | 2.1.21         | 1.8.2           |\n\n## 🚀 Getting Started\n\n### Initialization\n\nBefore using Compose Media Player, you need to create a state for the video player using the `rememberVideoPlayerState` function:\n\n```kotlin\nval playerState = rememberVideoPlayerState()\n```\n\n### Displaying the Video Surface\n\nAfter initializing the player state, you can display the surface of the video using `VideoPlayerSurface`:\n\n```kotlin\n// Video Surface\nBox(\n    modifier = Modifier.weight(1f).fillMaxWidth(),\n    contentAlignment = Alignment.Center\n) {\n    VideoPlayerSurface(\n        playerState = playerState,\n        modifier = Modifier.fillMaxSize()\n    )\n}\n```\n\n#### Content Scaling\n\n\u003e [!WARNING]\n\u003e Content scaling support is experimental. The behavior may vary across different platforms.\n\nYou can control how the video content is scaled inside the surface using the `contentScale` parameter:\n\n```kotlin\nVideoPlayerSurface(\n    playerState = playerState,\n    modifier = Modifier.fillMaxSize(),\n    contentScale = ContentScale.Crop // Default is ContentScale.Fit\n)\n```\n\nAvailable content scale options:\n- `ContentScale.Fit` (default): Scales the video to fit within the surface while maintaining aspect ratio\n- `ContentScale.Crop`: Scales the video to fill the surface while maintaining aspect ratio, potentially cropping parts\n- `ContentScale.FillBounds`: Stretches the video to fill the surface, may distort the aspect ratio\n- `ContentScale.Inside`: Similar to Fit, but won't scale up if the video is smaller than the surface\n- `ContentScale.None`: No scaling applied\n\n#### Surface type\n\n\u003e [!WARNING]\n\u003e Surface type parameter is supported only for Android target.\n\nAvailable surface type options:\n- `SurfaceType.SurfaceView`: uses SurfaceView for the player view, which is more performant for video playback but has limitations in terms of composability and animations.\n- `SurfaceType.TextureView` (default): uses TextureView for the player view, which allows for more complex composable layouts and animations.\n\n```kotlin\nVideoPlayerSurface(\n    playerState = playerState,\n    modifier = Modifier.fillMaxSize(),\n    surfaceType = SurfaceType.SurfaceView // Default is SurfaceType.TextureView\n)\n```\n\n#### Custom Overlay UI\n\nYou can add a custom overlay UI that will always be visible, even in fullscreen mode, by using the `overlay` parameter:\n\n```kotlin\nVideoPlayerSurface(\n    playerState = playerState,\n    modifier = Modifier.fillMaxSize()) {\n        // This overlay will always be visible\n        Box(modifier = Modifier.fillMaxSize()) {\n            // You can customize the UI based on fullscreen state\n            if (playerState.isFullscreen) {\n                // Fullscreen UI\n                IconButton(\n                    onClick = { playerState.toggleFullscreen() },\n                    modifier = Modifier.align(Alignment.TopEnd).padding(16.dp)\n                ) {\n                    Icon(\n                        imageVector = Icons.Default.FullscreenExit,\n                        contentDescription = \"Exit Fullscreen\",\n                        tint = Color.White\n                    )\n                }\n            } else {\n                // Regular UI\n                Row(\n                    modifier = Modifier\n                        .align(Alignment.BottomCenter)\n                        .fillMaxWidth()\n                        .background(Color.Black.copy(alpha = 0.5f))\n                        .padding(8.dp),\n                    horizontalArrangement = Arrangement.SpaceBetween\n                ) {\n                    // Your custom controls here\n                    IconButton(onClick = { \n                        if (playerState.isPlaying) playerState.pause() else playerState.play() \n                    }) {\n                        Icon(\n                            imageVector = if (playerState.isPlaying) \n                                Icons.Default.Pause else Icons.Default.PlayArrow,\n                            contentDescription = \"Play/Pause\",\n                            tint = Color.White\n                        )\n                    }\n                }\n            }\n        }\n    }\n```\n\n### Video Playback via URL or Local Files\n\nYou can play a video by providing a direct URL:\n\n```kotlin\n// Open a video and automatically start playing (default behavior)\nplayerState.openUri(\"http://example.com/video.mp4\")\n\n// Open a video but keep it paused initially\nplayerState.openUri(\"http://example.com/video.mp4\", InitialPlayerState.PAUSE)\n```\n\nTo play a local video file you can use [PlatformFile](https://filekit.mintlify.app/core/platform-file) from [FileKit](https://github.com/vinceglb/FileKit).\n\n```kotlin\nval file = FileKit.openFilePicker(type = FileKitType.Video)\n\n// Open a file and automatically start playing (default behavior)\nfile?.let { playerState.openFile(it) }\n\n// Open a file but keep it paused initially\nfile?.let { playerState.openFile(it, InitialPlayerState.PAUSE) }\n```\n\nThe `initializeplayerState` parameter controls whether the video automatically starts playing after opening:\n- `InitialPlayerState.PLAY` (default): The video will automatically start playing after opening\n- `InitialPlayerState.PAUSE`: The video will be loaded but remain paused until you call `play()`\n\nCheck the [sample project](sample/composeApp/src/commonMain/kotlin/sample/app/App.kt) for a complete example.\n\n### Full Controls\n\n- **Play and Pause**:\n\nYou can detect the current playback state via `playerState.isPlaying` and configure a Play/Pause button as follows:\n\n```kotlin\nButton(onClick = {\n    if (playerState.isPlaying) {\n        playerState.pause()\n        println(\"Playback paused\")\n    } else {\n        playerState.play()\n        println(\"Playback started\")\n    }\n}) {\n    Text(if (playerState.isPlaying) \"Pause\" else \"Play\")\n}\n```\n\n- **Stop**:\n\n```kotlin\nplayerState.stop()\nprintln(\"Playback stopped\")\n```\n\n- **Volume**:\n\n```kotlin\nplayerState.volume = 0.5f // Set volume to 50%\nprintln(\"Volume set to 50%\")\n```\n\n- **Loop Playback**:\n\n```kotlin\nplayerState.loop = true // Enable loop playback\nprintln(\"Loop playback enabled\")\n```\n\n- **Playback Speed**:\n\n```kotlin\nplayerState.playbackSpeed = 1.5f // Set playback speed to 1.5x\nprintln(\"Playback speed set to 1.5x\")\n```\n\nYou can adjust the playback speed between 0.5x (slower) and 2.0x (faster). The default value is 1.0x (normal speed).\n\n### Progress Indicators\n\nTo display and control playback progress:\n\n```kotlin\nSlider(\n    value = playerState.sliderPos,\n    onValueChange = {\n        playerState.sliderPos = it\n        playerState.userDragging = true\n        println(\"Position changed: $it\")\n    },\n    onValueChangeFinished = {\n        playerState.userDragging = false\n        playerState.seekTo(playerState.sliderPos)\n        println(\"Position finalized: ${playerState.sliderPos}\")\n    },\n    valueRange = 0f..1000f\n)\n```\n\n### Display Left and Right Volume Levels\n\nTo display audio levels:\n\n```kotlin\nprintln(\"Left level: ${playerState.leftLevel.toInt()}%, Right level: ${playerState.rightLevel.toInt()}%\")\n```\n\n\u003e [!IMPORTANT]\n\u003e This feature is not working on iOS.\n\n\n### Error Handling\n\nIn case of an error, you can display it using `println`:\n\n```kotlin\nplayerState.error?.let { error -\u003e\n    println(\"Error detected: ${error.message}\")\n    playerState.clearError()\n}\n```\n\n### Loading Indicator\n\nTo detect if the video is buffering:\n\n```kotlin \nif (playerState.isLoading) {\n    CircularProgressIndicator()\n}\n````\n\n### Using Subtitles\n\nCompose Media Player supports adding subtitles from both URLs and local files. Subtitles are now rendered using Compose, providing a uniform appearance across all platforms.\n\n#### 🎯 Supported Formats\n\nThe player supports both SRT and VTT subtitle formats with automatic format detection.\n\n#### 🎯 Adding Subtitles from URL or Local File\n\nYou can add subtitles by specifying a URL:\n\n```kotlin\nval track = SubtitleTrack(\n    label = \"English Subtitles\",\n    language = \"en\",\n    src = \"https://example.com/subtitles.vtt\" // Works with both .srt and .vtt files\n)\nplayerState.selectSubtitleTrack(track)\n```\n\n#### 🎨 Customizing Subtitle Appearance\n\nYou can customize the appearance of subtitles using the following properties:\n\n```kotlin\n// Customize subtitle text style\nplayerState.subtitleTextStyle = TextStyle(\n    color = Color.White,\n    fontSize = 20.sp,\n    fontWeight = FontWeight.Bold,\n    textAlign = TextAlign.Center\n)\n\n// Customize subtitle background color\nplayerState.subtitleBackgroundColor = Color.Black.copy(alpha = 0.7f)\n```\n\n#### ❌ Disabling Subtitles\n\nTo disable subtitles:\n\n```kotlin\nplayerState.disableSubtitles()\n```\n\n### 🖥️ Fullscreen Mode\n\n\u003e [!WARNING]\n\u003e Fullscreen support is experimental. The behavior may vary across different platforms.\n\nYou can toggle between windowed and fullscreen modes using the `toggleFullscreen()` method:\n\n```kotlin\n// Toggle fullscreen mode\nplayerState.toggleFullscreen()\n\n// Check current fullscreen state\nif (playerState.isFullscreen) {\n    println(\"Player is in fullscreen mode\")\n} else {\n    println(\"Player is in windowed mode\")\n}\n```\n\nThe player doesn't display any UI by default in fullscreen mode - you need to create your own custom UI using the `overlay` parameter of `VideoPlayerSurface`. The overlay will be displayed even in fullscreen mode, and you can customize it based on the fullscreen state:\n\n```kotlin\nVideoPlayerSurface(\n    playerState = playerState,\n    modifier = Modifier.fillMaxSize(),\n    overlay = {\n        Box(modifier = Modifier.fillMaxSize()) {\n            // Customize UI based on fullscreen state\n            if (playerState.isFullscreen) {\n                // Fullscreen UI\n                // ...\n            } else {\n                // Regular UI\n                // ...\n            }\n        }\n    }\n)\n```\n\nSee the \"Custom Overlay UI\" section under \"Displaying the Video Surface\" for a complete example.\n\n## 🔍 Metadata Support\n\n\u003e [!WARNING]\n\u003e Metadata support is experimental. There may be inconsistencies between platforms, and on WASM it's currently limited to width and height only.\n\nThe player can extract the following metadata:\n- Title\n- Duration (in milliseconds)\n- Video resolution (width and height)\n- Bitrate (in bits per second)\n- Frame rate\n- MIME type\n- Audio channels\n- Audio sample rate\n\n### Example Usage\n\nYou can access video metadata through the `metadata` property of the player state:\n\n```kotlin\n// Access metadata after loading a video\nplayerState.openUri(\"http://example.com/video.mp4\") // Auto-plays by default\n// Or load without auto-playing:\n// playerState.openUri(\"http://example.com/video.mp4\", InitialPlayerState.PAUSE)\n\n// Display metadata information\nval metadata = playerState.metadata\n\nprintln(\"Video Metadata:\")\nmetadata.title?.let { println(\"Title: $it\") }\nmetadata.duration?.let { println(\"Duration: ${it}ms\") }\nmetadata.width?.let { width -\u003e\n    metadata.height?.let { height -\u003e\n        println(\"Resolution: ${width}x${height}\")\n    }\n}\nmetadata.bitrate?.let { println(\"Bitrate: ${it}bps\") }\nmetadata.frameRate?.let { println(\"Frame Rate: ${it}fps\") }\nmetadata.mimeType?.let { println(\"MIME Type: $it\") }\nmetadata.audioChannels?.let { println(\"Audio Channels: $it\") }\nmetadata.audioSampleRate?.let { println(\"Audio Sample Rate: ${it}Hz\") }\n\n```\n\n\n### 📋 Basic Example\n\nHere is a minimal example of how to integrate the Compose Media Player into your Compose application with a hardcoded URL:\n\n```kotlin\n@Composable\nfun App() {\n    val playerState = rememberVideoPlayerState()\n\n    MaterialTheme {\n        Column(modifier = Modifier.fillMaxSize().padding(8.dp)) {\n\n            // Video Surface\n            Box(\n                modifier = Modifier.weight(1f).fillMaxWidth(),\n                contentAlignment = Alignment.Center\n            ) {\n                VideoPlayerSurface(\n                    playerState = playerState,\n                    modifier = Modifier.fillMaxSize()\n                )\n            }\n\n            Spacer(modifier = Modifier.height(8.dp))\n\n            // Playback Controls\n            Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {\n                Button(onClick = { playerState.play() }) { Text(\"Play\") }\n                Button(onClick = { playerState.pause() }) { Text(\"Pause\") }\n            }\n\n            Spacer(modifier = Modifier.height(8.dp))\n\n            // Open Video URL buttons\n            Row(\n                horizontalArrangement = Arrangement.SpaceBetween,\n                modifier = Modifier.fillMaxWidth()\n            ) {\n                Button(\n                    onClick = {\n                        val url = \"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4\"\n                        playerState.openUri(url) // Default: auto-play\n                    }\n                ) {\n                    Text(\"Play Video\")\n                }\n                \n                Button(\n                    onClick = {\n                        val url = \"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4\"\n                        playerState.openUri(url, InitialPlayerState.PAUSE) // Open paused\n                    }\n                ) {\n                    Text(\"Load Video Paused\")\n                }\n            }\n\n            Spacer(modifier = Modifier.height(8.dp))\n\n            // Volume Control\n            Text(\"Volume: ${(playerState.volume * 100).toInt()}%\")\n            Slider(\n                value = playerState.volume,\n                onValueChange = { playerState.volume = it },\n                valueRange = 0f..1f\n            )\n        }\n    }\n}\n```\n\n## 📄 License\n\nCompose Media Player is licensed under the MIT License. See [LICENSE](LICENSE) for details.\n\n## 📊 Roadmap\n\n- **Audio Player**: Introduce a standalone audio player for handling audio-only content.\n- **Player with Separate Audio and Video Streams**: Add functionality to support different audio and video streams for advanced playback scenarios.\n\n## 🚀 Applications Using This Library\n\n- [Pushscroll](https://pushscroll.com) - Pushscroll: Screen-Time Gym\n- [Pixelix](https://github.com/ghostbyte-dev/pixelix) - Pixelfed client for Android and iOS\n\nIf you're using this library in your project, please let us know and we'll add it to this list!\n\n## ⭐ Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=kdroidfilter/ComposeMediaPlayer\u0026type=Date)](https://www.star-history.com/#kdroidfilter/ComposeMediaPlayer\u0026Date)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkdroidfilter%2Fcomposemediaplayer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkdroidfilter%2Fcomposemediaplayer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkdroidfilter%2Fcomposemediaplayer/lists"}