I want to create a composable that can play a vide...
# compose
c
I want to create a composable that can play a video file in the same way a gif would "play". i.e. Auto play, no controls, on a loop. I got something working with ExoPlayer, but it's become a little too difficult to customize fully. (I can't get it to fill the entire screen and center crop, can't get the controls to hide if the user clicks on the video). What am I trying to do exactly? Replicate this kind of video playing in the background, similar to what spotify did a while back. Can anyone point me in the right direction? I want to bake the video file into the app. My video is only about 0.5MB large and it's what my designers want. But if anyone could point me in the right direction, it'd be much appreciated. Video attached:
a
You should be able to do that in Exoplayer. I fill up the screen for landscape in my case. You could also hide the controls
c
Thanks Allan, Do you use exoplayer with compose? I was using SImpleExoPlayer builder and I couldn't figure out how to hide controls or fill the screen so it crops the content depending on the device.
a
Yes
How about exoPlayerView.useController = false ?
Lemme check the code about filling
c
Yeah. I tried calling that with no luck. I'll paste my code in a sec...
Here's what I have that was adapted from https://itnext.io/playing-a-video-with-jetpack-compose-10a453ff956
Copy code
@Composable
fun VideoPlayer(sourceUrl: String = "<https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4>") {
    val local = LocalContext.current

    val exoPlayer = remember { SimpleExoPlayer.Builder(local).build() }

    LaunchedEffect(sourceUrl) {
        val dataSourceFactory: DataSource.Factory =
            DefaultDataSourceFactory(local, Util.getUserAgent(local, local.packageName))

        val source =
            ProgressiveMediaSource.Factory(dataSourceFactory)
                .createMediaSource(MediaItem.fromUri(Uri.parse(sourceUrl)))
        exoPlayer.setMediaSource(source)
        exoPlayer.prepare()
    }

    // Gateway to traditional Android Views
    AndroidView(
        factory = { context ->
            PlayerView(context).apply {
                player = exoPlayer
                exoPlayer.playWhenReady = true
            }
        })
}
No matter where I try the
useController
it is not recognized as an api.
a
Try
Copy code
view.resizeMode =  AspectRatioFrameLayout.RESIZE_MODE_ZOOM
or just try everything that fits your case 😄
for the cropping
n
and be careful with the SimpleExoPlayer class, usually those kind of classes are made for the most basic use case, like showing a video fully with the control. You should maybe look into another Exoplayer class But after looking at the doc I might be wrong, and maybe this is the only class available 😄
c
@allan.conda where do I write that line? I don't see anything that allows me to write
view
and then set resizeMode on it.
@nitrog42 I only worked with exoplayer for a single night, but yes it seems like the only thing available is the SimpleEP as EP is deprecated.
a
it’s the ExoPlayerView
c
That's apparently not available?
a
Ah, I was actually using StyledPlayerView it seems
c
Oh. Maybe I can use that?
Still no dice.
a
view not the player
c
Oh! Like this?
🎉 2
@allan.conda holy crap. This ended up working. Thank you sooooooooo much for helping me. Looks like the trick was indeed moving to the StyledPlayerView!
a
Glad it worked!
Also there’s an initialization time with a black screen so you might want to have a placeholder until it’s prepared
c
Hahaha. Yeah, trying to figure out how to get the black screen to be transparent. I have an image beneath it that I want to show.
@allan.conda another question. I'm trying to get a "placeholder" like you suggested. I have an image beneath the video, so I'm trying to set the video view to be transparent, but nothing works. Here is my code:
Copy code
StyledPlayerView(context).apply {
                player = exoPlayer
                exoPlayer.volume = 0f
                exoPlayer.playWhenReady = true
                resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM
                defaultArtwork = ColorDrawable(Color.TRANSPARENT)
                background = ColorDrawable(Color.TRANSPARENT)
                setBackgroundColor(Color.TRANSPARENT)
                setShutterBackgroundColor(Color.TRANSPARENT)
                videoSurfaceView?.setBackgroundColor(Color.TRANSPARENT)
            }
any ideas?
a
Why note put the image on top and crossfade when video is ready?
c
That's also a good idea which I tried, but I couldn't figure out how to tell when the video playback has started.
a
there’s a player.addListener
hide it when its ready
c
@allan.conda aha. Thanks again. I don't know how I missed that method. With your expierience with exoplayer, do you know the "right" method to override? I've tried three methods already, and implementing all of them still gave me the same black screen experience for the first 0.5 seconds or so.
Copy code
exoPlayer.addListener(
    object : Player.Listener {
        override fun onIsPlayingChanged(isPlaying: Boolean) {
// I have an event here that updates state of "isPlaying" but still no luck with this method
            super.onIsPlayingChanged(isPlaying)
        }
    })
a
My experience with ExoPlayer is like less than a week 😂
And apparently there is this function ``simpleExoPlayerView.setShutterBackgroundColor(Color.TRANSPARENT);`
c
My experience is ~1 day so you have me beat. But no worries. Thanks and I didn't mean to bother you. I'm just so close and I just can't figure out this last step. I have an image on top... that shows.. after like 0.5 seconds a black screen shows because onIsPlaying somehow is technically true, and so I go from my image, to black screen to video playing.
It's almost like what I actually want is to listen for playback location and only say isPlaying = true when video has been playing for 1 second or so. but that also seems hacky.
@allan.conda HOLD UP! I'm using this URL https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4 I think it IS BLACK for like 1 second lol
😅 1
Oh jeez. I'm an idiot. it was the video that was black. TIME FOR BED! Thank you so much @allan.conda I owe you a beer (or other beverage of your choice!)
a
Glad you’re making good progress
K 1