Exoplayer 如何切换音轨

598 阅读2分钟

前提条件:

语言:Kotlin
Exoplayer版本:2.18.5

需求: 给定一个 MV 资源文件,这个 MV 的资源文件中有两个音轨,一个是原唱的音轨,一个是伴唱的音轨,如何实现在播放的时候,这两个音轨之间的互相切换呢?

Exoplayer 在各个版本设置的 API 还并不是相同的,仅限我当前的版本,设置的代码如下:

fun setAudioTracks(exoPlayer: ExoPlayer, isSoloMode: Boolean) {
    with(exoPlayer) {
      val audioTracks = getAudioTracks()
      val targetTrack = if (soloMode) audioTracks.firstOrNull() else audioTracks.lastOrNull()
      targetTrack?.let {
        trackSelectionParameters = trackSelectionParameters
          .buildUpon()
          .setOverrideForType(TrackSelectionOverride(it.trackGroup, it.trackIndex))
          .build()
      }
    }
  }


/**
 * get all audio tracks from exoplayer
 *
 */
fun ExoPlayer.getAudioTracks(): List<CbTrackFormat> {
  val totalTrackFormats = mutableListOf<CbTrackFormat>()
  for (i in 0 until currentTracks.groups.size) {
    val item = currentTracks.groups[i]
    for (j in 0 until item.length) {
      val trackFormat = item.getTrackFormat(j)
      totalTrackFormats.add(CbTrackFormat(trackFormat, item.mediaTrackGroup, j))
    }
  }
  val audioTracks = totalTrackFormats.filter {
    it.format.sampleMimeType?.startsWith("audio") == true
  }
  return audioTracks
}

data class CbTrackFormat(val format: Format, val trackGroup: TrackGroup, val trackIndex: Int)

如果需要在资源播放的时候就设置音轨,记得在播放器接收到 Player.STATE_READY 回调之后再进行设置即可,关于哪个音轨是伴奏哪个是原唱,需要和配置这个 MV 资源的人进行默认规定。

需求: 如果我给你两个 MP3 资源,一个是伴奏的 MP3 资源,一个是原唱的 MP3 资源,应该怎么切换呢? 这个需求主要是如何组装数据给到 Exoplayer, 把这两个 MP3 文件通过 MergingMediaSource 直接组装成一个资源给到播放器,然后调用上面的切换音轨的方法就可以做到。组装资源的代码如下:

fun mergeAudioSource(context: Context, mp3Source: String, musicSource: String): MediaSource {
    val dataSourceFactory = DefaultDataSource.Factory(context)
    // 此处后面有用
    val extractorsFactory = DefaultExtractorsFactory()
    val originalSongMediaSource = ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory).createMediaSource(MediaItem.fromUri(mp3Source))
    val accompanyMediaSource = ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory).createMediaSource(MediaItem.fromUri(musicSource))
    val mergedMediaSource = MergingMediaSource(originalSongMediaSource, accompanyMediaSource)
    return mergedMediaSource
}

-> Exoplayer#setMediaSource(mergedMediaSource) 即可.

即使做了上面所有的工作,并不是所有的资源都能切换原唱伴唱成功! 需要在调用这一行代码

extractorsFactory.setConstantBitrateSeekingEnabled(true)

具体原因也不知道,但是如果遇到切换音轨错误的话,设置一下这行代码看看是否有效果。