
Automates library release workflow: converts README into a Docsify homepage, publishes API docs, deploys a live browser demo, builds downloadable sample executables, and wires complete CI/CD.
cmp-videoplayer is an OSS Compose Multiplatform video player component that focuses on one responsibility: playing video files across targets.
Supported targets:
<video>)Non-goals:
placeholder slot)Add the dependency to your commonMain:
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.aryapreetam:cmp-videoplayer:<version>")
}
}
}@Composable
fun MyScreen() {
VideoPlayer(
source = VideoSource.Url("https://example.com/video.mp4"),
config = VideoPlayerConfig(
autoplay = false,
showControls = true,
)
)
}VideoSource.Url(url) supports http(s)://, file://, and on Android also content:// and android.resource://.VideoSource.Path(path) is a raw filesystem path (Android/iOS/JVM). On wasm, use Url.On wasmJs, the HTML <video> element needs a URL. If your video is only available via Compose resources (Res.raw.*), use rememberBlobVideoUrl:
@Composable
fun ResourceVideo(bytes: ByteArray) {
// `mimeType` is explicit by design.
val url = rememberBlobVideoUrl(bytes, mimeType = "video/mp4")
VideoPlayer(VideoSource.Url(url))
}Notes:
blob: URLs are revoked on disposal.The library uses platform interop for real playback. For UI tests, you can force a pure-Compose render path:
CompositionLocalProvider(
LocalVideoPlayerConfig provides VideoPlayerConfig(renderMode = RenderMode.PlaceholderOnly)
) {
VideoPlayer(
source = VideoSource.Url("https://example.com/video.mp4"),
placeholder = { /* render your test-friendly placeholder UI */ }
)
}The root node uses the test tag cmp-videoplayer:VideoPlayer.
If using snapshots from Maven Local, ensure:
repositories {
mavenLocal()
mavenCentral()
}Download and try the sample app on your platform without building from source:
| Platform | Download Link |
|---|---|
| 🍏 macOS (Intel) | |
| 🍎 macOS (Apple Silicon) | |
| 🪟 Windows | |
| 🐧 Linux | |
| 🤖 Android | |
| 🌐 Web (Wasm) | |
| iOS Simulator |
Option 1: Drag and Drop
Option 2: ADB Install
adb install sample-app-android-unsigned.apksample-app-wasm.zip
index.html in a web browserNote: You can also try the live demo without downloading: Try Live Demo
sample-app-ios-simulator.zip from the latest release
sample-app-ios-simulator.app
.app onto the Simulator window OR run:
xcrun simctl install booted /path/to/sample-app-ios-simulator.appDownload the DMG for your Mac architecture (Intel or Apple Silicon)
Open (mount) the DMG and drag the app to your Applications folder (or Desktop)
When you try to open the app for the first time, macOS Gatekeeper will block it since it is an open-source build signed ad-hoc (not using a paid Apple Developer account). Follow these 6 sequential steps to allow running the app:
1. Block Alert Dialog
|
2. Open System Settings
|
3. Privacy & Security Section
|
4. Click "Open Anyway"
|
5. Authenticate Security Dialog
|
6. Click "Open" to Launch
|
To allow running the app:
This is a normal security step for all open-source and CI-generated Mac executables. Apps are signed ad-hoc for internal/dev use, not with a public Apple developer ID.
Tip: Unsure about your Mac's type? Click the Apple logo → "About This Mac". If it says Intel, download x64; if it says M1, M2, or M3, download arm64.
.deb filesudo dpkg -i sample-app-linux.debsample in the terminal!This library automatically deploys three key resources:
All three are automatically deployed to GitHub Pages:
https://<username>.github.io/<library-name>/
https://<username>.github.io/<library-name>/api/
https://<username>.github.io/<library-name>/demo/
You can also run Gradle tasks in the terminal:
./gradlew run to run application./gradlew package to store native distribution into build/compose/binaries
./gradlew :sample:composeApp:run
sample/iosApp/iosApp.xcodeproj in Xcode and run the sample app./gradlew :sample:composeApp:wasmJsBrowserRun
This repo ships with an opinionated CI/CD that builds, tests, packages, releases, and deploys docs & demo automatically on tags.
flowchart TD
A["Lint"] --> B["Build & Test - Library + Sample (all targets)"]
B --> C["Android UI tests (emulator) & Maestro E2E tests(iOS & Android)"]
C --> D["Build artifacts - APK • DMG (Intel/Apple Silicon) • MSI • DEB • iOS Simulator zip • wasm bundle"]
D --> E["Create GitHub Release and upload artifacts"]
E --> F["Publish to Maven Central"]
E --> G["Deploy GitHub Pages README site (Docsify) + wasm demo + API docs"]Key points:
v*) and manual runs../gradlew :cmp-videoplayer:publishToMavenLocal
~/.m2/repository/cmp-videoplayer/
Follow https://www.jetbrains.com/help/kotlin-multiplatform-dev/multiplatform-publish-libraries.html & complete all necessary steps.
The above article focuses on publishing to MavenCentral. But if you want to verify publishing from your local machine, you can follow below steps:
~/.gradle/gradle.properties(not to be confused with gradle.properties in project root):
signing.keyId=XXXXXXXX
signing.password=[key password]
signing.secretKeyRingFile=../XXXXXXXX.gpg
mavenCentralUsername=[generated username]
mavenCentralPassword=[generated password]
For GPG_KEY_CONTENTS secret(signing.secretKeyRingFile above), can get plain text version of gpg key using below commands.
# This will print the private GPG key in plain text.
gpg --export-secret-keys --armor <key id>
# this will copy it for pasting in github actions secrets.
gpg --export-secret-keys --armor <key id> | pbcopy
./gradlew :cmp-videoplayer:publishAndReleaseToMavenCentral --no-configuration-cache
Now check the deployments here https://central.sonatype.com/publishing/deployments
MIT License © 2025 aryapreetam and contributors. See LICENSE for details.
This template was built with inspiration and learnings from the excellent work of the Kotlin multiplatform community:
Project Setup: Initial project structure was created using Kotlin Multiplatform Web Wizard by terrakok
Inspirations:
Special thanks to:
This section lists planned improvements and features for the template. Contributions are welcome!
[ ] Add Detekt - Static code analysis for Kotlin
[ ] Add ktlint - Kotlin code formatter
[ ] Add Kover - Code coverage reporting
[ ] Add Dependabot - Automated dependency updates
[ ] Screenshot Testing - Visual regression testing
[ ] Performance Benchmarking - Track performance metrics
[ ] Multi-Module Support Guide
[ ] Compose Resources Guide
[ ] Video Tutorial
[ ] Blog Post / Article
[ ] Automated Changelog Generation
[ ] Version Bump Automation
[ ] Automated Screenshots
[ ] Linux Desktop Packaging
[ ] Additional Apple Platforms
[ ] Desktop Linux Native Build
[ ] Custom Domain Support
[ ] Improved Docsify Theme
[ ] Search Functionality
[ ] Vulnerability Scanning
[ ] SBOM Generation
[ ] Signed Releases
[ ] JitPack Support
[ ] NPM Package for Wasm
[ ] CocoaPods Support
If you have suggestions for improvements or want to contribute:
Priority: Items marked with 🔥 are high priority and would have the most impact.
See CONTRIBUTING.md for detailed contribution guidelines.
cmp-videoplayer is an OSS Compose Multiplatform video player component that focuses on one responsibility: playing video files across targets.
Supported targets:
<video>)Non-goals:
placeholder slot)Add the dependency to your commonMain:
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.aryapreetam:cmp-videoplayer:<version>")
}
}
}@Composable
fun MyScreen() {
VideoPlayer(
source = VideoSource.Url("https://example.com/video.mp4"),
config = VideoPlayerConfig(
autoplay = false,
showControls = true,
)
)
}VideoSource.Url(url) supports http(s)://, file://, and on Android also content:// and android.resource://.VideoSource.Path(path) is a raw filesystem path (Android/iOS/JVM). On wasm, use Url.On wasmJs, the HTML <video> element needs a URL. If your video is only available via Compose resources (Res.raw.*), use rememberBlobVideoUrl:
@Composable
fun ResourceVideo(bytes: ByteArray) {
// `mimeType` is explicit by design.
val url = rememberBlobVideoUrl(bytes, mimeType = "video/mp4")
VideoPlayer(VideoSource.Url(url))
}Notes:
blob: URLs are revoked on disposal.The library uses platform interop for real playback. For UI tests, you can force a pure-Compose render path:
CompositionLocalProvider(
LocalVideoPlayerConfig provides VideoPlayerConfig(renderMode = RenderMode.PlaceholderOnly)
) {
VideoPlayer(
source = VideoSource.Url("https://example.com/video.mp4"),
placeholder = { /* render your test-friendly placeholder UI */ }
)
}The root node uses the test tag cmp-videoplayer:VideoPlayer.
If using snapshots from Maven Local, ensure:
repositories {
mavenLocal()
mavenCentral()
}Download and try the sample app on your platform without building from source:
| Platform | Download Link |
|---|---|
| 🍏 macOS (Intel) | |
| 🍎 macOS (Apple Silicon) | |
| 🪟 Windows | |
| 🐧 Linux | |
| 🤖 Android | |
| 🌐 Web (Wasm) | |
| iOS Simulator |
Option 1: Drag and Drop
Option 2: ADB Install
adb install sample-app-android-unsigned.apksample-app-wasm.zip
index.html in a web browserNote: You can also try the live demo without downloading: Try Live Demo
sample-app-ios-simulator.zip from the latest release
sample-app-ios-simulator.app
.app onto the Simulator window OR run:
xcrun simctl install booted /path/to/sample-app-ios-simulator.appDownload the DMG for your Mac architecture (Intel or Apple Silicon)
Open (mount) the DMG and drag the app to your Applications folder (or Desktop)
When you try to open the app for the first time, macOS Gatekeeper will block it since it is an open-source build signed ad-hoc (not using a paid Apple Developer account). Follow these 6 sequential steps to allow running the app:
1. Block Alert Dialog
|
2. Open System Settings
|
3. Privacy & Security Section
|
4. Click "Open Anyway"
|
5. Authenticate Security Dialog
|
6. Click "Open" to Launch
|
To allow running the app:
This is a normal security step for all open-source and CI-generated Mac executables. Apps are signed ad-hoc for internal/dev use, not with a public Apple developer ID.
Tip: Unsure about your Mac's type? Click the Apple logo → "About This Mac". If it says Intel, download x64; if it says M1, M2, or M3, download arm64.
.deb filesudo dpkg -i sample-app-linux.debsample in the terminal!This library automatically deploys three key resources:
All three are automatically deployed to GitHub Pages:
https://<username>.github.io/<library-name>/
https://<username>.github.io/<library-name>/api/
https://<username>.github.io/<library-name>/demo/
You can also run Gradle tasks in the terminal:
./gradlew run to run application./gradlew package to store native distribution into build/compose/binaries
./gradlew :sample:composeApp:run
sample/iosApp/iosApp.xcodeproj in Xcode and run the sample app./gradlew :sample:composeApp:wasmJsBrowserRun
This repo ships with an opinionated CI/CD that builds, tests, packages, releases, and deploys docs & demo automatically on tags.
flowchart TD
A["Lint"] --> B["Build & Test - Library + Sample (all targets)"]
B --> C["Android UI tests (emulator) & Maestro E2E tests(iOS & Android)"]
C --> D["Build artifacts - APK • DMG (Intel/Apple Silicon) • MSI • DEB • iOS Simulator zip • wasm bundle"]
D --> E["Create GitHub Release and upload artifacts"]
E --> F["Publish to Maven Central"]
E --> G["Deploy GitHub Pages README site (Docsify) + wasm demo + API docs"]Key points:
v*) and manual runs../gradlew :cmp-videoplayer:publishToMavenLocal
~/.m2/repository/cmp-videoplayer/
Follow https://www.jetbrains.com/help/kotlin-multiplatform-dev/multiplatform-publish-libraries.html & complete all necessary steps.
The above article focuses on publishing to MavenCentral. But if you want to verify publishing from your local machine, you can follow below steps:
~/.gradle/gradle.properties(not to be confused with gradle.properties in project root):
signing.keyId=XXXXXXXX
signing.password=[key password]
signing.secretKeyRingFile=../XXXXXXXX.gpg
mavenCentralUsername=[generated username]
mavenCentralPassword=[generated password]
For GPG_KEY_CONTENTS secret(signing.secretKeyRingFile above), can get plain text version of gpg key using below commands.
# This will print the private GPG key in plain text.
gpg --export-secret-keys --armor <key id>
# this will copy it for pasting in github actions secrets.
gpg --export-secret-keys --armor <key id> | pbcopy
./gradlew :cmp-videoplayer:publishAndReleaseToMavenCentral --no-configuration-cache
Now check the deployments here https://central.sonatype.com/publishing/deployments
MIT License © 2025 aryapreetam and contributors. See LICENSE for details.
This template was built with inspiration and learnings from the excellent work of the Kotlin multiplatform community:
Project Setup: Initial project structure was created using Kotlin Multiplatform Web Wizard by terrakok
Inspirations:
Special thanks to:
This section lists planned improvements and features for the template. Contributions are welcome!
[ ] Add Detekt - Static code analysis for Kotlin
[ ] Add ktlint - Kotlin code formatter
[ ] Add Kover - Code coverage reporting
[ ] Add Dependabot - Automated dependency updates
[ ] Screenshot Testing - Visual regression testing
[ ] Performance Benchmarking - Track performance metrics
[ ] Multi-Module Support Guide
[ ] Compose Resources Guide
[ ] Video Tutorial
[ ] Blog Post / Article
[ ] Automated Changelog Generation
[ ] Version Bump Automation
[ ] Automated Screenshots
[ ] Linux Desktop Packaging
[ ] Additional Apple Platforms
[ ] Desktop Linux Native Build
[ ] Custom Domain Support
[ ] Improved Docsify Theme
[ ] Search Functionality
[ ] Vulnerability Scanning
[ ] SBOM Generation
[ ] Signed Releases
[ ] JitPack Support
[ ] NPM Package for Wasm
[ ] CocoaPods Support
If you have suggestions for improvements or want to contribute:
Priority: Items marked with 🔥 are high priority and would have the most impact.
See CONTRIBUTING.md for detailed contribution guidelines.