Compose Multiplatform Media Player is a powerful media player library designed for Compose Multiplatform projects. It enables seamless video player, reels viewing, audio playing, YouTube video integration, video preview thumbnails and HLS m3u8 support on iOS, Android, and Desktop platforms. The library offers extensive customization options for various controls, making it flexible for different types of media applications.
π Enhanced Audio Player Flexibility!
- π MediaPlayerHost Integration: The AudioPlayerComposable now seamlessly integrates with MediaPlayerHost, decoupling playback logic from the built-in UI. This gives you full control to customize or replace the default UI while maintaining smooth audio playback.
- π Standalone Audio Player: The AudioPlayer is now independent, offering more flexibility for different use cases.
Cross-Platform Compatibility: Works seamlessly on iOS, Android, and Desktop platforms within Compose Multiplatform projects.
Video Player: Effortlessly play videos in your app with high performance and reliability.
HLS m3u8 Playback: Stream live and on-demand content using the HLS .m3u8 format.
YouTube Player: Integrate YouTube videos directly into your app, with full control over playback and video state management.
Reel Viewing: Enjoy reel viewing with support for horizontal and vertical scrolling.
Audio Player: Enjoy high-quality audio playback with customizable controls.
Video Preview: Display animated video previews for a more engaging experience.
Customizable Controls: Enable/disable pause/resume functionality and adjust the appearance and visibility of the seek bar, along with various control icons and colors.
Add the following dependency to your build.gradle.kts
file:
commonMain.dependencies {
implementation("network.chaintech:compose-multiplatform-media-player:1.0.31")
}
π‘ Note: For desktop video player, ensure VLC Player is installed, and for desktop YouTube support, Java must be installed on your system.
- mediaUrl (String): The URL of the media to be played.
- isPaused (Boolean): Sets the initial playback state. Defaults to false (play on load).
- isMuted (Boolean): Indicates whether the video is muted initially. Defaults to false.
- initialSpeed (PlayerSpeed): Sets the initial playback speed. Defaults to PlayerSpeed.X1.
- initialVideoFitMode (ScreenResize): Specifies the video resizing mode. Defaults to ScreenResize.FILL.
- isLooping (Boolean): Enables or disables looping. Defaults to true.
- startTimeInSeconds (Int?): Optionally specifies the start time (in seconds) for the video. Defaults to null.
- isFullScreen (Boolean): Enables or disables full screen. Defaults to false.
- isZoomEnabled (Boolean): Enables or disables zoom functionality. Defaults to true. (Note: Set isZoomEnabled to false when using a pager to prevent conflicts with scrolling.)
- loadUrl(mediaUrl: String): Updates the media URL to load a new media.
- play(): Resumes media playback.
- pause(): Pauses media playback.
- togglePlayPause(): Toggles between play and pause states.
- mute(): Mutes the video.
- unmute(): Unmutes the video.
- toggleMuteUnmute(): Toggles between muted and unmuted states.
- setSpeed(speed: PlayerSpeed): Adjusts the playback speed.
- seekTo(seconds: Int?): Seeks to a specific time in the media.
- setVideoFitMode(mode: ScreenResize): Updates the video resizing mode.
- setLooping(isLooping: Boolean): Enables or disables looping.
- toggleLoop(): Toggles loop state.
- setVolume(level: Float): Adjusts the volume. Value must be between 0.0 and 1.0.
- setFullScreen(isFullScreen: Boolean): Enables or disables full screen.
- toggleFullScreen(): Toggles full screen enable/disable states.
The MediaPlayerHost class manages internal state changes and triggers events via the onEvent callback. These events allow developers to monitor and respond to changes in the media player state:
Event | Description |
---|---|
PauseChange(isPaused: Boolean) | Triggered when the playback state changes (play or pause). |
MuteChange(isMuted: Boolean) | Triggered when the mute state changes (mute or unmute). |
BufferChange(isBuffering: Boolean) | Triggered when the buffering state changes (e.g., when buffering starts/stops). |
TotalTimeChange(totalTime: Int) | Triggered when the total duration of the video updates. |
CurrentTimeChange(currentTime: Int) | Triggered when the current playback position updates. |
MediaEnd | Triggered when the media playback completes. |
The MediaPlayerHost class provides an onError callback to handle various errors that may occur during media playback.
Error Type | Description |
---|---|
VlcNotFound | Triggered when the VLC library is not found, preventing playback in Desktop. |
InitializationError(details: String) | Occurs if the media player fails to initialize properly. |
PlaybackError(details: String) | Triggered when an error occurs during media playback |
ResourceError(details: String) | Occurs when the media resource is unavailable or cannot be loaded. |
val videoPlayerHost = MediaPlayerHost(
mediaUrl = "https://example.com/video.mp4",
isPaused = true,
isMuted = false,
initialSpeed = PlayerSpeed.X1,
initialVideoFitMode = ScreenResize.FIT,
isLooping = false,
startTimeInSeconds = 10,
isFullScreen = true
)
// Play the video
videoPlayerHost.play()
// Pause the video
videoPlayerHost.pause()
// Toggle mute
videoPlayerHost.toggleMuteUnmute()
// Seek to 30 seconds
videoPlayerHost.seekTo(30)
// Change playback speed to 1.5x
videoPlayerHost.setSpeed(PlayerSpeed.X1_5)
// Enable looping
videoPlayerHost.setLooping(true)
// Enable Full screen
videoPlayerHost.setFullScreen(true)
videoPlayerHost.onEvent = { event ->
when (event) {
is MediaPlayerEvent.MuteChange -> { println("Mute status changed: ${event.isMuted}") }
is MediaPlayerEvent.PauseChange -> { println("Pause status changed: ${event.isPaused}") }
is MediaPlayerEvent.BufferChange -> { println("Buffering status: ${event.isBuffering}") }
is MediaPlayerEvent.CurrentTimeChange -> { println("Current playback time: ${event.currentTime}s") }
is MediaPlayerEvent.TotalTimeChange -> { println("Video duration updated: ${event.totalTime}s") }
MediaPlayerEvent.MediaEnd -> { println("Video playback ended") }
}
}
videoPlayerHost.onError = { error ->
when(error) {
is MediaPlayerError.VlcNotFound -> { println("Error: VLC library not found. Please ensure VLC is installed.") }
is MediaPlayerError.InitializationError -> { println("Initialization Error: ${error.details}") }
is MediaPlayerError.PlaybackError -> { println("Playback Error: ${error.details}") }
is MediaPlayerError.ResourceError -> { println("Resource Error: ${error.details}") }
}
}
To play videos in your app, use the VideoPlayerComposable:
val playerHost = remember { MediaPlayerHost(mediaUrl = url) }
VideoPlayerComposable(
modifier = Modifier.fillMaxSize(),
playerHost = playerHost
)
π‘ Note: The VideoPlayerComposable supports both online and local video playback. You can provide a URL for a remote video or a local file path.
To display video preview thumbnails, use the VideoPreviewComposable:
VideoPreviewComposable(
url = videoUrl,
frameCount = 5,
contentScale = ContentScale.Crop
)
π‘ Note: The VideoPreviewComposable does not support local asset video in Android.
To play youtube videos in your app, use the YouTubePlayerComposable:
val playerHost = remember { MediaPlayerHost(mediaUrl = youtubeVideoId) }
YouTubePlayerComposable(
modifier = Modifier.fillMaxSize(),
playerHost = playerHost
)
π‘ Note: The YouTubePlayerComposable supports both YouTube video URLs and video IDs. It automatically extracts the video ID if a full URL is provided, ensuring seamless playback.
For reel viewing, utilize the ReelsPlayerComposable:
ReelsPlayerComposable(
modifier = Modifier.fillMaxSize(),
urls = videoUrlArray
)
To play audio in your app, use AudioPlayerComposable
for a built-in UI experience or AudioPlayer
for a fully customizable, independent player. π΅
val playerHost = remember { MediaPlayerHost(mediaUrl = url) }
AudioPlayerComposable(
modifier = Modifier,
audios = audioFilesArray,
playerHost = playerHost,
)
//Independent player
AudioPlayer(
playerHost = playerHost
)
π‘ Note: The AudioPlayerComposable supports both online and local audio playback. You can provide a URL for a remote audio file or a local file path.
You can customize various aspects of the media player:
modifier
: Modifies the layout and appearance of the video player and reel player.playerHost
: The VideoPlayerHost class manages internal state changes of video player.urls
: An array of URLs for the reel player, allowing playback of multiple reels.playerConfig
: You can configure various aspects of the video player appearance using the VideoPlayerConfig data class.
Property | Description |
---|---|
showControls | Hide/Show video player inbuilt controls. |
isPauseResumeEnabled | Enable or disable the pause/resume functionality. |
isSeekBarVisible | Toggle the visibility of the seek bar. |
isDurationVisible | Control the display of the playback time duration. |
seekBarThumbColor | Customize the color of the seek bar thumb. |
seekBarActiveTrackColor | Customize the color of the seek barβs active track, representing the portion of the media content that has already been played. |
seekBarInactiveTrackColor | Customize the color of the seek barβs inactive track, representing the remaining portion of the media content yet to be played. |
durationTextColor | Customize the color of the duration text displayed alongside the seek bar. |
durationTextStyle | Customize the text style of the duration text, including font size and weight. |
seekBarBottomPadding | Configure the bottom padding for the seek bar control, ensuring proper alignment within the UI layout. |
playIconResource & pauseIconResource | Customize the play and pause button icons. |
pauseResumeIconSize | Customize the size of the pause/resume icons. |
reelVerticalScrolling | Manage vertical and horizontal scrolling in reel viewing. |
isAutoHideControlEnabled & controlHideIntervalSeconds | Enable the automatic hiding of controls after a specified time interval (in seconds). |
isFastForwardBackwardEnabled | Enable or disable fast forward and backward controls. |
fastForwardBackwardIconSize | Customize the size of the fast forward/backward icons. |
fastForwardIconResource & fastBackwardIconResource | Customize the icons for fast forward and fast backward controls. |
fastForwardBackwardIntervalSeconds | Set the interval (in seconds) for fast forward and backward actions. |
isMuteControlEnabled | Enable or disable mute control functionality. |
unMuteIconResource & muteIconResource | Customize the icons for unmute and mute controls. |
topControlSize | Customize the size of the top control buttons. |
isSpeedControlEnabled | Enable or disable speed control functionality. |
speedIconResource | Customize the icon for speed control. |
isFullScreenEnabled | Enable or disable full-screen functionality. |
controlTopPadding | Configure the top padding for controls, ensuring proper alignment within the UI layout. |
isScreenLockEnabled | Enable or disable screen lock functionality. |
iconsTintColor | Customize the tint color of the control icons. |
isScreenResizeEnabled | Enable or disable screen resize (Fit/Fill) functionality. |
loadingIndicatorColor | Customize the color of the loading indicator. |
loaderView | Custom loader for showing loading state. |
isLiveStream | A boolean property that indicates whether the currently playing video is a live stream. |
audioPlayerConfig
: You can configure various aspects of the audio player appearance and behavior using the AudioPlayerConfig data class.
Property | Description |
---|---|
showControl | Toggle to show or hide the AudioPlayer UI for a customizable playback experience. |
isControlsVisible | Toggle the visibility of the player controls. |
backgroundColor | Customize the background color of the audio player. |
coverBackground | Customize the background color of the cover image. |
seekBarThumbColor | Customize the color of the seek bar thumb. |
seekBarActiveTrackColor | Customize the color of the seek barβs active track, representing the portion of the media content that has already been played. |
seekBarInactiveTrackColor | Customize the color of the seek barβs inactive track, representing the remaining portion of the media content yet to be played. |
fontColor | Customize the color of the text used in the player. |
durationTextStyle | Customize the text style of the duration text, including font size and weight. |
titleTextStyle | Customize the text style of the title text, including font size and weight. |
controlsBottomPadding | Configure the bottom padding for the controls, ensuring proper alignment within the UI layout. |
playIconResource & pauseIconResource | Customize the play and pause button icons. |
pauseResumeIconSize | Customize the size of the pause/resume icons. |
previousNextIconSize | Customize the size of the previous and next track icons. |
previousIconResource & nextIconResource | Customize the icons for the previous and next track controls. |
iconsTintColor | Customize the tint color of the control icons. |
loadingIndicatorColor | Customize the color of the loading indicator. |
shuffleOnIconResource & shuffleOffIconResource | Customize the icons for the shuffle control when enabled and disabled. |
advanceControlIconSize | Customize the size of the advance control icons (e.g., fast forward/backward). |
repeatOnIconResource & repeatOffIconResource | Customize the icons for the repeat control when enabled and disabled. |
val playerHost = remember { MediaPlayerHost(mediaUrl = videoUrl) }
VideoPlayerComposable(modifier = Modifier.fillMaxSize(),
playerHost = playerHost,
playerConfig = VideoPlayerConfig(
isPauseResumeEnabled = true,
isSeekBarVisible = true,
isDurationVisible = true,
seekBarThumbColor = Color.Red,
seekBarActiveTrackColor = Color.Red,
seekBarInactiveTrackColor = Color.White,
durationTextColor = Color.White,
seekBarBottomPadding = 10.dp,
pauseResumeIconSize = 40.dp,
isAutoHideControlEnabled = true,
controlHideIntervalSeconds = 5,
isFastForwardBackwardEnabled = true,
playIconResource = Res.drawable.icn_play,
pauseIconResource = Res.drawable.icn_pause,
)
)
VideoPreviewComposable(
url = videoUrl,
loadingIndicatorColor = Color.White,
frameCount = 5
)
val playerHost = remember { MediaPlayerHost(mediaUrl = "QFxN2oDKk0E") }
YouTubePlayerComposable(modifier = Modifier.fillMaxSize(),
playerHost = playerHost,
playerConfig = VideoPlayerConfig(
isPauseResumeEnabled = true,
isSeekBarVisible = true,
isDurationVisible = true,
seekBarThumbColor = Color.Red,
seekBarActiveTrackColor = Color.Red,
seekBarInactiveTrackColor = Color.White,
durationTextColor = Color.White,
seekBarBottomPadding = 10.dp,
pauseResumeIconSize = 40.dp,
isAutoHideControlEnabled = true,
controlHideIntervalSeconds = 5,
isFastForwardBackwardEnabled = true,
playIconResource = Res.drawable.icn_play,
pauseIconResource = Res.drawable.icn_pause,
)
)
ReelsPlayerComposable(modifier = Modifier.fillMaxSize(),
urls = videoUrlArray,
playerConfig = VideoPlayerConfig(
isPauseResumeEnabled = true,
isSeekBarVisible = false,
isDurationVisible = false,
isMuteControlEnabled = false,
isSpeedControlEnabled = false,
isFullScreenEnabled = false,
isScreenLockEnabled = false,
reelVerticalScrolling = true
)
)
val audioFilesArray = listOf(
AudioFile(
audioUrl = "https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/theme_01.mp3",
audioTitle = "Galaxy Invaders",
thumbnailUrl = "https://c.saavncdn.com/866/On-My-Way-English-2019-20190308195918-500x500.jpg"
),
AudioFile(
audioUrl = "https://codeskulptor-demos.commondatastorage.googleapis.com/pang/paza-moduless.mp3",
audioTitle = "Paza Moduless"
)
)
val playerHost = remember { MediaPlayerHost(mediaUrl = audioFilesArray.first().audioUrl) }
AudioPlayerComposable(
modifier = Modifier,
audios = audioFilesArray,
playerHost = playerHost,
audioPlayerConfig = AudioPlayerConfig(
isControlsVisible = true,
fontColor = Color.White,
iconsTintColor = Color.White
)
)
Format | Android | iOS | Desktop |
---|---|---|---|
MP4 | β | β | β |
MOV | β | β | β |
3GP | β | β | β |
AVI | β | β | β |
MKV | β | β | β |
WEBM | β | β | β |
MTS | β | β | β |
m3u8 | β | β | β |
MP3 | β | β | β |
FLAC | β | β | β |
WAV | β | β | β |
AAC | β | β | β |
AIF | β | β | β |
ALAC | β | β | β |
OGG | β | β | β |
YouTube | β | β | β |
For an in-depth guide and detailed explanation, check out our comprehensive Medium Blog Post.
We're committed to continuously improving and expanding the capabilities of our media player library. Here's a glimpse into our future plans:
- Picture-in-Picture (PiP) Mode
- Video Caching for iOS & Desktop
- WasmJs support
The demo project utilizes the following libraries:
SDP & SSP for Compose Multiplatform β Scalable size units for responsive UI
- sdp-ssp-compose-multiplatform β network.chaintech:sdp-ssp-compose-multiplatform
Connectivity Monitor β Seamless Network Monitoring for Compose Multiplatform
- compose-connectivity-monitor β network.chaintech:compose-connectivity-monitor
Voyager Navigation β Simple and scalable navigation for Compose Multiplatform
voyager-navigator
β cafe.adriel.voyager:voyager-navigatorvoyager-transitions
β cafe.adriel.voyager:voyager-transitionsvoyager-tab
β cafe.adriel.voyager:voyager-tab-navigator
Image Loader β Efficient image loading and caching
image-loader
β io.github.qdsfdhvh:image-loader
- π¦ Fixing iOS Duplicate Symbols in KMM: Exporting Multiple Modules as an XCFramework
- π Essential Libraries for Compose Multiplatform: Boost Your Android and iOS Development
Copyright 2023 Mobile Innovation Network
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.