user3671635
user3671635

Reputation: 317

How to change subtitles in VideoView

I have multiple languages for subtitles in separate files. I would like to change subtitles when watching a movie. What is the right way to change the subtitles using addSubtitleSource() method in android VideoView?

if (subtitle.equals("Language_1")){ //button "Language_1"
mVideoView.addSubtitleSource(source_1, MediaFormat.createSubtitleFormat("text/vtt", "en"));
}
if (subtitle.equals("Language2")){ //button "Language_2"
mVideoView.addSubtitleSource(source_2, MediaFormat.createSubtitleFormat("text/vtt", "en"));
}

If I stop and start video, then I can switch between subtitles with this code (probably because after restarting the video it has "forgotten" about added sub source). Is there a way to unload one subtitle source and add different subtitle source without reloading the video? I am thinking of a method like removeSubtitleSource() which doesn't exist.

EDIT: Maybe I can use CaptioningManger for this?

Upvotes: 3

Views: 2735

Answers (1)

Hugo Allexis Cardona
Hugo Allexis Cardona

Reputation: 1432

I know is late for your question but maybe the answer can help other people... I was just working on this recently and needed the same feature of changing displayed subtitles of VideView.

First, add the two subtitles (source_1 and source_2) when you initialize the VideoView.

Then, what you can do is, inside the onPrepared() listener of your VideoView object, you can iterate through the tracks available for the current playing video and, what I did, was save them into a map declared on your class:

The needed reference to the MediaPlayer attached to your videoView, the map for the available subtitle tracks and the current selected subtitle track are private class members declared on my fragment, the one that contains the VideoView:

private MediaPlayer mediaPlayer;
private HashMap<String, IndexedTrackInfo> availableSubtitleTracks = new HashMap();
private IndexedTrackInfo currentSubtitleTrack;

Contents of onPrepared listener

@Override
public void onPrepared(MediaPlayer mp) {
    Log.d(JGA,"onPrepared");
    loadingIndicator.setVisibility(View.GONE);
    videoView.start();
    controllerFragmentListener.notifyPlaying();
    isPlaying=true;

    if(mediaPlayer == null) {
        mediaPlayer = mp;
    }

    MediaPlayer.TrackInfo[] tracks = mp.getTrackInfo();
    Log.d(TAG, "onInfo: MediaPlayer.getTrackInfo()[" + tracks.length + "]");
    MediaPlayer.TrackInfo track;
    IndexedTrackInfo indexedTrackInfo = null;
    for (int i = 0; i < tracks.length; i++) {
        track = tracks[i];
        Log.d(TAG, "onInfo: track received@" + i + ": " + track.getTrackType() + " = " + track.toString());
        if (track.getTrackType() == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
            indexedTrackInfo = new IndexedTrackInfo(track, i);
            if(track.getFormat().containsKey(TRACK_SUBTITLE_IS_DEFAULT_KEY)) {
                Log.d(TAG, "onInfo: Subtitle track has '" + TRACK_SUBTITLE_IS_DEFAULT_KEY + "' with value = " + track.getFormat().getInteger(TRACK_SUBTITLE_IS_DEFAULT_KEY));
                if(track.getFormat().getInteger(TRACK_SUBTITLE_IS_DEFAULT_KEY) == 1) {
                    Log.d(TAG, "onInfo: This track set as default");
                    currentSubtitleTrack = indexedTrackInfo;
                }
            }
            availableSubtitleTracks.put(track.getLanguage(), indexedTrackInfo);
        }
    }
    if(currentSubtitleTrack == null && indexedTrackInfo != null) {
        currentSubtitleTrack = indexedTrackInfo;
        mediaPlayer.selectTrack(currentSubtitleTrack.getIndex());
        Log.d(TAG, "onInfo: There was no default sub track but there are tracks available... picking the last one as default [" + currentSubtitleTrack.getIndex() + "]");
    }
    controllerFragmentListener.updateSpinnerSubtitleTracks(availableSubtitleTracks);
    controllerFragmentListener.updateSpinnerCurrentSelection(currentSubtitleTrack.getTrackInfo().getLanguage());
}

And the custom POJO to asociate each track with its corresponding index in the TrackInfo of the mediaPlayer (IndexedTrackInfo.java):

public class IndexedTrackInfo {

    private MediaPlayer.TrackInfo trackInfo;
    private int index;

    public IndexedTrackInfo(MediaPlayer.TrackInfo trackInfo, int index) {
        this.trackInfo = trackInfo;
        this.index = index;
    }

    public MediaPlayer.TrackInfo getTrackInfo() {
        return trackInfo;
    }

    public int getIndex() {
        return index;
    }
}

At the end, what I did was having a Spinner to display the available subtitles to the user and change them according to it's "index".

That depends on your needs, but for showing/hidding/changing the current subtitle track, what you need to do is something like:

//To show the subtitles:
mediaPlayer.selectTrack(currentSubtitleTrack.getIndex());
//To hide the subtitles:
mediaPlayer.deselectTrack(currentSubtitleTrack.getIndex());
//To change the track (secondSourceSubtitleTrack is the object in the map corresponding to your other subtitle source):
currentSubtitleTrack = secondSourceSubtitleTrack;
mediaPlayer.selectTrack(currentSubtitleTrack.getIndex());

I hope this can help someone else... I was strugging with this for a long time... there seems to be not much documentation or examples about this yet...

Upvotes: 4

Related Questions