ExoPlayer 获取可用的音轨并在它们之间切换

oto*_*to 5 android audiotrack exoplayer

我有一个使用 ExoPlayer 流式传输视频的 android 应用程序。我想为流添加语言支持。流将使用什么语言,必须从流的元数据中获取。

在 ExoPlayer 库中,我找到了通过以下方式从流中获取曲目列表的方法:

player.getCurrentTrackGroups().get(i).getFormat(i) //player is SimpleExoPlayer class
Run Code Online (Sandbox Code Playgroud)

但这给了我一些原始信息,这是需要标记的视频、音频和其他曲目。打印格式如下所示:

格式(1/100, null, video/avc, -1, null, [1920, 1080, -1.0], [-1, -1])
格式(1/8292, null, application/cea-608, -1 , null, [-1, -1, -1.0], [-1, -1])
格式(1/200, null, audio/mpeg-L2, -1, , [-1, -1, -1.0] , [2, 48000])
格式(1/201, null, audio/mpeg-L2, -1, , [-1, -1, -1.0], [2, 48000])

我想知道是否有一种更简单的方法可以只获取音轨及其所需的信息,以便以后在它们之间切换。

我的下一个问题是我不知道如何在音轨之间切换。我搜索并接受了一个答案,这是通过以下代码完成的:

player.selectTrack(FullPlayer.TYPE_AUDIO, ExoPlayer.TRACK_DEFAULT);

Run Code Online (Sandbox Code Playgroud)

此代码取自答案。问题是,我的SimpleExoPlayer类没有这个功能。我有 exoplayer 2.8.2 并且SimpleExoPlayerExoPlayer类都没有这个功能。所以我被困在那里。
另一个找到的答案来自 DefaultTrackSelector 类,它具有以下内容:

 trackSelector.setParameters( trackSelector.getParameters().buildUpon().setPreferredAudioLanguage("eng"));
Run Code Online (Sandbox Code Playgroud)

这看起来简单而好方法,但并非所有流都被标记为这样。许多曲目没有语言名称字符串。他们唯一不同的是ID字符串。并且传递 id 字符串不起作用。

oto*_*to 7

根据我拥有的流元数据,我认为不可能获得语言列表。现在修复元数据后,它看起来像这样:

格式(1/21,空,应用程序/id3,-1,空,[-1,-1,-1.0],[-1,-1])
格式(0,空,视频/hevc,2541422,空, [1920, 1080, -1.0], [-1, -1])
格式(1/8228, null, application/cea-608, -1, null, [-1, -1, -1.0], [-1 , -1])
格式(1/21, null, application/id3, -1, null, [-1, -1, -1.0], [-1, -1])
格式(eng, null, 音频/mpeg -L2, -1, eng, [-1, -1, -1.0], [2, 48000])
格式(1/21, null, application/id3, -1, null, [-1, -1, - 1.0], [-1, -1])
格式(rus, null, 音频/mpeg-L2, -1, rus, [-1, -1, -1.0], [2, 48000])

我编写了从元数据中获取信息的代码:

for(int i = 0; i < player.getCurrentTrackGroups().length; i++){
   String format = player.getCurrentTrackGroups().get(i).getFormat(0).sampleMimeType;
   String lang = player.getCurrentTrackGroups().get(i).getFormat(0).language;
   String id = player.getCurrentTrackGroups().get(i).getFormat(0).id;

   System.out.println(player.getCurrentTrackGroups().get(i).getFormat(0));
   if(format.contains("audio") && id != null && lang != null){
      //System.out.println(lang + " " + id);
      audioLanguages.add(new Pair<>(id, lang));
   }
}
Run Code Online (Sandbox Code Playgroud)

如果元数据的sampleMimeType包含“音频”字符串,我认为它与音频有关。可以有许多不同类型的音频。

现在关于音轨之间的切换:

trackSelector.setParameters( trackSelector.getParameters().buildUpon().setPreferredAudioLanguage("eng"));
Run Code Online (Sandbox Code Playgroud)

这个内部字符串应该匹配.getFormat(0).languageor .getFormat(0).id(我不太清楚)。

  • 您应该在流准备好播放时调用此方法。当“playbackState == Player.STATE_READY”时,我在侦听器的“onPlayerStateChanged”函数中调用此函数。`onPlayerStateChanged` 在新版本中已经被弃用,所以我认为当 `state == Player.STATE_READY` 时你可以在 `onPlaybackStateChanged` 中使用它 (3认同)