ExoPlayer get available audio tracks and switch between them
Asked Answered
A

1

8

I have an android application which streams videos with ExoPlayer. I want to add language support to the streams. What languages the stream will have, must be taken from the stream's metadata.

In ExoPlayer library I found the way to get list of the tracks from the stream by following:

player.getCurrentTrackGroups().get(i).getFormat(i) //player is SimpleExoPlayer class

but this give me kind of raw information, here is videos, audios, and other tracks that need to be labeled. printed formats looks like following:

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

I wonder if there is an easier way to get only audio tracks and their required information for switching between them for later.

My next problem is I don't know how to switch between the audio tracks. I searched and there is an answer accepted that this is done by the following code:

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

this code is taken from this answer. Problem is, that my SimpleExoPlayer class has not this function. I have exoplayer 2.8.2 and neither SimpleExoPlayer nor ExoPlayer class got that function. So i'm stuck there.
Another found answer was from DefaultTrackSelector class which has following face:

 trackSelector.setParameters( trackSelector.getParameters().buildUpon().setPreferredAudioLanguage("eng"));

this looks like simple and good way, But not all streams are labeled like that. many tracks has no string for language name. Only thing that they have different is ID string. And passing the id string does not work.

Alphonsealphonsine answered 9/5, 2019 at 15:22 Comment(2)
Any luck with this issue? Were you able to solve?Myrmeco
@negrotico19 I posted answer. see if it will be helpful. I will do some tests soon and I'll update the answer.Alphonsealphonsine
A
7

With the stream metadata I had, I don't think it was possible to get the language list. Now after fixing the metadata, it looks like this:

Format(1/21, null, application/id3, -1, null, [-1, -1, -1.0], [-1, -1])
Format(0, null, video/hevc, 2541422, null, [1920, 1080, -1.0], [-1, -1])
Format(1/8228, null, application/cea-608, -1, null, [-1, -1, -1.0], [-1, -1])
Format(1/21, null, application/id3, -1, null, [-1, -1, -1.0], [-1, -1])
Format(eng, null, audio/mpeg-L2, -1, eng, [-1, -1, -1.0], [2, 48000])
Format(1/21, null, application/id3, -1, null, [-1, -1, -1.0], [-1, -1])
Format(rus, null, audio/mpeg-L2, -1, rus, [-1, -1, -1.0], [2, 48000])

I wrote the code to get information from the metadata:

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));
   }
}

If metadata's sampleMimeType contains "audio" string I assume it's about audio. there can be many different types of audio.

Now about switching between the audio tracks:

trackSelector.setParameters( trackSelector.getParameters().buildUpon().setPreferredAudioLanguage("eng"));

this inside string should match .getFormat(0).language or .getFormat(0).id (I don't know exactly).

Alphonsealphonsine answered 22/8, 2019 at 8:29 Comment(4)
Was the above solution helpful, were you able to get the list of languages?Hochheimer
Yes with this solution I implemented audio language switches in my player.Alphonsealphonsine
Thank you for your kind reply, I tried the above code but didn't work for me, my HLS stream URL has audio tracks, I am getting feel that I am calling the above code from the incorrect place, right now I am calling right after initializing the ExoPlayer. Please let me know if I need to call it from anywhere else.Hochheimer
You should call this method when stream is ready to play. I'm calling this function in listener's onPlayerStateChanged function when playbackState == Player.STATE_READY. onPlayerStateChanged is already deprecated in newer versions so I think you can it in onPlaybackStateChanged when state == Player.STATE_READYAlphonsealphonsine

© 2022 - 2024 — McMap. All rights reserved.