CompositionPlayer: StuckPlayerException
@kggibson is already working on this.
Since Jan 20, 2026.
- Dominant language
- Java
- Stars
- 3k
- Forks
- 955
- Avg merge
- 12d 14h
- Merged PRs (30d)
- 2
Description
version ; 1.9.0 latest and last 1.9.0-rc-1
`//////CREATE-COMPOSITION//////
fun createComposition():Composition{
val editedMediaItemsList = mutableListOf()
filteredSelectionModels.forEachIndexed { index, mediaItem ->
log("Composition_LOG", "MEDIA->$index" + mediaItem.toString())
// Handle non-grid items
val selectionModel = mediaItem.clips?.first()?.file
selectionModel?.let { selectedFile ->
val durationSec = mediaItem.duration ?: 1.0
val imageDurationUs =
((durationSec * 1_000_000).toLong()).coerceAtLeast(100_000L)
val originalDurationUs = (selectedFile.uriDuration.times(1000000)).toLong()
val startTime = (selectedFile.uriStartTime * 1000L).toLong()
val clipDuration = (mediaItem.duration?.times(1000) ?: 1000).toLong()
val endTime = (startTime + clipDuration)
val filePath = selectedFile.trimPath ?: selectedFile.path
log(
"Composition_LOG",
"Composition->$index fileType:${selectedFile.fileType}, " +
"originalDur:${originalDurationUs}, " + "startTime:$startTime, " +
"clipDuration:${clipDuration}, endTime:${endTime},\n" +
"important videoSeqDuration:${videoSequenceDurationUs} "
)
val editedMediaItem = when (selectedFile.fileType) {
"Video" -> {
EditedMediaItem.Builder(
MediaItem.Builder().setUri(filePath).setClippingConfiguration(
ClippingConfiguration.Builder()
.setStartPositionMs(startTime).setEndPositionMs(endTime)
.build()
).build()
).apply {
setRemoveAudio(true)
setDurationUs(originalDurationUs.toLong())
setFrameRate(30)
setEffects(Effects(listOf(pitchChanger), listOf()))
}.build()
}
else -> {
EditedMediaItem.Builder(
MediaItem.Builder().setUri(filePath)
.setImageDurationMs((imageDurationUs / 1000)).build()
).apply {
setDurationUs(imageDurationUs)
setFrameRate(30)
setEffects(Effects(listOf(pitchChanger), listOf()))
}.build()
}
}
editedMediaItemsList.add(editedMediaItem)
videoSequenceDurationUs += clipDuration
}
}
// Create the final video sequences list
val videoImageSequences = mutableListOf()
// Create ONE main video sequence with all items
val mainVideoSequence =
EditedMediaItemSequence.Builder().addItems(editedMediaItemsList).build()
videoImageSequences.add(mainVideoSequence)
try {
val composition = Composition.Builder(videoImageSequences)
.setEffects(Effects(listOf(), videoEffects)).setTransmuxVideo(true).build()
compositionDeferred.complete(composition)
} catch (e: Exception) {
e.printStackTrace()
log("Composition_LOG", "composition is null with ${e.message}")
compositionDeferred.complete(null)
}
}
`
/////////// I'm creating composition with above code and playing it with compositionPlayer.
I've multiple success scenarios and then FAILURE with exception.
If I select one file witn 100ms results success in playing.
If I select two files with 100ms for each file it still plays the composition.
FAILURE:
When I include three files with 100ms for each it fails to play COMPOSITION.
Until unless I update first file of duration to atleast 300ms. same behavior for more entries.
//////////Here's my logs for Composition and CompositionPlayer:
`1- With only one File:
E previewComposition: creating new composition
Composition_LOG MEDIA->0start_time=0.0, end_time=0.1, duration=0.1, videoCount=1, uriTime=0.0, fileDur=3.0,)
Composition->0 fileType:Video, originalDur:3000000, startTime:0, clipDuration:100, endTime:100,important videoSeqDuration:0
Player ready: duration=100ms (0s), state=2, sequences=1
New composition player created successfully
2- With two Files:
E previewComposition: creating new composition
MEDIA->0 start_time=0.0, end_time=0.1, duration=0.1, videoCount=1, uriTime=0.0, fileDur=3.0,)
Composition->0 fileType:Video, originalDur:3000000, startTime:0, clipDuration:100, endTime:100, important videoSeqDuration:0
MEDIA->1 start_time=0.1, end_time=0.2, duration=0.1, videoCount=1, uriTime=0.0, fileDur=17.0,)
Composition->1 fileType:Video, originalDur:17000000, startTime:0, clipDuration:100, endTime:100, important videoSeqDuration:100
Player ready: duration=200ms (0s), state=2, sequences=1
New composition player created successfully
3-A With three Files (SUCCESS):
3-B With three Files (FAILURE):
E previewComposition: creating new composition
MEDIA->0start_time=0.0, end_time=0.1, duration=0.1, videoCount=1, uriTime=0.0, fileDur=3.0,)
Composition->0 fileType:Video, originalDur:3000000, startTime:0, clipDuration:100, endTime:100, important videoSeqDuration:0
MEDIA->1start_time=0.1, end_time=0.2, duration=0.1, videoCount=1, uriTime=0.0, fileDur=17.0,)
Composition->1 fileType:Video, originalDur:17000000, startTime:0, clipDuration:100, endTime:100, important videoSeqDuration:100
MEDIA->2start_time=0.2, end_time=5.333, duration=5.133, videoCount=1,uriTime=0.0, fileDur=5.133,)
Composition->2 fileType:Video, originalDur:5133000, startTime:0, clipDuration:5133, endTime:5133, important videoSeqDuration:200
Player ready: duration=5333ms (5s), state=2, sequences=1
New composition player created successfully
From Library::
CompositionPlayer-0
E playerFailed [eventTime=10.16, mediaPos=0.01, window=0, period=0, errorCode=ERROR_CODE_TIMEOUT (Ask Gemini)
androidx.media3.exoplayer.ExoPlaybackException: Unexpected runtime error
at androidx.media3.exoplayer.ExoPlayerImpl$ComponentListener.onStuckPlayerDetected(ExoPlayerImpl.java:3606)
at androidx.media3.common.util.StuckPlayerDetector$StuckPlayingDetector.update(StuckPlayerDetector.java:256)
at androidx.media3.common.util.StuckPlayerDetector.handleMessage(StuckPlayerDetector.java:130)
at androidx.media3.common.util.StuckPlayerDetector.$r8$lambda$O20OfWQe0IImnmxCKXMyVoyaxfk(Unknown Source:0)
at androidx.media3.common.util.StuckPlayerDetector$$ExternalSyntheticLambda0.handleMessage(D8$$SyntheticClass:0)
at android.os.Handler.dispatchMessage(Handler.java:128)
at android.os.Looper.dispatchMessage(Looper.java:333)
at android.os.Looper.loopOnce(Looper.java:263)
at android.os.Looper.loop(Looper.java:367)
at android.app.ActivityThread.main(ActivityThread.java:9287)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:566)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:929)
Caused by: androidx.media3.common.util.StuckPlayerException: Player stuck playing with no progress for 10000 ms
... 12 more
]
***More crashes when using all images files:
ExoPlayerImplInternal E Playback error
androidx.media3.exoplayer.ExoPlaybackException: Source error
at androidx.media3.exoplayer.ExoPlayerImplInternal.handleIoException(ExoPlayerImplInternal.java:937)
at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:907)
at android.os.Handler.dispatchMessage(Handler.java:128)
at android.os.Looper.dispatchMessage(Looper.java:333)
at android.os.Looper.loopOnce(Looper.java:263)
at android.os.Looper.loop(Looper.java:367)
at android.os.HandlerThread.run(HandlerThread.java:139)
Caused by: androidx.media3.exoplayer.source.UnrecognizedInputFormatException: None of the available extractors (JpegExtractor, FlvExtractor, FlacExtractor, WavExtractor, FragmentedMp4Extractor, Mp4Extractor, AmrExtractor, PsExtractor, OggExtractor, TsExtractor, MatroskaExtractor, AdtsExtractor, Ac3Extractor, Ac4Extractor, Mp3Extractor, AviExtractor, PngExtractor, WebpExtractor, BmpExtractor, HeifExtractor, AvifExtractor) could read the stream. {contentIsMalformed=false, dataType=1}
sniff failures: [NoDeclaredBrand, NoDeclaredBrand]
at androidx.media3.exoplayer.source.BundledExtractorsAdapter.init(BundledExtractorsAdapter.java:110)
at androidx.media3.exoplayer.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:1169)
at androidx.media3.exoplayer.upstream.Loader$LoadTask.run(Loader.java:453)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1154)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
at java.lang.Thread.run(Thread.java:1563)
MessageQueue W Handler (android.os.Handler) {792f255} sending message to a Handler on a dead thread (Ask Gemini)
java.lang.IllegalStateException: Handler (android.os.Handler) {792f255} sending message to a Handler on a dead thread
at android.os.MessageQueue.logDeadThread(MessageQueue.java:1452)
at android.os.MessageQueue.enqueueMessageLegacy(MessageQueue.java:1465)
at android.os.MessageQueue.enqueueMessage(MessageQueue.java:1539)
at android.os.Handler.enqueueMessage(Handler.java:829)
at android.os.Handler.sendMessageAtTime(Handler.java:771)
at android.os.Handler.sendMessageDelayed(Handler.java:741)
at android.os.Handler.post(Handler.java:461)
at androidx.media3.exoplayer.audio.AudioTrackAudioOutput.lambda$releaseAudioTrackAsync$1(AudioTrackAudioOutput.java:468)
at androidx.media3.exoplayer.audio.AudioTrackAudioOutput$$ExternalSyntheticLambda3.run(D8$$SyntheticClass:0)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:520)
at java.util.concurrent.FutureTask.run(FutureTask.java:317)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:348)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1154)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
at java.lang.Thread.run(Thread.java:1563)
From LOCAL:
E playerFailed [eventTime=10.18, mediaPos=0.01, window=0, errorCode=ERROR_CODE_TIMEOUT (Ask Gemini)
androidx.media3.common.PlaybackException: error from player 0
at androidx.media3.transformer.CompositionPlayer.maybeUpdatePlaybackError(CompositionPlayer.java:1721)
at androidx.media3.transformer.CompositionPlayer.access$2700(CompositionPlayer.java:149)
at androidx.media3.transformer.CompositionPlayer$PlayerListener.onPlayerError(CompositionPlayer.java:2036)
at androidx.media3.exoplayer.ExoPlayerImpl.lambda$updatePlaybackInfo$21(ExoPlayerImpl.java:2342)
at androidx.media3.exoplayer.ExoPlayerImpl$$ExternalSyntheticLambda34.invoke(D8$$SyntheticClass:0)
at androidx.media3.common.util.ListenerSet$ListenerHolder.invoke(ListenerSet.java:458)
at androidx.media3.common.util.ListenerSet.lambda$queueEvent$0(ListenerSet.java:326)
at androidx.media3.common.util.ListenerSet$$ExternalSyntheticLambda1.run(D8$$SyntheticClass:0)
at androidx.media3.common.util.ListenerSet.flushEvents(ListenerSet.java:350)
at androidx.media3.exoplayer.ExoPlayerImpl.updatePlaybackInfo(ExoPlayerImpl.java:2405)
at androidx.media3.exoplayer.ExoPlayerImpl.stopInternal(ExoPlayerImpl.java:2139)
at androidx.media3.exoplayer.ExoPlayerImpl.access$3500(ExoPlayerImpl.java:144)
at androidx.media3.exoplayer.ExoPlayerImpl$ComponentListener.onStuckPlayerDetected(ExoPlayerImpl.java:3605)
at androidx.media3.common.util.StuckPlayerDetector$StuckPlayingDetector.update(StuckPlayerDetector.java:256)
at androidx.media3.common.util.StuckPlayerDetector.handleMessage(StuckPlayerDetector.java:130)
at androidx.media3.common.util.StuckPlayerDetector.$r8$lambda$O20OfWQe0IImnmxCKXMyVoyaxfk(Unknown Source:0)
at androidx.media3.common.util.StuckPlayerDetector$$ExternalSyntheticLambda0.handleMessage(D8$$SyntheticClass:0)
at android.os.Handler.dispatchMessage(Handler.java:128)
at android.os.Looper.dispatchMessage(Looper.java:333)
at android.os.Looper.loopOnce(Looper.java:263)
at android.os.Looper.loop(Looper.java:367)
at android.app.ActivityThread.main(ActivityThread.java:9287)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:566)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:929)
Caused by: androidx.media3.exoplayer.ExoPlaybackException: Unexpected runtime error
at androidx.media3.exoplayer.ExoPlayerImpl$ComponentListener.onStuckPlayerDetected(ExoPlayerImpl.java:3606)
... 12 more
Caused by: androidx.media3.common.util.StuckPlayerException: Player stuck playing with no progress for 10000 ms
... 12 more
]
`
E Player timeout detected (likely due to short 100ms clips). Attempting restart...
`Final previewComposition Player:
fun previewComposition( composition: Composition, pauseCallback: () -> Unit){
try {
val player = CompositionPlayer.Builder(context).build()
compositionPlayer = player
playerView.setPlayer(player)
playerView.useController = false
playerView.setKeepContentOnPlayerReset(true)
playerView.resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FILL
// Duration will be logged after prepare() when it's actually available
player.addListener(object : Player.Listener {
override fun onPlayerError(error: PlaybackException) {
pauseCallback.invoke()
log(
"PLAYER_LOG",
"Preview error: code=${error.errorCode}, name=${error.errorCodeName}, " +
"msg=${error.message}, cause=${error.cause}"
)
when {
error.errorCode == PlaybackException.ERROR_CODE_TIMEOUT -> {
log("PLAYER_LOG", "Player timeout detected (likely due to short 100ms clips). Attempting restart...")
try {
} catch (e: Exception) {
log("PLAYER_LOG", "Failed to restart player after timeout: ${e.message}")
}
}
}
}
}
}catch ( e: StuckPlayerException){
log("Composition_LOG", "Player stuck: ${e.message}")
} catch (e: Exception) {
log("Composition_LOG", "Preview creation error: ${e.message}")
pauseCallback.invoke()
uiStateViewModel.isCreatingComposition.value = false
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.