Search code examples
androidvideoandroid-mediaplayerhttp-live-streamingm3u8

select quality video on hls stream on android


The HLS protocol is based around the idea of a .m3u8 "Playlist" file containing a list of multiple version of the same content, encoded in different video/audio qualities.

The idea is to let the client player to automatically switch quality based on custom rules (bandwith, client video size, etc...).

Using the MediaPlayer class on android platform, I can stream hls content (for example this url).

How can I programmatically select which of the available levels the application should use, during the streaming?


Solution

  • May be late, but hope someone might find it useful.

    You can use ExoPlayer to do this.

    In your build.gradle:

    implementation 'com.google.android.exoplayer:exoplayer:2.9.1'
    

    In your layout.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_height="match_parent"
                android:layout_width="match_parent">
        <com.google.android.exoplayer2.ui.PlayerView
            android:layout_width="match_parent"
            android:layout_height="400dp"
            android:id="@+id/video_player"/>
        <Button android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/quality_lo"
            android:text="@string/quality_lo"
            android:layout_below="@id/video_player"/>
    
        <Button android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/quality_mi"
            android:text="@string/quality_mi"
            android:layout_below="@id/video_player"
            android:layout_toEndOf="@id/quality_lo"/>
    
        <Button android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/quality_hi"
            android:text="@string/quality_hi"
            android:layout_below="@id/video_player"
            android:layout_toEndOf="@id/quality_mi"/>
    </RelativeLayout>
    

    In your Activity

        int HI_BITRATE = 2097152;
        int MI_BITRATE = 1048576;
        int LO_BITRATE = 524288;
    
        PlayerView playerView = findViewById(R.id.video_player);
    
        DefaultTrackSelector trackSelector = new DefaultTrackSelector();
        DefaultTrackSelector.Parameters defaultTrackParam = trackSelector.buildUponParameters().build();
        trackSelector.setParameters(defaultTrackParam);
    
        SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(this, trackSelector);
    
        playerView.setPlayer(player);
    
        DefaultDataSourceFactory fac = new DefaultDataSourceFactory(this,
                Util.getUserAgent(this, getString(R.string.app_name)));
    
        HlsMediaSource videoSource = new HlsMediaSource.Factory(fac).createMediaSource(
                Uri.parse("http://192.168.1.104:9999/statics/videos/oceans/master.m3u8")
        );
    
        player.prepare(videoSource);
    
    
        findViewById(R.id.quality_lo).setOnClickListener(v -> {
            DefaultTrackSelector.Parameters parameters = trackSelector.buildUponParameters()
                    .setMaxVideoBitrate(LO_BITRATE)
                    .setForceHighestSupportedBitrate(true)
                    .build();
            trackSelector.setParameters(parameters);
        });
    
        findViewById(R.id.quality_mi).setOnClickListener(v -> {
            DefaultTrackSelector.Parameters parameters = trackSelector.buildUponParameters()
                    .setMaxVideoBitrate(MI_BITRATE)
                    .setForceHighestSupportedBitrate(true)
                    .build();
            trackSelector.setParameters(parameters);
        });
    
        findViewById(R.id.quality_hi).setOnClickListener(v -> {
            DefaultTrackSelector.Parameters parameters = trackSelector.buildUponParameters()
                    .setMaxVideoBitrate(HI_BITRATE)
                    .setForceHighestSupportedBitrate(true)
                    .build();
            trackSelector.setParameters(parameters);
        });
    

    You master m3u8 file should be like:

    #EXTM3U
    #EXT-X-STREAM-INF:BANDWIDTH=2097152,RESOLUTION=1080x450,CODECS="avc1.4d001e,mp4a.40.2"
    hi/hi.m3u8
    #EXT-X-STREAM-INF:BANDWIDTH=1048576,RESOLUTION=960x400,CODECS="avc1.4d001e,mp4a.40.2"
    mi/mi.m3u8
    #EXT-X-STREAM-INF:BANDWIDTH=524288,RESOLUTION=720x300,CODECS="avc1.4d001e,mp4a.40.2"
    lo/lo.m3u8
    

    Read https://google.github.io/ExoPlayer/guide.html for more information.