ExoPlayerでhlsを流してみる

まずは、codelabsからコードをダウンロードしてきます。

https://developer.android.com/codelabs/exoplayer-intro?hl=ja#0

このコードラボのサンプルだとmp4とDASHの形式しか扱わないので、コードの修正が必要になります。

まずは、exoplayer-codelab-04を有効化(インポート)するのがいいと思います。

app/build.gradleを下記のように変更します。

// ここだけ抜粋
dependencies {
    // Switch out the code lab step to jump to different points in the code lab
    implementation project(':exoplayer-codelab-04') // ←だけ変更
    implementation 'androidx.multidex:multidex:2.0.1'
}

また、hls用のライブラリを読み込まないといけないので、 exoplayer-codelab-04/build.gradle に下記のように追加します。

そしてこの辺りを

    private fun initializePlayer() {
        // ExoPlayer implements the Player interface
        player = ExoPlayer.Builder(this)
            .build()
            .also { exoPlayer ->
                viewBinding.videoView.player = exoPlayer
                // Update the track selection parameters to only pick standard definition tracks
                exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters
                        .buildUpon()
                        .setMaxVideoSizeSd()
                        .build()

                val mediaItem = MediaItem.Builder()
                    .setUri(getString(R.string.media_url_dash))
                    .setMimeType(MimeTypes.APPLICATION_MPD)
                    .build()
                exoPlayer.setMediaItems(listOf(mediaItem), mediaItemIndex, playbackPosition)
                exoPlayer.playWhenReady = playWhenReady
                exoPlayer.addListener(playbackStateListener)
                exoPlayer.prepare()
            }
    }

このように修正します

    private fun initializePlayer() {
        // ExoPlayer implements the Player interface
        player = ExoPlayer.Builder(this)
            .build()
            .also { exoPlayer ->
                viewBinding.videoView.player = exoPlayer
                // Update the track selection parameters to only pick standard definition tracks
                exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters
                        .buildUpon()
                        .setMaxVideoSizeSd()
                        .build()

                val mediaItem = MediaItem.Builder()
                    .setUri(getString(R.string.media_url_hls)) // 適当なhlsのurlを入手してください
                    .setMimeType(MimeTypes.APPLICATION_M3U8)
                    .build()
                exoPlayer.setMediaItem(mediaItem)
                exoPlayer.playWhenReady = playWhenReady
                exoPlayer.addListener(playbackStateListener)
                exoPlayer.prepare()
            }
    }

そして、playbackStateListenerの中身は、同じActivity内にこんなふうに定義しています。

private fun playbackStateListener() = object : Player.Listener {
    override fun onPlaybackStateChanged(playbackState: Int) {
        val stateString: String = when (playbackState) {
            ExoPlayer.STATE_IDLE -> "ExoPlayer.STATE_IDLE      -"
            ExoPlayer.STATE_BUFFERING -> "ExoPlayer.STATE_BUFFERING -"
            ExoPlayer.STATE_READY -> "ExoPlayer.STATE_READY     -"
            ExoPlayer.STATE_ENDED -> "ExoPlayer.STATE_ENDED     -"
            else -> "UNKNOWN_STATE             -"
        }
        Log.d(TAG, "changed state to $stateString")
    }

    // こっちだとhls(多分tsファイル)からメタデータが取れない
    override fun onMediaMetadataChanged(mediaMetadata: MediaMetadata) {
        mediaMetadata.description?.let {
            Log.d(TAG, "cmId: $it")
        }

        super.onMediaMetadataChanged(mediaMetadata)
    }

    // こっちだとhlsからメタデータが取得できる
    @androidx.media3.common.util.UnstableApi
    override fun onMetadata(metadata: Metadata) {
        Log.d(TAG, "metadata: $metadata")
        super.onMetadata(metadata)
    }
}

これは、hls(多分tsファイル)からメタデータを取得するのを今のプロジェクトで行なっていたので、 自分でも行なってみたかったためです。

メタデータはmp4などだと、曲のタイトルや、アーティスト情報にあたるものです。